9 - 更写实的动画:模拟速度、加速度、重力、回弹、动量损失、冲量


接下来我们通过每帧动画, 模拟平面上的一些的物理运动状态。以下的时间相关的参数均是每帧计算的参数而不是每秒计算的参数。

速度

速度是一个矢量, 在平面上, 可以把矢量的速度分解为水平/垂直方向的标量分量。

定义矢量速度为 v, 矢量速度的角度为 rad(单位弧度), 分解成的水平速度分量为 vx, 垂直速度分量为 vy, 那么可以通过以下的计算互转:

//  通过矢量速度计算水平/垂直分量
vx = v * Math.cos(rad)
vy = v * Math.sin(rad)
//  通过水平/垂直分量计算矢量速度
rad = Math.atan2(vy, vx)
v = Math.sqrt(vx * vx + vy * vy)

在帧动画里, 让物体每帧位移(vx, vy)个单位, 物体即实现了匀速直线运动。可以通过以下这个例子手动调节速度查看效果。

加速度

加速度是速度的速度, 也是一个矢量, 它的计算方式同速度完全一样, 不同的是它是作用在速度上。

定义加速度的水平分量为 ax, 垂直分量为 ay, 那么物体每帧运动时的计算如下:

vx += ax
vy += ay
obj.x += vx
obj.y += vy

可以通过以下这个例子查看效果

重力

重力也是一种加速度, 它是属于物体之外的环境的参量。在加速度计算完毕之后, 再加上重力加速度的影响即可。

定义重力加速度为 g, 它的作用方向是垂直向下, 那么运动计算方式如下:

vx += ax
vy += ay
vy += g
obj.x += vx
obj.y += vy

速度回弹, 动量损失, 冲量

假设物体从空中自由落体降落, 当它触碰到边界(地面) 的时候, 可以令速度方向反向, 达到一种被边界弹回去的效果。

回弹系数可以是 [-1, 0]之间的值。当回弹系数是-1时, 没有动量损失; 当系数是0时, 全部动量损失, 物体立刻停止运动。

再进一步, 点击屏幕, 给物体施加一个向上的冲量, 让物体有能力向上跳跃。理论上来说, 瞬时冲量应该是那一帧施加一个加速度; 但是实际代码中, 这样的效果并不理想, 通常是直接改写速度为一个冲量值。

例子如下: 栗子