How to make object collision in "Update" function?

A homing projectile fired from a cannon chases the nearest object.
Rocket
In “update” a check occurs while the projectile is flying one condition when colliding with another. I looked at several examples, everywhere the collision is added to “create”, and then when opening the game the objects simply collide. I need to do a collision via “update” and check the collision via a condition. Now it looks like this for me:

function Update() {
	for (i = 0; i < missiles.length; i++) {
		if (this.CheckCollision(missile, target)) {
		} else {
		}
	}
}

How can I also do it only through Phaser 3.55?
Full code:

var target = null
var targetVY = 0
var gravity = 0.5
var floor = 385
var cannon = null
var missile = null
var missileOut = false
var targetX = 0
var targetY = 0
var distance = 0
var missiles = []
var ease = 10
var speed = 15

class GameScene extends Phaser.Scene {
	constructor() {
		super("gameScene")
	}

	preload() {
		this.load.setBaseURL("./assets/")
		this.load.image("sky", "sky.png")
		this.load.image("cannon1", "Cannon.png")
		this.load.image("missile1", "Missile.png")
		this.load.image("target1", "target.png")
	}

	create() {
		this.add.image(0, 0, "sky").setOrigin(0)
		this.targetgroup = this.add.group()
		this.targetgroup.enableBody = true
		this.unit1 = []

		for (var i = 0; i < 2; i++) {
			target = this.targetgroup.create(0, 0, "target1", "Target0000")

			target.x = Math.random() * 600
			target.y = 200
			target.r = 15
			this.unit1.push(target)
		}
		cannon = this.add.image(0, 0, "cannon1")

		missile = this.add.image(0, 0, "missile1")
		missile.r = 3
		missile.visible = false

		this.input.on("pointerdown", this.shoot, this)
	}

	shoot(scene, pointer) {
		missile = this.add.image(0, 0, "missile1")
		missile.r = 3
		missiles.push(missile)
		missileOut = true
		missile.x = cannon.x
		missile.y = cannon.y
		missile.angle = cannon.angle
	}

	distance2(obj1, obj2) {
		var dx = obj1.x - obj2.x
		var dy = obj1.y - obj2.y

		return dx * dx + dy * dy
	}

	CheckCollision(obj1, obj2) {
		var d2 = this.distance2(obj1, obj2)
		var dr = obj1.r + obj2.r
		return d2 < dr * dr
	}

	update() {
		var pointer = this.input.activePointer
		var x = pointer.x
		var y = pointer.y
		var mouseX = pointer.worldX
		var mouseY = pointer.worldY

		cannon.x = mouseX
		cannon.y = mouseY

		var i, j

		targetVY += gravity
		for (i = 0; i < this.unit1.length; i++) {
			targetX = this.unit1[i].x - missile.x
			targetY = this.unit1[i].y - missile.y

			var dist = Math.sqrt(targetX * targetX + targetY * targetY)

			if (i == 0 || dist < distance) {
				distance = dist
				target = this.unit1[i]
			}

			this.unit1[i].y += targetVY
			if (this.unit1[i].y > floor) this.unit1[i].y = floor
		}
		if (target.y >= floor) targetVY = -18
		if (!missileOut) {
			missile.x = cannon.x
			missile.y = cannon.y

			targetX = target.x - cannon.x
			targetY = target.y - cannon.y
			cannon.angle = (Math.atan2(targetY, targetX) * 180) / Math.PI
		} else {
			for (i = 0; i < missiles.length; i++) {
				missile = missiles[i]

				if (this.CheckCollision(missile, target)) {
					missile.destroy(true)
					missiles.splice(i, 1)
					if (missiles.length < 1) missileOut = false
					target.x = Math.random() * 600
				} else {
					targetX = target.x - missile.x
					targetY = target.y - missile.y
					var angle = (Math.atan2(targetY, targetX) * 180) / Math.PI
					if (Math.abs(angle - missile.angle) > 180) {
						if (angle > 0 && missile.angle < 0)
							missile.angle -= (360 - angle + missile.angle) / ease
						else if (missile.angle > 0 && angle < 0)
							missile.angle += (360 - angle + missile.angle) / ease
					} else if (angle < missile.angle)
						missile.angle -= Math.abs(missile.angle - angle) / ease
					else missile.angle += Math.abs(angle - missile.angle) / ease
					var vx = (speed * (90 - Math.abs(missile.angle))) / 90
					var vy
					if (missile.angle < 0) vy = -speed + Math.abs(vx)
					else vy = speed - Math.abs(vx)

					missile.x += vx
					missile.y += vy
				}
			}
		}
	}
}

