圆圈碰撞

我要开发一个两个球(圆圈)相撞的二维球类游戏。 现在我有确定碰撞点的问题(实际上,确定它们是否在X轴/ Y轴上碰撞)。 我有一个想法,当两个球的y坐标之间的差异大于x坐标差时,他们碰撞他们的y轴,否则,他们碰撞在他们的x轴。 我的想法是否正确? 我在游戏中实现了这个东西。 通常它运作良好,但有时它失败。 谁能告诉我,我的想法是对的? 如果没有,那么为什么,还有更好的办法?

通过x轴的碰撞,我的意思是圆的第1,第4,第5或第8个八分圆,y轴表示圆的第2,3,6或7个八分圆。

提前致谢!

圆圈之间的碰撞很容易。 想象一下有两个圈子:

  • C1与中心(x1,y1)和半径r1;
  • C2与中心(x2,y2)和半径r2。

想象一下,在这两个中心点之间有一条线路正在运行。 根据定义,从中心点到任一圆的边缘的距离等于它们各自的半径。 所以:

  • 如果圆的边缘接触,中心之间的距离是r1 + r2;
  • 任何更大的距离和圆不接触或碰撞; 和
  • 然后再碰撞。

所以你可以检测到碰撞,如果:

(x2-x1)^2 + (y1-y2)^2 <= (r1+r2)^2 

意味着中心点之间的距离小于半径之和。

同样的原理可以应用于检测三维球体之间的碰撞。

编辑:如果你想计算的碰撞点,一些基本的三angular可以做到这一点。 你有一个三angular形:

  (x1,y1) |\ | \ | \ sqrt((x2-x1)^2 + (y2-y1)^2) = r1+r2 |y2-y1| | \ | \ | X \ (x1,y2) +------+ (x2,y2) |x2-x1| 

expression式|x2-x1||y2-y1| 是绝对值。 所以对于angular度X:

  |y2 - y1| sin X = ------- r1 + r2 |x2 - x1| cos X = ------- r1 + r2 |y2 - y1| tan X = ------- |x2 - x1| 

一旦你有angular度,你可以通过将它们应用到一个新的三angular形来计算交点:

  + |\ | \ b | \ r2 | \ | X \ +-----+ a 

哪里:

  a cos X = -- r2 

所以

 a = r2 cos X 

从以前的公式:

  |x2 - x1| a = r2 ------- r1 + r2 

一旦你有a和b,你可以根据(x2,y2)偏移(a,b)来计算碰撞点。 你甚至不需要为此计算任何正弦,余弦或反正弦或余弦。 或者就此而言,任何平方根。 所以速度很快

但是,如果你不需要一个确切的angular度或碰撞点,只需要八分圆,就可以通过理解有关切线的东西来进一步优化:

  • 对于0 <= X <= 45度,0 <= tanX <= 1;
  • 对于45 <= X <= 90,tanX> = 1
  • 对于0> = X => -45,0> = tan X> = -1;
  • 对于-45> = X => -90,tan X <= -1; 和
  • tan X = tan(X + 180)= tan(X-180)。

这四个范围对应于圆的四个八分圆。 其他四个偏移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轴上实际碰撞,它们会以特定的angular度相撞。 除此之外,你不需要那个angular度。 你想要碰撞vector。 这两个圆的中心碰撞时的差别是:

 collision vector: d12= (x2-x1,y2-y1) = (dx,dy) actual distance: r12= sqrt( dx*dx + dy*dy ) 

请注意,在计算实际距离时,已经计算了上面的dx和dy,所以您不妨跟踪它们以达到这样的目的。 您可以使用这个碰撞vector来确定球的新速度 – 您将最终通过一些因素来缩放碰撞vector,并将其添加到旧的速度中……但是,要回到实际的碰撞点:

 collision point: pcollision= ( (x1*r2+x2*r1)/(r1+r2), (y1*r2+y2*r1)/(r1+r2) ) 

为了弄清楚如何find球的新速度(通常从整个情况来看更有意义),你应该find一本高中物理学的书或者相当的书。 不幸的是,我不知道一个好的networking教程 – build议,任何人?

哦,如果还想继续使用x / y轴的话,我想你已经明白了:

 if( abs(dx) > abs(dy) ) then { x-axis } else { y-axis } 

至于为什么它可能会失败,没有更多的信息很难说,但你可能有一个问题,你的球移动得太快,并在一个单一的时间步长相互传递。 有办法解决这个问题,但最简单的方法是确保他们不会太快…

这个网站解释了物理 , 派生algorithm ,并提供二维球碰撞的代码 。

在此函数计算出八分圆后,计算以下内容:碰撞点相对于物体的质心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; } 

它们相互碰撞的点在两个圆的中点之间的线上,并且它与中点的距离是相应圆的半径。

我同意提供的答案,他们是非常好的。
我只想指出一个小小的陷阱:如果球的速度很高,那么你可能会错过碰撞,因为在给定的步骤中,球不会相交。
解决scheme是解决运动方程,find正确的碰撞时刻。

无论如何,如果你要实施你的解决scheme(比较X轴和Y轴),你会得到老乒乓球! http://en.wikipedia.org/wiki/Pong
🙂

为了更直接地回答你的问题:是的,根据你的规则和要求,如果Y的差值大于X的差值,那么这些球在Y轴上碰撞。

如果这是你正在执行的,那么你得到了正确的答案“X或Y轴碰撞?”的问题。 但是我认为你在这里得到这么多答案的原因,你似乎无法使用,也是这样

  • 你问错误的问题(不在这里 – 在你的程序中); 要么

  • 你没有正确地使用答案。

我敢肯定,我们很多人已经编制了弹跳球程序,我怀疑我们谁也没有试图build立基于八分圆和轴的碰撞模型。 所以我怀疑,要么你有一个非常原始的新方法,或者你只是做错了。 因此,我build议回去检查一下你的方法和假设。