JavaScript:碰撞检测

IT技术 javascript collision-detection
2021-02-08 05:55:16

JavaScript 中的碰撞检测是如何工作的?

我不能使用 jQuery 或 gameQuery - 已经在使用原型 - 所以,我正在寻找一些非常简单的东西。我不是要求完整的解决方案,只是指出我正确的方向。

假设有:

<div id="ball"></div>
and
<div id="someobject0"></div>

现在球正在移动(任何方向)。"Someobject"(0-X) 已经预先定义好了,其中有 20-60 个随机放置,如下所示:

#someobject {position: absolute; top: RNDpx; left: RNDpx;}

我可以创建一个带有“someobject(X)”位置的数组,并在“球”移动时测试碰撞......像这样:

for(var c=0; c<objposArray.length; c++){
........ and code to check ball's current position vs all objects one by one....
}

但我想这将是一个“菜鸟”解决方案,它看起来很慢。有更好的吗?

6个回答

这是一个非常简单的边界矩形例程。该公司预计双方ab能与对象xywidthheight属性:

function isCollide(a, b) {
    return !(
        ((a.y + a.height) < (b.y)) ||
        (a.y > (b.y + b.height)) ||
        ((a.x + a.width) < b.x) ||
        (a.x > (b.x + b.width))
    );
}

要查看此功能的实际效果,请参阅@MixerOID慷慨制作的代码笔

@KryptoniteDove:不幸的是,您不能在此例程中简单地输入 DOM 元素,您需要某种转换(例如使用 jQuery)。此外,您的 div 可能应该使用position: absolute而不是relative. 这是您的版本的一个分支:jsbin.com/akeSeDI/3/edit
2021-03-17 05:55:16
这需要 jQuerz,因此不是一个有效的答案。stackoverflow.com/a/35974082/3580261实际上是正确的并且依赖于这个函数。
2021-03-17 05:55:16
谁能澄清我做错了什么?无论“碰撞”如何,它始终返回 true jsbin.com/akeSeDI/2/edit
2021-03-19 05:55:16
@eljefedelrodeodeljefe 我的代码不需要 jQuery。它只需要具有给定属性的对象,您可以使用 jQuery 获得这些属性,但也需要使用函数中描述的方法。
2021-03-26 05:55:16
我为这个奇妙的功能创建了可视化 GUI :) codepen.io/mixal_bl4/pen/qZYWOm你可以把这个添加到你的答案中 :)
2021-04-09 05:55:16

首先需要的是实际功能,它会检测您是否在球和物体之间发生碰撞。

为了性能,实现一些粗略的碰撞检测技术会很好,例如,边界矩形,如果需要,如果检测到碰撞,可以使用更准确的技术,这样您的函数将运行得更快一点,但恰好使用相同的循环。

另一个有助于提高性能的选项是对您拥有的对象进行一些预处理。例如,您可以像通用表格一样将整个区域分成单元格,并存储包含在特定单元格中的适当对象。因此,要检测碰撞,您正在检测球占据的单元格,从这些单元格中获取对象并使用碰撞检测功能。

为了加快速度,您可以实现2d-treequadtreeR-tree

没有 jQuery 的答案,以 HTML 元素作为参数:

这是一种更好的方法,可以检查元素在视口上显示时的真实位置,即使它们是绝对的、相对的或已通过转换进行操作:

function isCollide(a, b) {
    var aRect = a.getBoundingClientRect();
    var bRect = b.getBoundingClientRect();

    return !(
        ((aRect.top + aRect.height) < (bRect.top)) ||
        (aRect.top > (bRect.top + bRect.height)) ||
        ((aRect.left + aRect.width) < bRect.left) ||
        (aRect.left > (bRect.left + bRect.width))
    );
}
事实上,它应该是上述问题的唯一答案。最佳答案需要 jQuery
2021-03-12 05:55:16

你可以试试jquery-collision完全披露:我刚刚写了这个并发布了它。我没有找到解决方案,所以我自己写了一个。

它允许您执行以下操作:

var hit_list = $("#ball").collision("#someobject0");

这将返回与“#ball”重叠的所有“#someobject0”。

@irwin - 嗯,我正在继续“不能使用 jquery - 使用原型”,我很确定你实际上可以混合它们。不过,老实说,我还没有尝试过。很高兴它对你有帮助!也试试 jquery-draggable-collision!:-)
2021-03-16 05:55:16
@PeterAjtai:不,它在 sourceforge 上,为什么?
2021-03-17 05:55:16
OP 说他们不能使用 jQuery。不过还是不错的,帮助我解决了我自己的问题。
2021-03-22 05:55:16
@eruciform sourceforge 几乎无法使用。我敢肯定,如果它在 github 上,很多人会喜欢它
2021-03-27 05:55:16
@PeterAjtai - 今年夏天我可能会将它们全部转移到 github。它只是零更新一段时间,所以没有动力去破坏有效的东西。不过,我会尽快添加东西!
2021-04-08 05:55:16

bcm 的答案,此时有 0 票,实际上是一个很好的,被低估的答案。它使用古老的毕达哥拉斯来检测物体何时比它们的组合边界圆更近。简单的碰撞检测通常使用矩形碰撞检测,如果您的精灵倾向于是矩形,这很好。如果它们是圆形的(或其他小于矩形的),例如球、小行星或任何其他极端角通常是透明的形状,您可能会发现这种高效的例程是最准确的。

但为了清楚起见,这里是代码的更完全实现版本:

function doCollide(x1, y1, w1, x2, y2, w2) {
    var xd = x1 - x2;
    var yd = y1 - y2;
    var wt = w2 + w1;
    return (xd * xd + yd * yd <= wt * wt);
}

其中传入的参数是两个不同精灵对象的 x、y 和宽度值。