Collision detection
You now know how to make a huge variety of graphics objects, but what can you do with them? A fun thing to do is to build a simple collision detection system. You can use a custom function called hitTestRectangle
that checks whether any two rectangular Pixi sprites are touching.
hitTestRectangle(spriteOne, spriteTwo)
if they overlap, hitTestRectangle
will return true
. You can use hitTestRectangle
with an if
statement to check for a collision between two sprites like this:
if (hitTestRectangle(cat, box)) {
//There's a collision
} else {
//There's no collision
}
As you’ll see, hitTestRectangle
is the front door into the vast universe of game design.
Run the collisionDetection.html
file in the examples
folder for a working example of how to use hitTestRectangle
. Use the arrow keys to move the cat. If the cat hits the box, the box becomes red and “Hit!” is displayed by the text object.
You’ve already seen all the code that creates all these elements, as well as the keyboard control system that makes the cat move. The only new thing is the way hitTestRectangle
is used inside the play
function to check for a collision.
function play(delta) {
//use the cat's velocity to make it move
cat.x += cat.vx;
cat.y += cat.vy;
//check for a collision between the cat and the box
if (hitTestRectangle(cat, box)) {
//if there's a collision, change the message text
//and tint the box red
message.text = "hit!";
box.tint = 0xff3300;
} else {
//if there's no collision, reset the message
//text and the box's color
message.text = "No collision...";
box.tint = 0xccff99;
}
}
Because the play
function is being called by the game loop 60 times per second, this if
statement is constantly checking for a collision between the cat and the box. If hitTestRectangle
is true
, the text message
object uses text
to display “Hit”:
message.text = "Hit!";
The color of the box is then changed from green to red by setting the box’s tint
property to the hexadecimal red value.
box.tint = 0xff3300;
If there’s no collision, the message and box are maintained in their original states:
message.text = "No collision...";
box.tint = 0xccff99;
This code is pretty simple, but suddenly you’ve created an interactive world that seems to be completely alive. It’s almost like magic! And, perhaps surprisingly, you now have all the skills you need to start making games with Pixi!
The hitTestRectangle function
But what about the hitTestRectangle
function? What does it do, and how does it work? The details of how collision detection algorithms like this work is a little bit outside the scope of this tutorial. (If you really want to know, you can find out how this book.) The most important thing is that you know how to use it. But, just for your reference, and in case you’re curious, here’s the complete hitTestRectangle
function definition. Can you figure out from the comments what it’s doing?
function hitTestRectangle(r1, r2) {
//Define the variables we'll need to calculate
let hit, combinedHalfWidths, combinedHalfHeights, vx, vy;
//hit will determine whether there's a collision
hit = false;
//Find the center points of each sprite
r1.centerX = r1.x + r1.width / 2;
r1.centerY = r1.y + r1.height / 2;
r2.centerX = r2.x + r2.width / 2;
r2.centerY = r2.y + r2.height / 2;
//Find the half-widths and half-heights of each sprite
r1.halfWidth = r1.width / 2;
r1.halfHeight = r1.height / 2;
r2.halfWidth = r2.width / 2;
r2.halfHeight = r2.height / 2;
//Calculate the distance vector between the sprites
vx = r1.centerX - r2.centerX;
vy = r1.centerY - r2.centerY;
//Figure out the combined half-widths and half-heights
combinedHalfWidths = r1.halfWidth + r2.halfWidth;
combinedHalfHeights = r1.halfHeight + r2.halfHeight;
//Check for a collision on the x axis
if (Math.abs(vx) < combinedHalfWidths) {
//A collision might be occurring. Check for a collision on the y axis
if (Math.abs(vy) < combinedHalfHeights) {
//There's definitely a collision happening
hit = true;
} else {
//There's no collision on the y axis
hit = false;
}
} else {
//There's no collision on the x axis
hit = false;
}
//`hit` will be either `true` or `false`
return hit;
};