木匣子

Web/Game/Programming/Life etc.

小球碰撞实验

回顾了一下向量计算,用 js + canvas 写了一个小球碰撞实验,并用 Flash Actionscript 3.0 高级动画教程 里的方法做了简单的优化。

这里用的碰撞处理稍简单了一点,静态碰撞检测,不考虑小球的速度,只检测相交,然后做不相容处理,最后计算碰撞后的速度。

碰撞后的速度变化算法可以参考 Vectors for Flash2 moving balls 这一章节。这个教程使用动态处理,将小球的运动速度考虑进去,可以得到更逼真的碰撞。而且解决了小球速度太快相互越过对方的问题。如果英文不好的话,可以看这里

另外处理速度的时候,直接交换碰撞轴上两球的速度分量(按质量1:1的弹性碰撞来分配)。如果想要更加真实的效果,可以考虑增加质量变化,并使用弹性碰撞公式来计算碰撞后的速度。

其它资料

The World Of Bouncing Balls

我在整理收藏夹的时候发现一篇非常棒的文章,是关于我一个很喜欢的游戏 n-game 的,这是由他们官方编写的碰撞检测教程:
http://www.metanetsoftware.com/technique/tutorialA.html

update 140108

在实践的过程中遇到了一个细节上的问题。我用的是欧拉方法处理小球运动,起初我先处理位移,然后再处理速度,最后处理边界碰撞:

# 伪代码
p += v
v += g # wrong here
if (p.y < r):
  p.y = r
  v.y *= -0.9

这导致第二次帧循环的时候小球向上轻微跃起,然后又落下,如此往复出现抖动。后来我观察 N tutorial A 的演示的时候,发现它的小球在地面的十分平稳,没有出现抖动。而 N 使用的是 Verlet 积分方法处理物体运动。经过分析发现,其实不应该在处理位移后才处理速度,而应该在处理位移之前处理速度:

v += g # do this first
p += v
if (p.y < r):
  p.y = r
  v.y *= -0.9

这样即使有轻微的反弹速度,也会在第二次帧循环处理位移之前被重力抵消掉。实际上 Verlet 积分方法隐含了速度以及加速度的处理过程,所以没有将这些细节问题暴露给开发者。