碰撞检测

现在你知道了如何制造种类繁多的图形对象,但是你能用他们做什么?一个有趣的事情是利用它制作一个简单的 碰撞检测系统 。你可以用一个叫做:hitTestRectangle 的自定义的函数来检测两个矩形精灵是否接触。

  1. hitTestRectangle(spriteOne, spriteTwo)

如果它们重叠, hitTestRectangle 会返回 true。你可以用 hitTestRectangle 结合 if 条件语句去检测两个精灵是否碰撞:

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

正如你所见, hitTestRectangle 是走入游戏设计这片宇宙的大门。

运行在 examples 文件夹的 collisionDetection.html 文件,看看怎么用 hitTestRectangle工作。用方向按键去移动猫,如果猫碰到了盒子,盒子会变成红色,然后 “Hit!” 文字对象会显示出来。

Displaying text

你已经看到了创建这些所有元素的代码,让猫移动的键盘控制。唯一的新的东西就是 hitTestRectangle 函数被用在 play 函数里检测碰撞。

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

play 函数被每秒调用了60次,每一次这个 if 条件语句都会在猫和盒子之间进行碰撞检测。如果 hitTestRectangletrue,那么文字 message 对象会用 setText 方法去显示 “Hit”:

  1. message.text = "Hit!";

这个盒子的颜色改变的效果是把盒子的 tint 属性改成一个16进制的红色的值实现的。

  1. box.tint = 0xff3300;

如果没有碰撞,消息和盒子会保持它们的原始状态。

  1. message.text = "No collision...";
  2. box.tint = 0xccff99;

代码很简单,但是你已经创造了一个看起来完全活着的互动的世界!它简直跟魔术一样!令人惊讶的是,你大概已经拥有了你需要用Pixi制作游戏的全部技能!

碰撞检测函数

hitTestRectangle 函数都有些什么呢?它做了什么,还有它是如何工作的?关于碰撞检测算法的细节有些超出了本教程的范围。最重要的事情是你要知道如何使用它。但是,只是作为你的参考资料,不让你好奇,这里有全部的 hitTestRectangle 函数的定义。你能从注释弄明白它都做了什么吗?

  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 occuring. 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. };