const config = {
	width: 600,
	height: 400,
	physics: {
		default: "arcade",
		arcade: {
			gravity: { y: 500 },
			debug: false,
		},
	},

	scene: [GameScene],
}

const game = new Phaser.Game(config)

In your code, you’re spawning the projectile on a pointerdown event. Inside shoot(), you can add a timer event, like this:

this.time.addEvent({
	delay: 500,
	callback: function(){
		if(this.canSpawn) {
			this.spawn(screenMeta.spawners);
		}
	},
	callbackScope: this,
	loop: true
});

In my game, I spawn gems in random locations every half second until my scene ends. You could put your homing code inside the callback and run all your calculations in there.

https://newdocs.phaser.io/docs/3.55.2/Phaser.Time.TimerEvent

Also, another thing to note is the update method is already a loop. It’s an infinite loop that runs every frame. It’s usually a good idea to keep a for loop out of the update method because performance could become an issue. You could use the time and delta parameters if you need granular control over something every x number of frames (example below), but I usually use the update method to take care of the visual aspects of the game and move more complex logic into events. I have found that once you put a bunch of stuff in the update method, the game can start to lag really quickly.

update(time, delta) {
    // Move an object 100 pixels per second, regardless of the frame rate
    this.myObject.x += 100 * (delta / 1000);

    // Check if it's time to perform some action every second
    if (time > this.nextActionTime) {
        // Perform some action
        this.nextActionTime = time + 1000; // Schedule the next action in 1 second
    }
}

If you want to use Arcade Physics you’ll have to convert a lot of things. Here’s a start.

function create() {
  this.targetgroup = this.physics.add.group();

  for (var i = 0; i < 2; i++) {
    target = this.targetgroup
      .create(Math.random() * 600, 200, 'target1', 'Target0000')
      .setCircle(15);
  }

  cannon = this.add.image(0, 0, 'cannon1');

  this.missilegroup = this.physics.add.group();

  missile = this.missilegroup.create(0, 0, 'missile1').setCircle(3);
  missile.visible = false;
}

function update() {
  var missiles = this.missilegroup.getChildren();
  var targets = this.targetgroup.getChildren();

  for (var m = 0; m < missiles.length; m++) {
    var missile = missiles[m];

    for (var t = 0; t < targets.length; t++) {
      var target = targets[t];

      if (this.physics.overlap(missile, target)) {
        missile.destroy();
        target.destroy();
      } else {
        //
      }
    }
  }
}

Add debug: true to the physics config.

See the examples for velocity and rotation.

1 Like

To make a projectile collide with a target in “update”

“if (this.physics.overlap(missile, target))”

I added “physics (this.targetgroup = this.physics.add.group(); and missile = this.physics.add.image(0, 0, ‘missile1’);)” to “target” and “missile” when creating them.

As a result, the entire mechanics of the game break down for me. Gravity acts.

If you compare the gif from the first post and here it is:
rocket
How to fix it?

Here is the code:

<!DOCTYPE html>
<html lang="en" >

<head>
  <meta charset="UTF-8">
  


  <title>Rocket guidance system</title>

</head>

<body translate="no">
  <script src='./Vector2.js'></script>
  <script src='https://cdnjs.cloudflare.com/ajax/libs/phaser/3.55.2/phaser.min.js'></script>
      <script>

var target = null;
var targetVY = 0
var gravity = 0.5;
var floor = 385;
var cannon = null;
var missile = null;
var missileOut = false;
var targetX = 0;
var targetY = 0;
var distance = 0;
var missiles = [];
var ease = 10;
var speed = 15;


class GameScene extends Phaser.Scene {
  constructor() {
    super('gameScene');

  }

  preload() {

    this.load.setBaseURL('./assets/');
    this.load.image('sky', 'sky.png');
    this.load.image('cannon1', 'Cannon.png');
    this.load.image('missile1', 'Missile.png');
    this.load.image('target1', 'target.png');
 }

