Javascript 碰撞时计算球位置的最简单方法是什么?

Javascript 碰撞时计算球位置的最简单方法是什么?,javascript,geometry,collision-detection,Javascript,Geometry,Collision Detection,我正在尝试用java脚本制作一些简单的台球游戏。我已经做到了,但我不喜欢检查两个球是否会在下一帧碰撞的方式。我想有更简单的方法来计算碰撞发生时球的坐标。我发现很多答案都是基于碰撞运动学,如何处理碰撞后的速度和方向,但没有计算碰撞发生时的位置 正如您在示例图中所看到的,金球的移动速度比蓝球慢,并且每个球在下一帧上必须移动的距离不会被视为碰撞。但是,正如您所看到的,它们应该碰撞(虚线) 因此,我将每一个动作划分为多个部分,并计算各点之间的距离是否等于或小于球的直径,这会减慢每一帧中必须计算多个球(

我正在尝试用java脚本制作一些简单的台球游戏。我已经做到了,但我不喜欢检查两个球是否会在下一帧碰撞的方式。我想有更简单的方法来计算碰撞发生时球的坐标。我发现很多答案都是基于碰撞运动学,如何处理碰撞后的速度和方向,但没有计算碰撞发生时的位置

正如您在示例图中所看到的,金球的移动速度比蓝球慢,并且每个球在下一帧上必须移动的距离不会被视为碰撞。但是,正如您所看到的,它们应该碰撞(虚线)

因此,我将每一个动作划分为多个部分,并计算各点之间的距离是否等于或小于球的直径,这会减慢每一帧中必须计算多个球(如斯诺克)的过程,而且这种方法并非总是100%准确,击球后球可能会以不准确的角度移动(差别不大,但对斯诺克很重要)


在知道每个球的起始位置和速度的情况下,有没有更简单的方法来计算这些(XAC、YAC)和(XBC、YBC)值,而无需将球的路径划分为扇区并进行多次计算以找到合适的距离?

只需预先计算一次碰撞事件是值得的(这种方法适用于可靠数量的球,因为我们必须处理所有
~n^2
对球)

第一个球的位置是
A0
,速度矢量是
VA
。 第二个球的位置是
B0
,速度矢量是
VB

为了简化计算,我们可以使用Halileo原理-使用与第一个球相连的移动坐标系。在该系统中,第一个球的位置和速度始终为零。第二个球相对于时间的位置为:

B'(t) = (B0 - A0) + (VB - VA) * t = B0' + V'*t
我们只需要找到碰撞的二次方程的解
距离=2R

 (B0'.X + V'.X*t)^2 + (B0'.X + V'.Y*t)^2 = 4*R^2
对未知时间
t
求解该方程,我们可能会得到以下情况:无解(无碰撞)、单一解(仅接触事件)、两个解-在这种情况下,较小的
t
值对应于碰撞的物理力矩

示例(对不起,在Python中,
**
是power操作符):

def冲突(ax、ay、bx、by、vax、vay、vbx、vby、r):
dx=bx-ax
dy=by-ay
vx=vbx-vax
vy=vby-vay
#(dx+vx*t)**2+(dy+vy*t)**2==4*r*r解这个方程
#系数
a=vx**2+vy**2
b=2*(vx*dx+vy*dy)
c=dx**2+dy**2-4*r**2
dis=b*b-4*a*c

如果dis关于MBo的解决方案,下面是java脚本中的一个函数,它将计算碰撞时球的坐标和碰撞发生的时间:

calcCollisionBallCoordinates(ball1_x, ball1_y, ball2_x, ball2_y, ball1_vx, ball1_vy, ball2_vx, ball2_vy, r) {
    let dx = ball2_x - ball1_x, 
        dy = ball2_y - ball1_y,
        vx = ball2_vx - ball1_vx, 
        vy = ball2_vy - ball1_vy,
        a = Math.pow(vx, 2) + Math.pow(vy, 2), 
        b = 2 * (vx * dx + vy * dy), 
        c = Math.pow(dx, 2) + Math.pow(dy, 2) - 4 * Math.pow(r, 2), 
        dis = Math.pow(b, 2) - 4 * a * c;
    if (dis < 0) {
        //no collision
        return false;
    } else {
        let t1 = 0.5 * (-b - Math.sqrt(dis)) / a, 
            t2 = 0.5 * (-b + Math.sqrt(dis)) / a,
            t = Math.min(t1, t2);
        if (t < 0) {
            //time cannot be smaller than zero
            return false;
        }
        return {
            ball1: {x: ball1_x + t * ball1_vx, y: ball1_y + t * ball1_vy},
            ball2: {x: ball2_x + t * ball2_vx, y: ball2_y + t * ball2_vy},
            time: t
        };
    }
}
calcCollisionBallCoordinates(ball1_x,ball1_y,ball2_x,ball2_y,ball1_vx,ball1_vy,ball2_vx,ball2_vy,r){
设dx=ball2_x-ball1_x,
dy=ball2_y-ball1_y,
vx=ball2_vx-ball1_vx,
vy=ball2vy-ball1vy,
a=数学功率(vx,2)+数学功率(vy,2),
b=2*(vx*dx+vy*dy),
c=数学功率(dx,2)+数学功率(dy,2)-4*数学功率(r,2),
dis=数学功率(b,2)-4*a*c;
如果(dis<0){
//无碰撞
返回false;
}否则{
设t1=0.5*(-b-数学sqrt(dis))/a,
t2=0.5*(-b+数学sqrt(dis))/a,
t=数学最小值(t1,t2);
if(t<0){
//时间不能小于零
返回false;
}
返回{
ball1:{x:ball1_x+t*ball1_vx,y:ball1_y+t*ball1_vy},
ball2:{x:ball2_x+t*ball2_vx,y:ball2_y+t*ball2_vy},
时间:t
};
}
}

我不确定是否可以计算时间。在我发送的图像中,球在路上移动的时间相同(1帧)。很明显,球A移动到碰撞点的时间是(相对角度)远高于球B,因此我不确定这是否有效。对于碰撞,球必须在同一时间在同一点上相遇。是否要在没有实际碰撞的情况下找到轨迹的交点?这有什么意义?我已尝试将此计算用于实际数据(图像上的示例)但结果很尴尬。我得到的数据是:
x1=730,y1=497,x2=1560,y2=579,vx1=413,vy1=-231,vx2=-1010,vy2=-1190,r=100
并且我得到了
dis
变量负值,所以没有冲突。也许我做错了什么,但你们能在python中添加这些数字并检查解决方案吗?好的,当我再多想一想的时候,请注意在图形上不会发生碰撞,因为我忽略了时间。我想你是绝对正确的。当蓝球到达“碰撞点”时,金球会离它很远……用球检查公式,这些球会在时间上发生碰撞,它非常有效。谢谢!
calcCollisionBallCoordinates(ball1_x, ball1_y, ball2_x, ball2_y, ball1_vx, ball1_vy, ball2_vx, ball2_vy, r) {
    let dx = ball2_x - ball1_x, 
        dy = ball2_y - ball1_y,
        vx = ball2_vx - ball1_vx, 
        vy = ball2_vy - ball1_vy,
        a = Math.pow(vx, 2) + Math.pow(vy, 2), 
        b = 2 * (vx * dx + vy * dy), 
        c = Math.pow(dx, 2) + Math.pow(dy, 2) - 4 * Math.pow(r, 2), 
        dis = Math.pow(b, 2) - 4 * a * c;
    if (dis < 0) {
        //no collision
        return false;
    } else {
        let t1 = 0.5 * (-b - Math.sqrt(dis)) / a, 
            t2 = 0.5 * (-b + Math.sqrt(dis)) / a,
            t = Math.min(t1, t2);
        if (t < 0) {
            //time cannot be smaller than zero
            return false;
        }
        return {
            ball1: {x: ball1_x + t * ball1_vx, y: ball1_y + t * ball1_vy},
            ball2: {x: ball2_x + t * ball2_vx, y: ball2_y + t * ball2_vy},
            time: t
        };
    }
}