Javascript:碰撞检测

jac*_*ore 45 javascript collision-detection

有人可以帮我理解碰撞检测在JS中是如何工作的吗?我不能使用jQuery或gameQuery - 已经使用原型 - 所以,我正在寻找一些非常简单的东西.不要求完整的解决方案,只需指出正确的方向.

让我们说:

<div id="ball"></div>
and 
<div id="someobject0"></div>
Run Code Online (Sandbox Code Playgroud)

现在球正在移动(任何方向)."Someobject"(0-X)已经预先定义,其中有20-60个随机定位如下:

#someobject {position: absolute; top: RNDpx; left: RNDpx;} 
Run Code Online (Sandbox Code Playgroud)

我可以创建一个带有"someobject(X)"位置的数组,并在"ball"移动时测试碰撞...类似于:

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

但我想这将是一个"noob"解决方案,它看起来很慢.有更好的吗?

Hus*_*sky 65

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

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))
    );
}
Run Code Online (Sandbox Code Playgroud)

要查看此功能的运行情况,这里是@MixerOID优雅地编写的代码.

  • @KryptoniteDove:遗憾的是,你不能简单地在这个例程中输入一个DOM元素,你需要某种转换(例如使用jQuery).另外,你的div应该使用`position:absolute`而不是`relative`.这是你的版本的一个分支:http://jsbin.com/akeSeDI/3/edit (2认同)
  • 我为这个奇妙的功能创建了可视化GUI :) http://codepen.io/mixal_bl4/pen/qZYWOm你可以添加这个给你答案:) (2认同)

Li0*_*liQ 29

首先要做的是检测球与物体之间是否发生碰撞的实际功能.

为了性能起见,实现一些粗略的碰撞检测技术(例如,边界矩形)以及在检测到碰撞时需要更准确的技术将是很好的,这样您的功能可以更快地运行但是使用完全相同的同样的循环.

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

为了加快速度,你可以实现2d-tree,quadtreeR-tree.


eru*_*orm 22

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

它允许你做:

var hit_list = $("#ball").collision("#someobject0");
Run Code Online (Sandbox Code Playgroud)

这将返回与"#ball"重叠的所有"#someobject0".

  • OP表示他们不能使用jQuery.虽然还不错,但在我自己的解决方案中帮助了我. (6认同)
  • @eruciform sourceforge几乎无法使用.我敢肯定很多人都会喜欢它,如果它是在github上 (3认同)
  • 这是在github上吗? (2认同)

小智 18

没有jQuery的版本,以HTMLElements作为输入

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

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))
    );
}
Run Code Online (Sandbox Code Playgroud)

  • 实际上,它应该是上述问题的唯一答案。最佳答案需要jQuery (2认同)

J S*_*gue 8

"bcm's"的答案,此时有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);
} 
Run Code Online (Sandbox Code Playgroud)

传入的参数是两个不同精灵对象的x,y和width值


B M*_*B M 8

Mozilla有一篇很好的文章,代码如下所示

https://developer.mozilla.org/en-US/docs/Games/Techniques/2D_collision_detection

矩形碰撞

if (rect1.x < rect2.x + rect2.width &&
   rect1.x + rect1.width > rect2.x &&
   rect1.y < rect2.y + rect2.height &&
   rect1.height + rect1.y > rect2.y) {
    // collision detected!
}
Run Code Online (Sandbox Code Playgroud)

圆碰撞

if (distance < circle1.radius + circle2.radius) {
    // collision detected!
}
Run Code Online (Sandbox Code Playgroud)


bcm*_*bcm 5

这是我遇到的轻量级解决方案 -

function E() { // check collision
            S = X - x;
            D = Y - y;
            F = w + W;
            return (S * S + D * D <= F * F)
        }
Run Code Online (Sandbox Code Playgroud)

大小变量是2个对象,(x coord,y coord和w width)

这里开始

  • 据我所知,这个函数假设对象是方形的(甚至是圆形的?)。此外,哈士奇上面的代码似乎不太可读,如果这还不够,它似乎也更慢(请参阅:http://jsperf.com/simple-collision-detection) (2认同)