<p>在不回答你的问题的情况下,我想评论一下你的实施策略,并推荐一种新的方法。以极坐标的形式表示球的速度,如<code>ball.angle</code>和<code>ball.speed</code>。</p>
<p>我想这对你来说通常是不方便的。例如,在冲突代码中,您最终调用<code>atan2</code>将向量(<code>dx</code>,<code>dy</code>)转换为角度,然后调用<code>sin</code>和<code>cos</code>将角度再次转换为向量。(同样,如果你试图将你的代码推广到三维空间,你会发现自己身处一个痛苦的世界。)所以,除非你有特殊的要求,需要极坐标,我建议你做其他人都做的事情,即用笛卡尔坐标表示球的速度作为矢量(<code>vx</code>,<code>vy</code>)。</p>
<p>我还建议改变你的物理方法,从静态的方法(“物体a当前是否与物体B发生碰撞?”)到a<em>dynamic</em>one(“对象a在下一个移动步骤中是否会与对象B发生碰撞?”)。在静态物理系统中,你经常在一个运动步骤结束时发现物体相互交叉,然后你必须找出使它们再次分离的最佳方法,这是很难做到的。</p>
<p>如果你同时做这两件事,你很容易在没有任何三角学的情况下弹起球。</p>
<p>第一步。使用<a href="http://en.wikipedia.org/wiki/Minkowski_addition" rel="nofollow noreferrer">Minkowski addition</a>将圆/圆碰撞转换为点/圆碰撞:</p>
<p><img src="https://i.stack.imgur.com/tNbA0.png" alt="Original problem at left shows small circle moving inside a large circle. Transformed problem at right shows point moving in circle whose radius is the difference between the radii of the circles in the original problem."/></p>
<p>第二步。考虑一个时间段,在该时间段中,球从<strong>p</strong>=(px,py)开始并移动<strong>v</strong>=(vx,vy)。它和圆相交吗?您可以使用<a href="http://garethrees.org/2009/02/17/physics/#section-4" rel="nofollow noreferrer">standard line segment/circle test</a>来实现这一点,但测试的意义是相反的。</p>
<p>第三步。找到碰撞点<strong>c</strong>=(cx,cy)。球从圆上反弹的方式与它从与该点的圆相切的线上反弹的方式相同。对于一个以原点为中心的圆,切向量只是(-cy,cx),我相信你可以找出如何计算其他圆的切向量。</p>
<p><img src="https://i.stack.imgur.com/YrjYW.png" alt="Figure described above"/></p>
<p>如何根据摩擦系数和恢复系数计算球的新路径。</p>
<p>第四步。别忘了,球可能还有一段距离要沿新向量移动。如果时间步长足够大或速度足够高,则可能在同一时间段内再次发生碰撞。</p>