碰撞检测,用来检查两个精灵是否接触。html
Pixi 没有内置的碰撞检测系统, 因此这里咱们使用一个名为 Bump 的库,Bump 是一个易于使用的2D碰撞方法的轻量级库,可与 Pixi 渲染引擎一块儿使用。它提供了制做大多数2D动做游戏所需的全部碰撞工具。git
要开始使用 Bump,首先直接用 script 标签,引入 js 文件github
<script src="https://www.kkkk1000.com/js/bump.js"></script>
复制代码
而后建立它的实例算法
let b = new Bump(PIXI);
复制代码
变量 b 如今表明 Bump 实例。可使用它来访问 Bump 的全部碰撞方法。数组
hit 方法是一种通用碰撞检测功能。它会自动检测碰撞中使用的精灵种类,并选择适当的碰撞方法。这意味着你没必要记住要使用 Bump 库中的许多碰撞方法的哪个,你只须要记住一个 hit 。可是为了不 hit 方法最后产生的效果和你想象的不同,最好仍是要了解一下 Bump 库中其余的方法。函数
如下是 hit 方法最简单的使用形式:工具
b.hit(sprite1, sprite2);
复制代码
若是两个精灵碰撞到了,就返回 true,没有碰撞到,则返回 false。post
查看示例学习
在碰撞检测时,Bump 的方法默认精灵是矩形的,使用矩形碰撞检测的算法,若是你想让方法把一个精灵当作圆形,使用圆形碰撞检测的算法,须要将精灵的 circular 属性设置为 true 。动画
anySprite.circular = true;
复制代码
若是你使用 hit 方法检测两个圆形精灵是否碰撞,你还须要将两个精灵的 diameter 属性设置为 true 。
若是你但愿精灵对碰撞做出反应,使它们不重叠,请将第三个参数设置为 true 。
b.hit(sprite1, sprite2, true);
复制代码
这个防止重叠的功能,对于制做墙壁,地板或任何其余类型的边界很是有用。
若是你想让精灵碰撞后反弹,请将第四个参数设置为 true。
b.hit(sprite1, sprite2, true, true);
复制代码
注意:
若是须要精灵反弹,精灵还必须有速度属性,也就是 vx 和 vy 属性。
设置第五个参数为 true 使 hit 方法使用精灵的全局坐标。在检测不一样父容器的精灵之间的碰撞时,这颇有用。
b.hit(sprite1, sprite2, true, true, true);
复制代码
精灵的全局坐标是相对于画布左上角的位置。 精灵的局部坐标是相对于其父容器的左上角的位置。
若是要检查点对象是否与精灵碰撞,将点对象做为第一个参数,以下所示:
b.hit({x: 200, y:120}, sprite);
复制代码
点对象是一个具备 x 和 y 两个属性的对象,x 和 y 表示了画布中一个点的坐标。
hit 方法还容许你检查精灵和精灵组之间的碰撞。只需将精灵组做为第二个参数便可。在此示例中,精灵组是 spriteArray。
b.hit(sprite, spriteArray, true, true, true);
复制代码
你将看到 hit 方法自动遍历精灵组中的全部精灵,并根据参数中的第一个精灵检测它们。这意味着你没必要本身编写 for 循环或 forEach 循环。
你还可使用回调函数做为第六个参数。这对于检查单个精灵和精灵组之间的碰撞特别有用。若是发生碰撞,回调函数将运行,你能够访问碰撞返回值和碰撞中涉及的精灵。下面是如何使用这个特性来检测一个名为 sprite 的精灵和一个名为 spriteArray 的精灵组之间的碰撞。
b.hit(
sprite,
spriteArray,
true, true, true,
function (collision, platform) {
//collision 表示 sprite 的哪一边发生碰撞
//platform 表示 sprite 正在碰撞的精灵组中的精灵
console.log(collision);
console.log(platform);
}
);
复制代码
这是一种执行复杂碰撞检测的简洁方式,能够为你提供大量信息和低级控制,但没必要手动遍历数组中的全部精灵。
hit 方法的返回值会与你正在检查的精灵的种类相匹配。例如,若是两个精灵都是矩形,而且 hit 方法的第三个参数是 true,碰撞后,返回值表示参数中第一个矩形发生碰撞的一侧,若是没有发生碰撞,返回值就是 undefined 。
示例:
let collision = b.hit(rectangleOne, rectangleTwo, true);
message.text = "参数中第一个矩形的碰撞侧是: " + collision;
复制代码
hit 方法只是 Bump 的许多低级碰撞方法的高级包装器。若是你更喜欢使用较低级别的方法,接下来会列出全部的这些方法。
最基本的碰撞检测是检查点对象是否与精灵碰撞。hitTestPoint 方法将帮助你解决这个问题。
hitTestPoint 方法须要两个参数:
名称 | 描述 |
---|---|
point | 具备 x 和 y 属性的点对象,x 和 y 表示了画布中一个点的坐标 |
sprite | 精灵 |
示例:
let collision = b.hitTestPoint(
{ x: 180, y: 128 }, //具备 x 和 y 属性的点对象
sprite //须要检测的精灵
)
复制代码
若是点对象与精灵碰撞,hitTestPoint 方法返回 true,不然返回 false。
上面示例中的精灵被看成是矩形的,但 hitTestPoint 方法一样适用于圆形精灵。若是精灵具备 radius 属性,则 hitTestPoint 方法假定精灵是圆形的而且对它应用圆形碰撞检测算法。若是精灵没有 radius 属性,则该方法假定它是矩形。你能够给任何精灵一个 radius 属性。而一个更简单的方法是给精灵一个 circular 属性并将其设置为 true 。
anySprite.circular = true;
复制代码
这样精灵就会应用圆形碰撞检测算法,并具备一个 radius 属性,该属性的值等于精灵宽度的一半。
hitTestCircle 方法用来检测两个圆形精灵之间的碰撞。
b.hitTestCircle(sprite1,sprite2)
复制代码
做为参数传入 hitTestCircle 方法的精灵须要有 radius 属性,若是精灵碰撞则返回 true,所以你能够将其与 if 语句一块儿使用来检测碰撞,以下所示:
if(b.hitTestCircle(sprite1,sprite2)){
message.text = "碰撞到了!";
//碰撞到后,将 vx 设置为0,中止移动
sprite1.vx=0;
}
复制代码
当移动的圆形精灵碰到没有移动的圆形精灵时,你可使用 circleCollision 方法建立碰撞反应。
参数:
名称 | 默认值 | 描述 |
---|---|---|
circle1 | 移动的圆形精灵 | |
circle2 | 没有移动的圆形精灵 | |
bounce | false | 用于肯定第一个精灵碰撞到第二个精灵时是否应该反弹 |
global | false | 是否使用精灵的全局坐标。若是要检测具备不一样父容器的精灵之间的碰撞 ,这颇有用 |
注意: 若是你但愿参数中第一个精灵碰撞到第二个精灵时反弹,那第一个精灵必须有速度属性,也就是 vx 和 vy 属性。
movingCircleCollision 方法可让两个移动的圆形精灵在碰撞时弹开,它们会以一种很是逼真的方式将速度传递给对方,从而使它们弹开。
参数:
名称 | 默认值 | 描述 |
---|---|---|
circle1 | 移动的圆形精灵 | |
circle2 | 移动的圆形精灵 | |
global | false | 是否使用精灵的全局坐标。若是要检测具备不一样父容器的精灵之间的碰撞 , |
b.movingCircleCollision(circle1, circle2)
复制代码
若是圆形精灵具备 mass 属性,则该值将用于帮助肯定圆形精灵应该相互反弹的力。
若是你有一堆移动的圆形精灵,你但愿这些精灵都在碰撞后进行反弹,这个时候你须要把这些精灵进行两两检查,判断它们是否碰撞,这须要把这些精灵放在一个数组中,使用两层 for 循环,而且内层 for 循环的计数器比外层的 for 循环大1,这样就能够检测全部圆形精灵的碰撞状况。
for (let i = 0; i < container.children.length; i++) {
//碰撞检查中使用的第一个圆形精灵
var c1 = container.children[i];
for (let j = i + 1; j < container.children.length; j++) {
//碰撞检查中使用的第二个圆形精灵
let c2 = container.children[j];
//检查碰撞状况,若是精灵发生碰撞,将精灵弹开
b.movingCircleCollision(c1, c2);
}
}
复制代码
你能够看到内层 for 循环的计数器开始就是一个大于外层 for 循环的数字:
let j = i + 1
复制代码
这能够防止对任何一对精灵进行屡次碰撞检测。
Bump 库还有一个方便的方法 multipleCircleCollision,使用这个方法能够替代 for 循环的方式。这个方法会对每对精灵自动调用 movingCircleCollision,使它们互相反弹。 你能够在游戏循环中使用它来检查数组中的全部精灵,可是要注意数组中的精灵是不能重复的。
示例:
b.multipleCircleCollision(container.children);
复制代码
要肯定两个矩形精灵是否碰撞,请使用 hitTestRectangle 方法:
b.hitTestRectangle(rectangle1, rectangle2)
复制代码
若是矩形精灵碰撞,hitTestRectangletrue 方法返回 true,没有碰撞则返回 false。
示例:
if(b.hitTestRectangle(sprite1,sprite2)){
message.text = "碰撞到了!";
}else{
message.text = "没有碰到";
}
复制代码
rectangleCollision 方法使矩形精灵表现得好像它们有质量。它能够防止参数中的两个矩形精灵重叠。
参数:
名称 | 默认值 | 描述 |
---|---|---|
rectangle1 | 矩形精灵 | |
rectangle2 | 矩形精灵 | |
bounce | false | 用于肯定第一个精灵是否应该从第二个精灵反弹 |
global | true | 是否使用精灵的全局坐标 |
返回值:
若是精灵碰撞到了,rectangleCollision 方法返回一个字符串值,告诉你第一个矩形精灵的哪一侧碰到了第二个矩形精灵。其值多是 left
,right
,top
或 bottom
。若是没有碰撞到返回值就是 undefined
。
示例:
let collision = b.rectangleCollision(sprite2, sprite1);
//碰撞发生在矩形1(第一个参数)的哪一侧
switch (collision) {
case "left":
message.text = "参数中的第一个精灵的 左侧 发生碰撞";
break;
case "right":
message.text = "参数中的第一个精灵的 右侧 发生碰撞";
break;
case "top":
message.text = "参数中的第一个精灵的 上方 发生碰撞";
break;
case "bottom":
message.text = "参数中的第一个精灵的 下方 发生碰撞";
break;
default:
message.text = "没有发生碰撞";
}
复制代码
此示例代码将阻止矩形重叠,并在名为 message 的文本精灵中显示碰撞侧。
rectangleCollision 方法具备很是有用的反作用。参数中的第二个精灵可以将第一个精灵推走。若是你须要相似于推箱子游戏中的那种功能,这会颇有用。
hitTestCircleRectangle 方法能够检查圆形和矩形精灵之间的碰撞。
参数:
名称 | 默认值 | 描述 |
---|---|---|
circle | 圆形精灵 | |
rectangle | 矩形精灵 | |
global | false | 是否使用精灵的全局坐标 |
返回值:
若是精灵碰撞到了,hitTestCircleRectangle 方法一样返回一个字符串值,告诉你圆形精灵在哪里碰到了矩形精灵。其值多是 topLeft
,topMiddle
,topRight
,leftMiddle
,rightMiddle
,bottomLeft
,bottomMiddle
或 bottomRight
。若是没有碰撞到返回值就是 undefined
。
示例:
let collision = b.hitTestCircleRectangle(circle, rectangle);
if (collision) {
message.text = "圆形精灵的 " + collision + " 侧,发生碰撞";
} else {
message.text = "没有发生碰撞";
}
复制代码
使用 circleRectangleCollision 方法让一个圆形精灵从矩形精灵的侧面或角反弹。
参数:
名称 | 默认值 | 描述 |
---|---|---|
circle | 圆形精灵 | |
rectangle | 矩形精灵 | |
bounce | false | 是否使使精灵反弹 |
global | false | 是否使用精灵的全局坐标 |
示例:
b.circleRectangleCollision(circle, rectangle, true);
复制代码
contain 方法能够将精灵限制在必定矩形区域内。
参数:
名称 | 默认值 | 描述 |
---|---|---|
sprite | 精灵 | |
container | 容器,这是一个对象,具备 x、y、width 和 height 属性,表示一个矩形区域。 | |
bounce | false | 肯定精灵在碰到容器边界时是否应该反弹。 |
callbackFunction | 回调函数,当精灵碰撞到容器边界时会调用它,而且会将 contain 方法的返回值做为参数传入这个回调函数。 |
返回值:
若是精灵碰撞到容器边界,contain 方法将返回一个 Set 对象,告诉你精灵撞到了哪一侧,它的值可能有 left
,right
,top
或 bottom
,若是精灵没有碰撞到容器边界, 返回值就是 undefined
。
示例:
let collision = b.contain(sprite, { x: 0, y: 0, width: 512, height: 512 }, true, callbackFunction);
//发生碰撞时的回调函数
function callbackFunction(collision) {
console.log("collision", collision);
}
//若是发生碰撞,显示哪边的边界发生碰撞
if (collision) {
if (collision.has("left")) {
message.text = "边界 左侧 发生碰撞";
};
if (collision.has("right")) {
message.text = "边界 右侧 发生碰撞";
};
if (collision.has("top")) {
message.text = "边界 上方 发生碰撞";
};
if (collision.has("bottom")) {
message.text = "边界 下方 发生碰撞";
};
}
复制代码
上面的代码会将精灵限制在对象定义的512 x 512像素区域内。若是精灵碰撞到容器的边界,它将会反弹, 而且显示碰到了哪边的边界,callbackFunction(第四个参数)也将运行。
contain 方法的另外一个特色是,若是精灵具备 mass 属性,该值将用于以很是天然的方式抑制精灵的反弹。
注意:
使用 Bump 库时,最好给精灵设置上速度属性(vx,vy),由于 Bump 库中许多方法实现效果时,都须要用到这个两个属性。