专栏首页FEWY学习 PixiJS — 碰撞检测

学习 PixiJS — 碰撞检测

版权声明:本文为博主原创文章,欢迎转载,转载请注明出处。 https://blog.csdn.net/FE_dev/article/details/87646110

说明

碰撞检测,用来检查两个精灵是否接触。

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

没有移动的圆形精灵

bounce

false

用于确定第一个精灵碰撞到第二个精灵时是否应该反弹

global

false

是否使用精灵的全局坐标。如果要检测具有不同父容器的精灵之间的碰撞 ,这很有用

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

查看示例

movingCircleCollision

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

要确定两个矩形精灵是否碰撞,请使用 hitTestRectangle 方法:

b.hitTestRectangle(rectangle1, rectangle2)

如果矩形精灵碰撞,hitTestRectangletrue 方法返回 true,没有碰撞则返回 false。

示例:

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

查看示例

rectangleCollision

rectangleCollision 方法使矩形精灵表现得好像它们有质量。它可以防止参数中的两个矩形精灵重叠。

参数:

名称

默认值

描述

rectangle1

矩形精灵

rectangle2

矩形精灵

bounce

false

用于确定第一个精灵是否应该从第二个精灵反弹

global

true

是否使用精灵的全局坐标

返回值:

如果精灵碰撞到了,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

矩形精灵

global

false

是否使用精灵的全局坐标

返回值:

如果精灵碰撞到了,hitTestCircleRectangle 方法同样返回一个字符串值,告诉你圆形精灵在哪里碰到了矩形精灵。其值可能是 topLefttopMiddletopRightleftMiddlerightMiddlebottomLeftbottomMiddlebottomRight 。如果没有碰撞到返回值就是 undefined

示例:

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

查看示例

circleRectangleCollision

使用 circleRectangleCollision 方法让一个圆形精灵从矩形精灵的侧面或角反弹。

参数:

名称

默认值

描述

circle

圆形精灵

rectangle

矩形精灵

bounce

false

是否使使精灵反弹

global

false

是否使用精灵的全局坐标

示例:

b.circleRectangleCollision(circle, rectangle, true);

查看示例

contain

contain 方法可以将精灵限制在一定矩形区域内。

参数:

名称

默认值

描述

sprite

精灵

container

容器,这是一个对象,具有 x、y、width 和 height 属性,表示一个矩形区域。

bounce

false

确定精灵在碰到容器边界时是否应该反弹。

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 — 交互工具

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

推荐阅读

  • 远程办公经验为0,如何将日常工作平滑过度到线上?

    我是一名创业者,我的公司(深圳市友浩达科技有限公司)在2018年8月8日开始运营,现在还属于微型公司。这个春节假期,我一直十分关注疫情动向,也非常关心其对公司带来的影响。

    TVP官方团队
    TAPD 敏捷项目管理腾讯乐享企业邮箱企业编程算法
  • 数据中台,概念炒作还是另有奇效? | TVP思享

    作者简介:史凯,花名凯哥,腾讯云最具价值专家TVP,ThoughtWorks数据智能业务总经理。投身于企业数字化转型工作近20年。2000年初,在IBM 研发企业级中间件,接着加入埃森哲,为大型企业提供信息化架构规划,设计,ERP,云平台,数据仓库构建等技术咨询实施服务,随后在EMC负责企业应用转型业务,为企业提供云迁移,应用现代化服务。现在专注于企业智能化转型领域,是数据驱动的数字化转型的行业布道者,数据中台的推广者,精益数据创新体系的创始人,2019年荣获全球Data IQ 100人的数据赋能者称号,创业邦卓越生态聚合赋能官TOP 5。2019年度数字化转型专家奖。打造了行业第一个数据创新的数字化转型卡牌和工作坊。创建了精益数据创新方法论体系构建数据驱动的智能企业,并在多个企业验证成功,正在向国内外推广。

    TVP官方团队
    大数据数据分析企业
  • 扩展 Kubernetes 之 CRI

    使用 cri-containerd 的调用流程更为简洁, 省去了上面的调用流程的 1,2 两步

    王磊-AI基础
    Kubernetes
  • 扩展 Kubernetes 之 Kubectl Plugin

    kubectl 功能非常强大, 常见的命令使用方式可以参考 kubectl --help,或者这篇文章

    王磊-AI基础
    Kubernetes
  • 多种登录方式定量性能测试方案

    最近接到到一个测试任务,某服务提供了两种登录方式:1、账号密码登录;2、手机号+验证码登录。要对这两种登录按照一定的比例进行压测。

    八音弦
    测试服务 WeTest
  • 线程安全类在性能测试中应用

    首先验证接口参数签名是否正确,然后加锁去判断订单信息和状态,处理用户增添VIP时间事务,成功之后释放锁。锁是针对用户和订单的分布式锁,使用方案是用的redis。

    八音弦
    安全编程算法
  • 使用CDN(jsdelivr) 优化博客访问速度

    PS: 此篇文章适用于 使用 Github pages 或者 coding pages 的朋友,其他博客也类似.

    IFONLY@CUIT
    CDNGitGitHub开源
  • 扩展 Kubernetes 之 CNI

    Network Configuration 是 CNI 输入参数中最重要当部分, 可以存储在磁盘上

    王磊-AI基础
    Kubernetes
  • 聚焦【技术应变力】云加社区沙龙online重磅上线!

    云加社区结合特殊时期热点,挑选备受关注的音视频流量暴增、线下业务快速转线上、紧急上线防疫IoT应用等话题,邀请众多业界专家,为大家提供连续十一天的干货分享。从视野、预判、应对等多角度,帮助大家全面提升「技术应变力」!

    腾小云
  • 京东购物小程序购物车性能优化实践

    它是小程序开发工具内置的一个可视化监控工具,能够在 OS 级别上实时记录系统资源的使用情况。

    WecTeam
    渲染JavaScripthttps网络安全缓存

扫码关注云+社区

领取腾讯云代金券