• 碰撞检测
    • 碰撞检测函数

    碰撞检测

    现在你知道了如何制造种类繁多的图形对象,但是你能用他们做什么?一个有趣的事情是利用它制作一个简单的 碰撞检测系统 。你可以用一个叫做: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. };