创客们的超级开源制作项目
上QQ阅读APP看书,第一时间看更新

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/mt

Δv是在离散的时间片段内速度的改变值,因此当前的速度取决于之前的速度与速度变化之和。

v(t)+Δv=v(t)+(F/mt

在初始条件下,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
    分量赋值
        ......
    }
    ......

在精心地调整各项参数之后,弹道的模拟效果还是比较满意的。