[英]circle-circle collision
我将开发一个二维球类游戏,其中两个球(圆圈)发生碰撞。 现在我遇到了确定碰撞点的问题(实际上,确定它们是否在 x 轴/y 轴上发生碰撞)。 我有一个想法,当 2 个球的 y 坐标差大于 x 坐标差时,它们会在 y 轴上发生碰撞,否则,它们会在 x 轴上发生碰撞。 我的想法对吗? 我在我的游戏中实现了这个东西。 通常它运行良好,但有时会失败。 谁能告诉我我的想法对不对? 如果不是,那么为什么,还有更好的方法吗?
x 轴上的碰撞是指圆的第 1、4、5 或 8 个八分圆,y 轴是指圆的第 2、3、6 或 7 个八分圆。
提前致谢!
圆圈之间的碰撞很容易。 想象有两个圈子:
想象一下,在这两个中心点之间有一条直线。 根据定义,从中心点到每个圆的边缘的距离等于它们各自的半径。 所以:
因此,您可以在以下情况下检测碰撞:
(x2-x1)^2 + (y1-y2)^2 <= (r1+r2)^2
表示中心点之间的距离小于半径的总和。
可以将相同原理应用于检测三维球体之间的碰撞。
编辑:如果要计算碰撞点,则可以使用一些基本的三角函数来实现。 你有一个三角形:
(x1,y1)
|\
| \
| \ sqrt((x2-x1)^2 + (y2-y1)^2) = r1+r2
|y2-y1| | \
| \
| X \
(x1,y2) +------+ (x2,y2)
|x2-x1|
表达式|x2-x1|
和|y2-y1|
是绝对值。 因此对于角度X:
|y2 - y1|
sin X = -------
r1 + r2
|x2 - x1|
cos X = -------
r1 + r2
|y2 - y1|
tan X = -------
|x2 - x1|
一旦有了角度,就可以通过将它们应用于新三角形来计算相交点:
+
|\
| \
b | \ r2
| \
| X \
+-----+
a
哪里:
a
cos X = --
r2
所以
a = r2 cos X
根据以前的公式:
|x2 - x1|
a = r2 -------
r1 + r2
一旦有了a和b,就可以根据(x,y2)偏移(a,b)的方式计算碰撞点。 您甚至不需要为此计算任何正弦,余弦或反正弦或余弦。 或与此相关的任何平方根。 这样很快。
但是,如果您不需要精确的碰撞角度或碰撞点,而只想八分圆,则可以通过了解切线来进一步优化它,这是:
这四个度范围对应于圆的四个八分圆。 其他四个偏移180度。 如上所示,正切可以简单地计算为:
|y2 - y1|
tan X = -------
|x2 - x1|
失去绝对值,该比率将告诉您碰撞在四个八分之一中(通过上述切线范围)。 要计算出确切的八分圆,只需比较x1和x2以确定哪一个最左边。
另一个碰撞上的碰撞的八分圆是偏移的(C1上的八分圆1表示C2、2和6、3和7、4和8等上的八分圆)。
正如cletus所说,您想使用两个球的半径之和。 您要计算球的中心之间的总距离,如下所示:
Ball 1: center: p1=(x1,y1) radius: r1
Ball 2: center: p2=(x2,y2) radius: r2
collision distance: R= r1 + r2
actual distance: r12= sqrt( (x2-x1)^2 + (y2-y2)^2 )
只要(r12 <R),就会发生碰撞。 正如Artelius所说,它们实际上不应在x / y轴上发生碰撞,而是以特定角度发生碰撞。 除此以外,您实际上并不想要那个角度。 您想要碰撞矢量。 这是两个圆心碰撞时的中心之间的差异:
collision vector: d12= (x2-x1,y2-y1) = (dx,dy)
actual distance: r12= sqrt( dx*dx + dy*dy )
请注意,在计算实际距离时,您已经在上面计算了dx和dy,因此出于这种目的,您最好也可以对其进行跟踪。 您可以使用此碰撞向量来确定球的新速度-您将最终通过某些因素缩放碰撞向量,并将其添加到旧速度中……但是,要返回到实际碰撞点:
collision point: pcollision= ( (x1*r2+x2*r1)/(r1+r2), (y1*r2+y2*r1)/(r1+r2) )
为了弄清楚如何找到球的新速度(通常从整体上讲更有意义),您可能应该找到一本高中物理书或同等学历书。 不幸的是,我不知道一个好的网络教程-建议,有人吗?
哦,如果仍然想坚持使用x / y轴,我认为您可以使用以下方法:
if( abs(dx) > abs(dy) ) then { x-axis } else { y-axis }
至于为什么它可能会失败,很难在没有更多信息的情况下知道,但是您可能会遇到一个问题,即您的球移动得太快,并且在一个时间步中彼此直传。 有一些方法可以解决此问题,但是最简单的方法是确保它们不会太快地移动...
该站点解释了物理原理 , 推导了算法 ,并提供了2D球碰撞的代码 。
此函数计算以下内容后计算八分圆:碰撞点相对于物体质心的位置a; 碰撞点相对于质心a的位置
/**
This function calulates the velocities after a 2D collision vaf, vbf, waf and wbf from information about the colliding bodies
@param double e coefficient of restitution which depends on the nature of the two colliding materials
@param double ma total mass of body a
@param double mb total mass of body b
@param double Ia inertia for body a.
@param double Ib inertia for body b.
@param vector ra position of collision point relative to centre of mass of body a in absolute coordinates (if this is
known in local body coordinates it must be converted before this is called).
@param vector rb position of collision point relative to centre of mass of body b in absolute coordinates (if this is
known in local body coordinates it must be converted before this is called).
@param vector n normal to collision point, the line along which the impulse acts.
@param vector vai initial velocity of centre of mass on object a
@param vector vbi initial velocity of centre of mass on object b
@param vector wai initial angular velocity of object a
@param vector wbi initial angular velocity of object b
@param vector vaf final velocity of centre of mass on object a
@param vector vbf final velocity of centre of mass on object a
@param vector waf final angular velocity of object a
@param vector wbf final angular velocity of object b
*/
CollisionResponce(double e,double ma,double mb,matrix Ia,matrix Ib,vector ra,vector rb,vector n,
vector vai, vector vbi, vector wai, vector wbi, vector vaf, vector vbf, vector waf, vector wbf) {
double k=1/(ma*ma)+ 2/(ma*mb) +1/(mb*mb) - ra.x*ra.x/(ma*Ia) - rb.x*rb.x/(ma*Ib) - ra.y*ra.y/(ma*Ia)
- ra.y*ra.y/(mb*Ia) - ra.x*ra.x/(mb*Ia) - rb.x*rb.x/(mb*Ib) - rb.y*rb.y/(ma*Ib)
- rb.y*rb.y/(mb*Ib) + ra.y*ra.y*rb.x*rb.x/(Ia*Ib) + ra.x*ra.x*rb.y*rb.y/(Ia*Ib) - 2*ra.x*ra.y*rb.x*rb.y/(Ia*Ib);
double Jx = (e+1)/k * (Vai.x - Vbi.x)( 1/ma - ra.x*ra.x/Ia + 1/mb - rb.x*rb.x/Ib)
- (e+1)/k * (Vai.y - Vbi.y) (ra.x*ra.y / Ia + rb.x*rb.y / Ib);
double Jy = - (e+1)/k * (Vai.x - Vbi.x) (ra.x*ra.y / Ia + rb.x*rb.y / Ib)
+ (e+1)/k * (Vai.y - Vbi.y) ( 1/ma - ra.y*ra.y/Ia + 1/mb - rb.y*rb.y/Ib);
Vaf.x = Vai.x - Jx/Ma;
Vaf.y = Vai.y - Jy/Ma;
Vbf.x = Vbi.x - Jx/Mb;
Vbf.y = Vbi.y - Jy/Mb;
waf.x = wai.x - (Jx*ra.y - Jy*ra.x) /Ia;
waf.y = wai.y - (Jx*ra.y - Jy*ra.x) /Ia;
wbf.x = wbi.x - (Jx*rb.y - Jy*rb.x) /Ib;
wbf.y = wbi.y - (Jx*rb.y - Jy*rb.x) /Ib;
}
它们碰撞的点在两个圆的中点之间的线上,其与任一中点的距离为相应圆的半径。
我同意提供的答案,它们非常好。
我只想向您指出一个小陷阱:如果球的速度很高,您可能会错过碰撞,因为在给定的步骤中,圆永远不会相交。
解决方案是求解运动方程并找到正确的碰撞时刻。
无论如何,如果您实施解决方案(在X和Y轴上进行比较),您将得到很好的老式乒乓球! http://en.wikipedia.org/wiki/庞
:)
要更直接地回答您的问题:是的,根据您布置的规则和要求,如果Y的差异大于X的差异,那么这些球会在Y轴上碰撞。
如果这是您要实现的,那么您将得到对“ X或Y轴碰撞?”问题的正确答案。 但我认为您在这里获得如此多答案而似乎无法利用的原因是
您问的是错误的问题(不在此处-在您的程序中); 要么
您没有正确使用答案。
我敢肯定,我们中的许多人都编写了弹跳球程序,而且我怀疑我们当中没有人曾尝试过根据八分圆和轴建模碰撞。 因此,我怀疑您是采用了非常原始的新方法,还是只是做错了。 因此,我建议返回并检查您的方法和假设。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.