Answers:
注意:以下所有条件均假设球的表面无摩擦(因此不会开始旋转或反弹,因为它确实如此)。
碰撞时,球将碰到角球。当固体物体碰撞时,力将沿着所谓的表面法线(即垂直于碰撞点处的表面)作用。
由于它是球,因此垂直于表面的方向是球的中心。好的,所以我们知道了力的方向,力的大小呢?假设发生弹性碰撞(并且矩形不能移动),则球必须以与撞击时相同的速度反弹。
令(nDx,nDy)为碰撞后的速度,(oDx,oDy)为碰撞前的速度,(x,y)为球在碰撞点的位置。让我们进一步假设球碰撞的角在(0,0)。
以公式表示我们的见解,我们有:
(nDx, nDy) = (oDx, oDy) + c * (x, y)
length (nDx, nDy) = length (oDx, oDy)
等效于:
nDx = oDx + c * x
nDy = oDy + c * y
nDx^2 + nDy^2 = oDx^2 + oDy^2
将前两个方程式替换为最后一个方程式,我们得到:
(oDx + c * x)^2 + (oDy + c * y)^2 = oDx^2 + oDy^2
使用二项式定理扩展
(a+b)^2 = a^2 + 2ab + b^2
产量:
oDx^2 + 2 * oDx * c * x + (c * x) ^ 2 + oDy^2 + 2 * oDy * c * y + (c * y) ^ 2 = oDx^2 + oDy^2
2 * oDx * c * x + 2 * oDy * c * y + (c * x) ^ 2 + (c * y) ^ 2 = 0
(2 * oDx * x + 2 * oDy * y) * c + (x^2 + y^2) * c^2 = 0
这个二次方程式c
有两个解,其中一个为0。显然,这不是我们感兴趣的解,因为通常球的方向会因碰撞而改变。为了获得其他解决方案,我们将双方除以c并得到:
(2 * oDx * x + 2 * oDy * y) + (x^2 + y^2) * c = 0
那是:
c = -(2 * oDx * x + 2 * oDy * y) / (x^2 + y^2)
总而言之,我们有:
c = -(2 * oDx * x + 2 * oDy * y) / (x^2 + y^2)
nDx = oDx + c * x
nDy = oDy + c * y
编辑:在代码中:
if (collision) {
float x = ballX - cornerX;
float y = ballY - cornerY;
float c = -2 * (ballDx * x + ballDy * y) / (x * x + y * y);
ballDx = ballDx + c * x;
ballDy = ballDy + c * y;
}
一些实施注意事项:尽管您可以在模拟步骤之后用球的位置来近似(x,y),但是这种近似会改变偏转角度,因此非常引人注目,因此您的模拟步骤必须非常精细(也许这样球每步移动不超过其直径的1/20)。为了获得更准确的解决方案,您可以计算发生碰撞的时间,并在该时间拆分该模拟步骤,即执行一个局部步骤直到碰撞点,然后执行另一个局部步骤以完成其余步骤。
编辑2:计算影响点
令r为半径,(x0,y0)为位置,(dx,dy)为模拟步骤开始时球的速度。为简单起见,让我们进一步假设所讨论的角位于(0,0)。
我们知道:
(x,y) = (x0, y0) + (dx, dy) * t
我们想要
length(x,y) = r
那是
(x0 + dx * t) ^ 2 + (y0 + dy * t) ^ 2 = r^2
x0^2 + 2 * x0 * dx * t + dx^2 * t^2 + y0^2 + 2 * y0 * dy * t + dy^2 * t^2 = r ^ 2
(dx^2 + dy^2) * t^2 + (2 * x0 * dx + 2 * y0 * dy) * t + (x0^2 + y0^2 - r^2) = 0
\____ _____/ \____________ ___________/ \_______ ________/
\/ \/ \/
a b c
那是t中的二次方程。如果有区别
D = b^2 - 4 * a * c
如果为负,则没有解决方案,即,球永远不会撞到当前路线的角落。否则,它的两个解由
t1 = (-b - sqrt(D)) / (2 * a)
t2 = (-b + sqrt(D)) / (2 * a)
我们对碰撞开始的时间感兴趣,这是更早的时间t1
。
您的方法将变为:
// compute a,b,c and D as given above
if (D >= 0) {
t = (-b - sqrt(D)) / (2 * a);
if (0 < t && t <= ts) {
// collision during this timestep!
x = x + t * dx;
y = y + t * dy;
ts = ts - t;
// change dx and dy using the deflection formula
}
}
x = x + ts * dx;
y = y + ts * dy;
At the moment of collision, the ball will be touching the corner
但是我没有看到这种近似的合理性(它必须是一种近似,因为它不是正确的-球在两个位置接触,两个都不在角落)。
运动学就是选择正确的参考系,因为对于计算最方便。
在这里,我们将首先定义变换T,该变换将我们的轴分解为与球的中心和角之间的线平行(x')和垂直(y')的分量。逆变换T *将恢复我们的原始坐标系。
在这个新的参考系中,通过反射(以及物理学的时间和空间对称性),我们得到了接触M的速度变换(一个点冲量),它使x'分量反转而使y'分量不变。用矩阵术语来说,这是对角矩阵,对角线上有-1和1。
那么碰撞后的速度就是:V' = T *。中号。Ť。VO。
的碰撞时吨然后只为溶液(Ť。请)+(X。Ť。VO)(吨)= - [R ,其中X是X轴投影算子和- [R是球的半径。重新排列,我们得到
吨 =([R - (Ť。景点))/((X。Ť。VO)(吨))
这具有将所有复杂的数学都埋入严格编写,测试和调试的标准图形库中的明显优势。对于2D和3D情况,此解决方案也相同-只需切换图形库即可。最后,它强调指出,在解决任何物理问题之前,首先应考虑适当的参考系。总是有NIH的诱惑,但是实际上,当可以提供更多简洁的解决方案时,这仅仅是bug的秘诀。