XNA 3.0 Game Programming Recipes翻译4-4

4-4. 用加速度来控制速度

问题

       您想使您的模型加速很好,而不会从全速状态立即停止,反之亦然。下图显示一种你想要的加速度示意图。

 

       

 

方案

        定义加速度,你可以定义你的物体如何加速。这是你加到模型的每一帧的数值。

 

如何运作

       你要跟踪位置和模型的朝向,因为你要知道朝那个方向。本例中,你使模型只绕着Y轴旋转,只改变位置的XZ坐标。

    还有,因为下一刻的速度取决于当前的速度,所以你要跟踪当前速度。比用数字更好的方法是用速度向量来储存速度。向量包含模型前进的方向,长度表示速度。所以加这3个变量到你的类中:

 

    Vector3 modelPosition = new Vector3();  // 模型位置

    Float modelYRot = 0;                    // 模型方向

    Vector3 modelVelocity = new Vector3();  // 模型速度

 

    你也可以定义最大加速度和最大转向速度:

   

    const float modelMaxAcceleration = 30.0f;

    const float modelMaxTurnSpeed = 0.002f;

   

    Update方法中,检索从上一帧到现在过去的时间,并检测用户要模型前进还是转向:

   

    Float elapsedSeconds = (float)gameTime.ElapsedGameTime.Milliseconds / 1000.0f;

    Float forwardReq = 0;

    Float angleReq = 0;

    If(keyState.IsKeyDown(Keys.Up))

        forwardReq += 1.0f;

If(keyState.IsKeyDown(Keys.down))

        forwardReq -= 1.0f;

If(keyState.IsKeyDown(Keys.left))

        angleReq += 1.0f;

If(keyState.IsKeyDown(Keys.right))

        angleReq -= 1.0f;

 

        如果用户想要模型向前加速那么forwardReq的值就是绝对值。如果模型要减速或向反方向加速符号就为负。angleReq包含模型转左或转右。

   

冰上加速

    这段代码添加了加速度的基础知识:

 

Matrix rotMatrix = Matrix.CreateRotationY(angle);

        Vector3 forwardDir = Vector3.Transform(new Vector3(0,0,-1),rotMatrix);

        Velocity = velocity + elapsedTime * forwardReq * maxAccel * forwardDir;

        modelPosition += velocity;

        modelYRot += rotationReq * maxRotSpeed * velocity.Length();

 

        前两行计算模型当前向前向量,因为需要知道模型的加速方向。这个向前向量是由默认(0,0,-1)向量绕向上Y轴旋转的。

 

注意 本节,模型只能绕Y轴旋转,所以向前方向只能绕Y轴。

 

第三行计算速度。你从上一个速度开始,第二个增量基于用户输入。传递的次数越多,你越需要调整这个速度。用户要求的加速度越大,你也越需要调整这个速度。作为最后的因素,你把最大加速度写到账户。把所有3个向量乘到一起,得到这一帧你总共要调整多少速度。你用forwardDir向量乘这个值得出你要加到这一帧的速度向量。

 

注意 如果没有被应用旋转,无论速度和moveDirection将指向同一个方向,这使速度向量越来越大,使您的模型更快。

 

        最后,Vector3加到模型的位置,并旋转模型。模型移动越快,就旋转得越快。

    用这个代码,要注意两个缺陷。第一,你的模型不会减速且没有最大速度。你想像4-9一样增加速度并在某个最大速度饱和。用这个代码,你的模型会保持相同加速度加速。

    第二,如果模型非常快的转入一个方向,你旋转模型后,他还是朝着相同的方向前进。如果是在冰上,这非常好,但实际上可能不是你想要的。

 

添加摩擦

事实上,模型的速度会由于和空气,平面等的摩擦力减少,也适用内部机器。当你停止模型加速,摩擦会使你的模型减速直到完全停止。当你保持加速,摩擦会让你的速度在一个水平饱和。代码如下:

 

Velocity = velocity * (1 – friction * elapsedTime) + elaspedTime * forwardReq * maxAccel * forwardDir;

 

两帧之间有更多次的摩擦影响,所以你要把传入的摩擦值和摩擦次数的相乘。

 

    只保持向前部分

        虽然你的模型有更自然的方法加速,但当他旋转时仍移动的有点笨拙。通常你只想你的模型沿着向前方向移动。

        为此,你想知道模型沿当前方向的速度向量。这就是点积要做的:组合速度向量在向前向量上,返回组建后的向量长度。

 

       

 

        所以更新速度后用如下代码:

       

        Float forwardSpeed = Vector3.Dot(velocity, forwardDir);

        Velocity = forwardSpeed * forwardDir;

        modelPosition += velocity * elapsedTime;

        modelYRot += rotationReq * maxRotSpeed * forwardSpeed;

 

        forwardSpeed变量指出速度向量的向前部分。你把这个值和向前方向乘并存为新速度向量。这样模型只沿着向前方向移动。

 

注意 forwardSpeed的额外的优势是不论模型向前向后都表示为绝对值。这和velocity.Length()矛盾,它永远返回绝对值。

 

扩展阅读

    您可以扩展此说明到对象允许多个加速度对模型的影响,例如,在重力加速度。您可以通过综合加速度,并把它作为forwardDir

转载于:https://www.cnblogs.com/XNAconglele/archive/2009/08/28/1555529.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值