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.

  1. 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:

  1. if (hitTestRectangle(cat, box)) {
  2. //There's a collision
  3. } else {
  4. //There's no collision
  5. }

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.

Displaying text

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.

  1. function play(delta) {
  2. //use the cat's velocity to make it move
  3. cat.x += cat.vx;
  4. cat.y += cat.vy;
  5. //check for a collision between the cat and the box
  6. if (hitTestRectangle(cat, box)) {
  7. //if there's a collision, change the message text
  8. //and tint the box red
  9. message.text = "hit!";
  10. box.tint = 0xff3300;
  11. } else {
  12. //if there's no collision, reset the message
  13. //text and the box's color
  14. message.text = "No collision...";
  15. box.tint = 0xccff99;
  16. }
  17. }

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”:

  1. 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.

  1. box.tint = 0xff3300;

If there’s no collision, the message and box are maintained in their original states:

  1. message.text = "No collision...";
  2. 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?

  1. function hitTestRectangle(r1, r2) {
  2. //Define the variables we'll need to calculate
  3. let hit, combinedHalfWidths, combinedHalfHeights, vx, vy;
  4. //hit will determine whether there's a collision
  5. hit = false;
  6. //Find the center points of each sprite
  7. r1.centerX = r1.x + r1.width / 2;
  8. r1.centerY = r1.y + r1.height / 2;
  9. r2.centerX = r2.x + r2.width / 2;
  10. r2.centerY = r2.y + r2.height / 2;
  11. //Find the half-widths and half-heights of each sprite
  12. r1.halfWidth = r1.width / 2;
  13. r1.halfHeight = r1.height / 2;
  14. r2.halfWidth = r2.width / 2;
  15. r2.halfHeight = r2.height / 2;
  16. //Calculate the distance vector between the sprites
  17. vx = r1.centerX - r2.centerX;
  18. vy = r1.centerY - r2.centerY;
  19. //Figure out the combined half-widths and half-heights
  20. combinedHalfWidths = r1.halfWidth + r2.halfWidth;
  21. combinedHalfHeights = r1.halfHeight + r2.halfHeight;
  22. //Check for a collision on the x axis
  23. if (Math.abs(vx) < combinedHalfWidths) {
  24. //A collision might be occurring. Check for a collision on the y axis
  25. if (Math.abs(vy) < combinedHalfHeights) {
  26. //There's definitely a collision happening
  27. hit = true;
  28. } else {
  29. //There's no collision on the y axis
  30. hit = false;
  31. }
  32. } else {
  33. //There's no collision on the x axis
  34. hit = false;
  35. }
  36. //`hit` will be either `true` or `false`
  37. return hit;
  38. };