进修 PixiJS — 碰撞检测

申明

碰撞检测,用来搜检两个精灵是不是打仗。

Pixi 没有内置的碰撞检测体系, 所以这里我们运用一个名为 Bump 的库,Bump 是一个易于运用的2D碰撞要领的轻量级库,可与 Pixi 衬着引擎一同运用。它供应了制造大多数2D动作游戏所需的一切碰撞东西。

运用 Bump

要最先运用 Bump,起首直接用 script 标签,引入 js 文件

<script src="https://www.kkkk1000.com/js/bump.js"></script>

然后建立它的实例

let b = new Bump(PIXI);

变量 b 如今代表 Bump 实例。可以运用它来接见 Bump 的一切碰撞要领。

运用 Bump 的碰撞要领

hit

hit 要领是一种通用碰撞检测功用。它会自动检测碰撞中运用的精灵品种,并挑选恰当的碰撞要领。这意味着你没必要记着要运用 Bump 库中的很多碰撞要领的哪个,你只须要记着一个 hit 。然则为了防备 hit 要领末了发作的结果和你设想的不一样,最好照样要相识一下 Bump 库中其他的要领。

以下是 hit 要领最简朴的运用情势:

b.hit(sprite1, sprite2);

假如两个精灵碰撞到了,就返回 true,没有碰撞到,则返回 false。

检察示例

在碰撞检测时,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 要领将协助你处理这个题目。
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

hitTestCircle 要领用来检测两个圆形精灵之间的碰撞。

b.hitTestCircle(sprite1,sprite2)

作为参数传入 hitTestCircle 要领的精灵须要有 radius 属性,假如精灵碰撞则返回 true,因而你可以将其与 if 语句一同运用来检测碰撞,以下所示:

if(b.hitTestCircle(sprite1,sprite2)){
    message.text = "碰撞到了!";
    //碰撞到后,将 vx 设置为0,住手挪动
    sprite1.vx=0;
}

检察示例

circleCollision

当挪动的圆形精灵遇到没有挪动的圆形精灵时,你可以运用 circleCollision 要领建立碰撞回响反映。

参数:

称号默许值形貌
circle1挪动的圆形精灵
circle2没有挪动的圆形精灵
bouncefalse用于肯定第一个精灵碰撞到第二个精灵时是不是应当反弹
globalfalse是不是运用精灵的全局坐标。假如要检测具有不同父容器的精灵之间的碰撞 ,这很有效

注重:
假如你愿望参数中第一个精灵碰撞到第二个精灵时反弹,那第一个精灵必须有速率属性,也就是 vx 和 vy 属性。

检察示例

movingCircleCollision

movingCircleCollision 要领可以让两个挪动的圆形精灵在碰撞时弹开,它们会以一种异常传神的体式格局将速率传递给对方,从而使它们弹开。

参数:

称号默许值形貌
circle1挪动的圆形精灵
circle2挪动的圆形精灵
globalfalse是不是运用精灵的全局坐标。假如要检测具有不同父容器的精灵之间的碰撞 ,
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

要肯定两个矩形精灵是不是碰撞,请运用 hitTestRectangle 要领:

b.hitTestRectangle(rectangle1, rectangle2)

假如矩形精灵碰撞,hitTestRectangletrue 要领返回 true,没有碰撞则返回 false。

示例:

if(b.hitTestRectangle(sprite1,sprite2)){
    message.text = "碰撞到了!";
}else{
    message.text = "没有遇到";
}

检察示例

rectangleCollision

rectangleCollision 要领使矩形精灵表现得彷佛它们有质量。它可以防备参数中的两个矩形精灵堆叠。

参数:

称号默许值形貌
rectangle1矩形精灵
rectangle2矩形精灵
bouncefalse用于肯定第一个精灵是不是应当从第二个精灵反弹
globaltrue是不是运用精灵的全局坐标

返回值:

假如精灵碰撞到了,rectangleCollision 要领返回一个字符串值,通知你第一个矩形精灵的哪一侧遇到了第二个矩形精灵。其值多是 leftrighttopbottom 。假如没有碰撞到返回值就是 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

hitTestCircleRectangle 要领可以搜检圆形和矩形精灵之间的碰撞。

参数:

称号默许值形貌
circle圆形精灵
rectangle矩形精灵
globalfalse是不是运用精灵的全局坐标

返回值:

假如精灵碰撞到了,hitTestCircleRectangle 要领一样返回一个字符串值,通知你圆形精灵在那里遇到了矩形精灵。其值多是 topLefttopMiddletopRightleftMiddlerightMiddlebottomLeftbottomMiddlebottomRight 。假如没有碰撞到返回值就是 undefined

示例:

let collision = b.hitTestCircleRectangle(circle, rectangle);
if (collision) {
    message.text = "圆形精灵的 " + collision + " 侧,发作碰撞";
} else {
    message.text = "没有发作碰撞";
}

检察示例

circleRectangleCollision

运用 circleRectangleCollision 要领让一个圆形精灵从矩形精灵的正面或角反弹。

参数:

称号默许值形貌
circle圆形精灵
rectangle矩形精灵
bouncefalse是不是使使精灵反弹
globalfalse是不是运用精灵的全局坐标

示例:

b.circleRectangleCollision(circle, rectangle, true);

检察示例

contain

contain 要领可以将精灵限定在肯定矩形地区内。

参数:

称号默许值形貌
sprite精灵
container容器,这是一个对象,具有 x、y、width 和 height 属性,示意一个矩形地区。
bouncefalse肯定精灵在遇到容器边境时是不是应当反弹。
callbackFunction回调函数,当精灵碰撞到容器边境时会挪用它,而且会将 contain 要领的返回值作为参数传入这个回调函数。

返回值:

假如精灵碰撞到容器边境,contain 要领将返回一个 Set 对象,通知你精灵撞到了哪一侧,它的值可能有 leftrighttopbottom ,假如精灵没有碰撞到容器边境, 返回值就是 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 库中很多要领完成结果时,都须要用到这个两个属性。

上一篇 进修 PixiJS — 补间动画

下一篇 进修 PixiJS — 交互东西

    原文作者:FEWY
    原文地址: https://segmentfault.com/a/1190000018273360
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