Collisions and Explosions
We have a lot of things moving around the screen now but at the moment everything simply passes right through each other. Clearly, if we’re going to make this into a game - we’ll need to make some of those things do something when they collide.
Trying to determine whether two objects collide in a game can be a reasonably complex problem to solve. It’s not too hard to solve with two objects, but if you have 200 objects in your game you don’t want to spend the majority of the time each frame just checking 200x199 (almost 40,000) combinations of objects in pairs to see if they collide.
Fortunately, Phaser comes with a complete 2D physics engine which allows you to place objects into a 2D world and give them acceleration or velocity to have them move. Actually, Phaser comes with 3 different physics systems - some more complex but able to produce more realistic physics. As we’re making an Arcade game however, and mostly just want to figure out if two objects are overlapping or not at this point - we will use the ARCADE physics system. This one is pretty simple, and favours more “fun” physics over super-realistic physics. Perfect for our game!
Task Definition
The overall steps for solving this task are as follows;
- Enable the physics system and ensure you’ve added your entities to it (you’ve already done this)!
- Setup a function in your game state object that will be called whenever a bullet and an asteroid collide. To start with, this function can just print console.log(“COLLISION”) to the console to ensure it’s working properly.
- Have the game check for collisions between bullets and asteroids.
- Update your collision function to mark both the asteroid and the bullet as “ready to be destroyed”.
Note It’s important to note that you cannot use the destroy() method in the callback function and should set sprite.pendingDestroy = true; instead - which will cause the sprite to be destroyed at the end of the frame.
Hints
The following Phaser function will prove helpful in your task of adding collisions to the game;
game.physics.arcade.collide([spriteOrArrayOfSprites], [spriteOrArrayOfSprites], [callbackFunction], null, this)
This method will check for collisions between two sprites or groups of sprites and will call the given “callbackFunction” if any two of those objects are touching. Note. You need to pass “null” as the 4th parameter and “this” as the last parameter in order for Phaser to know which object the callback belongs too.
Note It’s important to note that you cannot use the destroy() method in the callback function and should set sprite.pendingDestroy = true; instead - which will cause the sprite to be destroyed at the end of the frame.
Task Breakdown
1. Create the callback function
Create a function called onAsteroidBulletCollision(asteroid, bullet) on your main game state object. This function is going to be called by Phaser when it detects that an asteroid and bullet have collided. Initially, we will just have our function show a console message so that we know that our collision function is being called.
mainGameState.onAsteroidBulletCollision = function(asteroid, bullet) {
console.log("COLLISION!");
}Note. This callback function will be called by phaser whenever two objects collide. The two objects that do collide will be given as paramters to the function as asteroid and bullet.
2. Check for collisions
Now that we have a function to call whenever an asteroid collides with a bullet we’re able to ask Phaser to check for collisions in our update loop. We can ask Phaser to check for collisions anywhere in our update loop by using the following function;
game.physics.arcade.collide([spriteOrArrayOfSprites], [spriteOrArrayOfSprites], [functionToCall], null, this);This function takes the following parameters; parameters 1 and 2 are the two objects that phaser will check to see if they collide. Fortunately, you can also pass an array of objects here too - so we should pass our array of asteroids and our array of bullets. Important These should be in the same order that you have listed the items in the callback function (ie. If you expect the first argument in your callback to be an asteroid, the first argument here should be asteroids). The third parameter is the function that will be called every time phaser finds that two of these objects collide. The fourth parameter is another type of callback function that we’re not interested in using right now. Finally, you must pass this as the last parameter so that Phaser knows which game state the function belongs to.
game.physics.arcade.collide(this.asteroids, this.playerBullets, mainGameState.onAsteroidBulletCollision, null, this);3. Destroy the Asteroid and Bullet!
Now that we know that our collisions are being detected, we should make the function destroy the objects that collided. Note. In this callback function we should not call the destroy() function as it might cause our game to crash. Instead, we should set the property object.pendingDestroy = true; to true. Setting this property to true will cause Phaser to destroy the object later in the frame, but not immediately - as the Physics system might still need the object for a little while.
Note. It’s also important to note that we don’t know at this point what object1 and object2 are. We know that one is an asteroid and one is a bullet, but we do not know which is which. Unfortunately, it’s kind of random. However, for now we just want to destroy both objects - so that’s not a problem in this case.
mainGameState.onAsteroidBulletCollision = function(object1, object2) {
object1.pendingDestroy = true;
object2.pendingDestroy = true;
}Sample Solution
If you need a reference solution to base your own from, then you can see all of the added code for this task here;
mainGameState.update = function() {
game.physics.arcade.collide(this.asteroids, this.playerBullets, onAsteroidBulletCollision, this);
}
mainGameState.onAsteroidBulletCollision = function(object1, object2) {
object1.pendingDestroy = true;
object2.pendingDestroy = true;
}