我的碰撞检测算法似乎甚至在物体触碰之前就会触发

时间:2011-11-22 17:16:56

标签: javascript collision-detection

我写了一个非常简单的碰撞检测演示: http://jsfiddle.net/colintoh/UzPg2/5/

正如您所看到的,对象有时根本不连接,但触发了碰撞。球的半径是10px,因此当两个球中心之间的距离小于20px时,算法会触发碰撞。我把它缩小到18px以获得更好的视觉效果,但空碰撞仍然是随机发生的。我做错了吗?

2 个答案:

答案 0 :(得分:3)

看起来你没有使用正确的公式来确定两点之间的距离。有关完整说明,请参阅http://www.purplemath.com/modules/distform.htm

你这样做:

this.ballCollide = function(balli) {
    if (Math.abs((this.x) - (balli.x)) < (2*radius - buffer)) {
        if (Math.abs((this.y) - (balli.y)) < (2*radius - buffer)) {
             // Do collision
        }
    }
};

这是一个方形边界框,而不是圆形边框。要获得一个圆形边界框,您可以根据引用的网页中的公式执行类似的操作:

this.ballCollide = function(balli) {
    var deltax = this.x - balli.x;
    var deltay = this.y - balli.y;
    if (Math.sqrt(deltax * deltax + deltay * deltay) < 2 * radius - buffer) {
        // Do collision
    }
};

有关工作示例,请参阅http://jsfiddle.net/UzPg2/14/

请注意,完美的圆形边界框是慢得多的算法,而不是方形边界框近似。

按照Jarrod Roberson的观点(一个完美的圆圈总是在一个完美的正方形内),你可以通过基本上将原始代码与我发布的代码组合在一起来做到这一点(你可以将它们组合成一个条件开关,如果你想):

var deltax = this.x - balli.x;
var deltay = this.y - balli.y;
var dist = 2 * radius - buffer;
if (Math.abs(deltax) < dist && Math.abs(deltay) < dist) {
    if (Math.sqrt(deltax * deltax + deltay * deltay) < dist) {
       // Do collision
    }
}

请参阅http://jsfiddle.net/UzPg2/21/了解一个工作示例(我已离开buffer,因为您的变量在2处被调用,但我个人认为值为1时看起来更好。

如果需要,还有许多其他方法可以优化速度,但Jarrod的建议可以为您提供最快的速度提升。

答案 1 :(得分:1)

您只检查两个轴x,y上的碰撞。你需要使用毕达哥拉斯定理来检测所有轴上的效率。例如。

您的算法将检测这两个球所在​​点周围的碰撞,因为如果您从一个球沿x或y轴绘制一条切线,它会穿过另一个球:http://jsfiddle.net/XpXzW/1/

在这里你可以看到它们实际碰撞的位置: http://jsfiddle.net/wdVmQ/1/

如果您更改碰撞检测算法以检查完美碰撞(效率会降低),您也可以摆脱缓冲区:

http://jsfiddle.net/ucxER/

(使用毕达哥拉斯定理,碰撞的公式是:

 Math.sqrt((this.x - balli.x)*(this.x - balli.x) 
   + (this.y - balli.y)*(this.y - balli.y)) < 2*radius

Jarrod评论的内容也非常聪明。您可以使用这样的技术加快速度。由于平方根仅在球彼此靠近时计算:

http://jsfiddle.net/bKDXs/