  create() {
     this.add.image(0, 0, 'sky').setOrigin(0);
     this.targetgroup = this.physics.add.group();
     this.targetgroup.enableBody = true;
     this.unit1 = [];
     
    for(var i=0; i<2; i++) {
        target = this.targetgroup.create(0, 0, 'target1', 'Target0000');
       
        target.x = Math.random() * 600;
				target.y = 200;
				target.r = 15;
        this.unit1.push(target);
        
        
    }
     cannon = this.add.image(0, 0, 'cannon1');
     
     missile = this.physics.add.image(0, 0, 'missile1');
     missile.r = 3;
     missile.visible = false;
     
     this.input.on('pointerdown',this.shoot,this)
   

  }
  
  shoot(scene,pointer){   
      missile = this.physics.add.image(0, 0, 'missile1');
      missile.r = 3;
      missiles.push(missile);
      missileOut = true;
      missile.x = cannon.x;
			missile.y = cannon.y;
			missile.angle = cannon.angle;
  }
  
  
  distance2(obj1,obj2) {
		var dx = obj1.x - obj2.x;
		var dy = obj1.y - obj2.y;
		
		return dx*dx + dy*dy;
  }
  
  CheckCollision(obj1,obj2) {
		var d2 = this.distance2(obj1,obj2); 
		var dr = obj1.r + obj2.r; 
		return (d2 < dr*dr); 
  }

  update() {
    var pointer = this.input.activePointer;
    var x = pointer.x;
    var y = pointer.y;
    var mouseX = pointer.worldX;
    var mouseY = pointer.worldY;
    
    cannon.x=mouseX;
    cannon.y=mouseY;
   
    var i,j;
   
   targetVY += gravity;
   for(i = 0; i < this.unit1.length; i++)
    {
       
        targetX = this.unit1[i].x - missile.x;
				targetY = this.unit1[i].y - missile.y;
				
				var dist = Math.sqrt(targetX * targetX + targetY * targetY);
				
				if (i == 0 || dist < distance)
				{
					distance = dist;
					target = this.unit1[i];
				}
        
        this.unit1[i].y += targetVY;
        if (this.unit1[i].y > floor)
					this.unit1[i].y = floor;
    }
    if (target.y >= floor)
				targetVY = -18;
    if (!missileOut)
		{
        
        missile.x = cannon.x;
				missile.y = cannon.y;
				
        targetX = target.x - cannon.x;
				targetY = target.y - cannon.y;
				cannon.angle = Math.atan2(targetY, targetX) * 180 / Math.PI;
				
			 
		}
		else
		{
      for (i = 0; i < missiles.length; i++)
			{
			  
			
				missile = missiles[i];
				
				if (this.physics.overlap(missile, target)) {
				 
          missile.destroy();
          missiles.splice(i, 1);
          if (missiles.length < 1)
							missileOut = false;
					target.x = Math.random() * 600;
        }
				else
				{
          targetX = target.x - missile.x;
          targetY = target.y - missile.y;
          var angle = Math.atan2(targetY, targetX) * 180 / Math.PI;
          if (Math.abs(angle - missile.angle) > 180)
          { 
                if (angle > 0 && missile.angle < 0)
                  missile.angle -= (360 - angle + missile.angle) / ease;
                else if (missile.angle > 0 && angle < 0)
                  missile.angle += (360 - angle + missile.angle) / ease;
          }
          else if (angle < missile.angle)
              missile.angle -= Math.abs(missile.angle - angle) / ease;
          else
              missile.angle += Math.abs(angle - missile.angle) / ease;
          var vx = speed * (90 - Math.abs(missile.angle)) / 90;
          var vy;
          if (missile.angle < 0)
              vy = -speed + Math.abs(vx);
           else
              vy = speed - Math.abs(vx);
              
           missile.x += vx;
           missile.y += vy;
				 }
			}
		}
  }
}





const config = {
  width: 600,
  height: 400,
  physics: {
    default: 'arcade',
    arcade: {
      gravity: { y: 500 },
      debug: false } },


  scene: [GameScene] };


const game = new Phaser.Game(config);

    </script>

</body>

</html>

Remove this or change it to 0 if you don’t want world gravity.

1 Like