【问题标题】:What is the easiest way to calculate position of balls on collision?计算碰撞球位置的最简单方法是什么?
【发布时间】:2021-01-13 20:22:38
【问题描述】:

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

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

因此,我将每个动作划分为多个扇区并计算点之间的距离是否等于或小于球的直径,当必须在每帧中计算许多球(如斯诺克球)时,这会减慢过程,加上这种方式并不总是 100% 准确,而且击球后球可能会以不准确的角度进入(差别不大,但在斯诺克中很重要)。

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

【问题讨论】:

    标签: javascript geometry collision-detection


    【解决方案1】:

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

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

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

    B'(t) = (B0 - A0) + (VB - VA) * t = B0' + V'*t
    

    我们只需要找到碰撞二次方程的解distance=2R

     (B0'.X + V'.X*t)^2 + (B0'.X + V'.Y*t)^2 = 4*R^2
    

    在未知时间t 求解这个方程,我们可能会遇到以下情况:无解(无碰撞)、单一解(仅触摸事件)、两个解 - 在这种情况下,较小的 t 值对应于物理时刻碰撞。

    示例(抱歉,在 Python 中,** 是幂运算符):

    def collision(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  solve this equation
        #coefficients
        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
        if dis<0:
            return None
        else:
            t = 0.5*(-b - dis**0.5)/a  ##includes case of touch when dis=0
            return [(ax + t * vax, ay + t * vay), (bx + t * vbx, by + t * vby)]
    
    print(collision(0,0,100,0,50,50,-50,50,10))  #collision
    print(collision(0,0,100,0,50,50,-50,80,10))  #miss
    print(collision(0,0,100,0,100,0,99,0,10))    #long lasting chase along OX axis
    
    
    [(40.0, 40.0), (60.0, 40.0)]
    None
    [(8000.0, 0.0), (8020.0, 0.0)]
    

    【讨论】:

    • 我不确定是否可以计算时间。在我发送的图像中,球在相同的时间内移动(1 帧)。很明显,球 A 移动到碰撞点的时间(从相对角度来看)远高于球 B,所以我不确定这是否可行。
    • 因为碰撞球必须在同一时间在同一点相遇。你想在没有真正碰撞的情况下找到轨迹的交点吗?这样做有什么意义?
    • 我曾尝试将此计算与真实数据(图像上的样本)一起使用,但结果很尴尬。我拥有的数据是:x1=730, y1=497, x2=1560,y2=579, vx1=413, vy1=-231, vx2=-1010, vy2=-1190, r=100,我得到了dis 变量负数,所以没有冲突。也许我做错了什么,但是你能在你的 python 中添加这些数字并检查解决方案吗?
    • 好吧,当我多想一点时,图形上的球不会碰撞,因为我忽略了时间。我想你是绝对正确的。当蓝球到达“碰撞点”时,金球会远离它.....
    • 检查过的带有球的公式,实际上会及时碰撞,而且效果很好。谢谢!
    【解决方案2】:

    关于 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
            };
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2014-01-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-12-18
      • 1970-01-01
      相关资源
      最近更新 更多