2.2 弹道的计算
第二个问题就是弹道的模拟了。一般情况下,各类游戏引擎就是专门用来计算这个的,可是我需要的仅仅是简单的2D抛物线计算而已,完全没必要兴师动众地去移植一款大型的游戏引擎,所以就自己动手写一个吧。
首先在不考虑空气阻力的理想情况下简化土豆抛射运动,如图2.4所示。
图2.4 在不考虑空气阻力的理想情况下简化的土豆抛射运动
如果土豆不是垂直向上发射,而是与地平面呈φ角度射出,那么,这物体会按照抛物线轨迹移动,它的水平运动与垂直运动可以通过下式计算。
x(t)=(v0cosφ)t
y(t)=(v0sin φ)t-(gt2)/2
vx(t)=v0cosφ
v y(t)=v0sin φ-gt
R=v0tcosφ
t=(2v0sinφ)/g
其中,R代表土豆的抛射距离,v0代表抛射的初速度。
如果假设土豆是以初速度50m/s,与地平面呈30°角射出。根据公式,不考虑任何干扰因素,它会飞到220.7m远的地方。如果真砸到怪兽,估计会很痛。
以上是假设了一个具体数字来帮助大家理解。在这个游戏程序中,我们需要解决的问题就是如何写一个程序来计算任意φ时的土豆运动轨迹。一旦这个土豆在某时刻的位置达到怪兽的边界坐标内,那么即说明怪兽被击中;否则当土豆运动到0高度时,则说明碰撞到地面,没有击中目标。
为了能让程序实时地计算出土豆的位置,我们回顾一下那个遗忘了很多年却又十分神奇的牛顿定律。通常线性的运动方程表示如下。
F=mdv/dt
换个形式让它可以被积分
dv/dt=F/m
dv=(F/m)dt
可以认为速度上的无穷小的变化量dv等于(F/m)乘以时间无穷小的变化量。可是在计算机中我们是无法让时间无穷小的,因此我们只能取一个较小的离散时间增量Δt,那么Δv就可以通过下式表示。
Δv=(F/m)Δt
Δv是在离散的时间片段内速度的改变值,因此当前的速度取决于之前的速度与速度变化之和。
v(t)+Δv=v(t)+(F/m)Δt
在初始条件下,vt为土豆离开炮筒时的速度。同理,位置的计算也可以用类似的方法表示。对于风力的影响,我们可以把它简化为在水平方向上的恒定加速度,然后用与垂直方向相同的方法来处理。
经过这样的转化和简化,以上微分方程问题就适合数字计算机来计算了,这就是游戏引擎中常用的所谓“欧拉积分法”。虽然这种方式的计算精度不高,只是对函数曲线进行了多边形近似,但是如果把离散时间尽量取得小一些,对付这种简单的小游戏还是绰绰有余了。搞明白了上面的内容,相关代码就简单了。我们只摘录其中最需要说明的部分。
…… xspeed=xspeed+ (float(wind_force)- 50.0)*0.0004; //计算离散时间内风对速度x分量的影响 yspeed=yspeed+force; //计算离散时间内重力对速度y分量的影 响 xpos = xpos + xspeed; //计算速度对位置x坐标的影响 ypos = ypos + yspeed; //计算速度对位置y坐标的影响 deg=(analogRead(A0)*0.0005)+ offset; //通过ADC采集电位器的角度信 息,经过转换后用于控制发射方向 xspeed_p = cos( deg )*6; //计算初始速度x分量 yspeed_p = sin( deg )*6; //计算初始速度y分量 ...... f(digitalRead(2)==0)//按下发射按钮 { ...... xspeed=xspeed_p; //给初始速度x 分量赋值 yspeed=yspeed_p; //给初始速度y 分量赋值 ...... } ......
在精心地调整各项参数之后,弹道的模拟效果还是比较满意的。