This is my first Phaser 3 program. I can’t figure out why the collisions between the characters spawned and the bullets aren’t consistently detected. Sometimes bullets pass through characters with no collision. How can I detect collisions between spawned characters and bullets consistently?
Press ‘W’ to spawn characters.
<!DOCTYPE html>
<head>
<title>Gauging Difficulty for initial Game Design</title>
<script src="/assets/phaser-arcade-physics.min.js"></script>
</head>
<body style="text-align: center;">
<script>
var config = {
type: Phaser.WEBGL,
width: 1000,
height: 1000,
physics: {
default: 'arcade',
arcade: {
gravity: { y: 0 },
debug: true,
}
},
scene: {
preload: preload,
create: create,
update: update,
extend: {
player: null,
healthpoints: null,
reticle: null,
moveKeys: null,
playerBullets: null,
zombies: null,
time: 0,
spawnPoints: null,
spawnKey: null,
gun_cooldown: null,
}
}
};
function preload ()
{
var d = new Date();
var n = d.getTime();
gun_cooldown = n;
// Load in images and sprites
this.load.spritesheet('player_handgun', 'assets/character.png',
{ frameWidth: 66, frameHeight: 60 }
); // Made by tokkatrain: https://tokkatrain.itch.io/top-down-basic-set
this.load.image('bullet', 'assets/bullet.png');
this.load.image('target', 'assets/reticle.png');
this.load.image('background', 'assets/background.png');
}
var game = new Phaser.Game(config);
var Bullet = new Phaser.Class({
Extends: Phaser.GameObjects.Image,
initialize:
// Bullet Constructor
function Bullet (scene)
{
Phaser.GameObjects.Image.call(this, scene, 0, 0, 'bullet');
this.speed = 1;
this.born = 0;
this.direction = 0;
this.xSpeed = 0;
this.ySpeed = 0;
this.setSize(20, 20, true);
},
// Fires a bullet from the player to the reticle
fire: function (shooter, target)
{
this.setPosition(shooter.x, shooter.y); // Initial position
this.direction = Math.atan( (target.x-this.x) / (target.y-this.y));
// Calculate X and y velocity of bullet to moves it from shooter to target
if (target.y >= this.y)
{
this.xSpeed = this.speed*Math.sin(this.direction);
this.ySpeed = this.speed*Math.cos(this.direction);
}
else
{
this.xSpeed = -this.speed*Math.sin(this.direction);
this.ySpeed = -this.speed*Math.cos(this.direction);
}
this.rotation = shooter.rotation; // angle bullet with shooters rotation
this.born = 0; // Time since new bullet spawned
},
// Updates the position of the bullet each cycle
update: function (time, delta)
{
this.x += this.xSpeed * delta;
this.y += this.ySpeed * delta;
this.born += delta;
if (this.born > 1800)
{
this.setActive(false);
this.setVisible(false);
}
}
});
function hitzombie(bullet, zombiehit)
{
bullet.destroy();
zombiehit.destroy();
console.log("zombieHit");
}
function create ()
{
spawnKey = 0;
this.physics.world.setBounds(0, 0, 1000, 1000);
var circle = new Phaser.Geom.Circle(450, 250, 10);
var graphics = this.add.graphics({ lineStyle: { color: 0x00ff00 } });
graphics.strokeCircleShape(circle);
spawnPoints = [];
for(var i = 0; i < 16; i++)
{
var angle = i / 16 * Phaser.Math.PI2;
var xOffset = Math.cos(angle) * 100;
var yOffset = Math.sin(angle) * 100;
//turn spawn point into 2d array
Phaser.Geom.Circle.Offset(circle, xOffset, yOffset);
graphics.strokeCircleShape(circle);
spawnPoints[i] = [];
spawnPoints[i][0] = xOffset*2.8+500;
spawnPoints[i][1] = yOffset*2.8+500;
}
/* spawnPoints.forEach(function(element) {
console.log(element);
});*/
playerBullets = this.physics.add.group({ classType: Bullet, runChildUpdate: true });
zombies = this.physics.add.group();
//this.physics.add.collider(zombies, playerBullets);
//new Collider(world, overlapOnly, object1, object2, collideCallback, processCallback, callbackContext)
this.physics.add.collider(playerBullets, zombies, hitzombie, null, this);
player = this.physics.add.sprite(500, 500, 'player_handgun');
player.setOrigin(0.5, 0.5).setDisplaySize(60, 60).setCollideWorldBounds(true).setDrag(500, 500);
reticle = this.physics.add.sprite(800, 700, 'target');
// Pointer lock will only work after mousedown
game.canvas.addEventListener('mousedown', function () {
game.input.mouse.requestPointerLock();
});
// Exit pointer lock when Q or escape (by default) is pressed.
this.input.keyboard.on('keydown_Q', function (event) {
if (game.input.mouse.locked)
game.input.mouse.releasePointerLock();
}, 0, this);
// Move reticle upon locked pointer move
this.input.on('pointermove', function (pointer) {
if (this.input.mouse.locked)
{
reticle.x += pointer.movementX;
reticle.y += pointer.movementY;
}
}, this);
// Fires bullet from player on left click of mouse
this.input.on('pointerdown', function (pointer, time, lastFired) {
if (player.active === false)
return;
// Get bullet from bullets group
var bullet = playerBullets.get().setActive(true).setVisible(true);
if (bullet)
{
bullet.fire(player, reticle);
this.physics.add.collider(zombies, bullet, hitzombie);
}
}, this);
// Enables movement of player with WASD keys
this.input.keyboard.on('keydown_W', function (event) {
//enemyHit.health = enemyHit.health - 1;
//console.log("Enemy hp: ", enemyHit.health);
//var x = (player.x < 400) ? Phaser.Math.Between(400, 800) : Phaser.Math.Between(0, 400);
if(spawnKey>=16)
{
spawnKey=0;
}
var zombie = zombies.create(spawnPoints[spawnKey][0], spawnPoints[spawnKey++][1], 'player_handgun');
zombie.setBounce(1);
zombie.setCollideWorldBounds(true);
zombie.setVelocity(Phaser.Math.Between(-200, 200), 20);
zombie.allowGravity = false;
//spawnPoints.forEach(function(element) {
console.log(spawnKey);
//});
});
}
function getClosestEnemy() {
var zombieUnits = zombies.getChildren();
if(zombieUnits.length === 0)
return false;
var closest_zombie = 0;
var cur_distance = zombieUnits[0].active && Phaser.Math.Distance.Between(player.x, player.y, zombieUnits[0].x, zombieUnits[0].y)
var min_distance = cur_distance;
for(var i = 0; i < zombieUnits.length; i++) {
cur_distance = zombieUnits[i].active && Phaser.Math.Distance.Between(player.x, player.y, zombieUnits[i].x, zombieUnits[i].y)
if (cur_distance < min_distance)
{
min_distance = cur_distance;
closest_zombie = i;
}
}
return zombieUnits[closest_zombie];
}
function update (time, delta)
{
var target = getClosestEnemy();
var rotate_to = Phaser.Math.Angle.Between(player.x, player.y, target.x, target.y);
//target.body.debugBodyColor = target.body.touching.none ? 0x0099ff : 0xff9900;
if(player.rotation < rotate_to)
player.rotation += .2;
if(player.rotation > rotate_to)
player.rotation -= .2;
if(player.rotation - rotate_to < .2)
{
var d = new Date();
var now = d.getTime();
if (now-gun_cooldown > 500)
{
gun_cooldown = now;
var bullet = playerBullets.get().setActive(true).setVisible(true);
if (bullet)
{
bullet.fire(player, target);
this.physics.add.collider(zombies, bullet, hitzombie);
}
}
}
//var timer = this.time.addEvent({ delay: 10, callback: aimandshoot, callbackScope: this });
// Rotates player to face towards reticle
//player.rotation = Phaser.Math.Angle.Between(player.x, player.y, reticle.x, reticle.y);
//console.log(getClosestEnemy().x);
/*for (var j=10; j--; j>0)
{
enemy[j].rotation = Phaser.Math.Angle.Between(enemy[j].x, enemy[j].y, player.x, player.y);
enemyFire(enemy[j], player, time+(Math.floor(Math.random() * 1000) + 1), this);
if(enemy[j].x < player.x)
enemy[j].body.velocity.x = 50;
if(enemy[j].x > player.x)
enemy[j].body.velocity.x = -50;
if(enemy[j].y < player.y)
enemy[j].body.velocity.y = 50;
if(enemy[j].y > player.y)
enemy[j].body.velocity.y = -50;
}*/
// Rotates enemy to face towards player
//zombies.rotation = Phaser.Math.Angle.Between(enemy.x, enemy.y, player.x, player.y);
//Make reticle move with player
//reticle.body.velocity.x = player.body.velocity.x;
//reticle.body.velocity.y = player.body.velocity.y;
// Constrain velocity of player
//constrainVelocity(player, 500);
// Constrain position of constrainReticle
//constrainReticle(reticle);
// Make enemy fire
//enemyFire(enemy, player, time, this);
}
</script>
</body>
</html>