[翻译]XNA 3.0 Game Programming Recipes之twenty-one
PS:自己翻译的,转载请著明出处格
4-4 使用加速控制速度
问题
您想使您的模型很好的加速,而不是将从停止到立即全速,反之亦然。图4-9显示了你想要的这种增加速度。
解决方案
加入加速速,您可以定义您的模型以多快的速度增加。这是一个数量值的速度你想把它添加到当前模型的每一祯的速度中。
它是如何工作的
您将需要掌握你的模型旋转和它的位置 ,因为您需要知道哪个方向是前进方向。在这个例子中,你让模型只围绕Up的y轴旋转,同时只能在X和Z坐标轴上移动他们的位置。见4-7节如果您想模型离开表面,这要完全根据X和Z坐标。
此外,由于模型的下一个速度基于你当前的速度,你会需要追踪当前的速度。而不是只储存了一些速度,你将存储速度矢量。这包含模型当前准备去的速度矢量的方向,而其长度显示的速度。因此,这三个变量添加到您的类中:
Acceleration on Ice
这一段代码添加了加速的基础代码
注意:在此节,模型只能被围绕y轴旋转,所以前进的方向依靠围绕着Up的y轴旋转。见2-3,2-4节,如需有关计算前进向量的全三维或四元轮换参看上述章节。
第二行代码是计算速度,是最重要的一个。从上一个速度开始,而第二个周期内增加了一个新的载向量基于用户输入。更多的时间已过去了直到最后一祯,更需要调整这个速度。 此外,用户需要较大的加速度,更需要调整速度。作为最后的因素,你采取的最大加速度into account。您乘所有三个因素,给你一个值,表明您是否需要调整你的速度在这一祯中。因为你需要一个Vector3去增加这个速度,你乘这值用forwardDir去获取向量,要添加到此帧中的速度。
注意 如果没有旋转被应用,velocity和moveDirection都会指出相同的方向,这将导致velocity向量变大,模型速度变快。
最后,这Vector3添加到您模型的位置 ,和模型的旋转被调整。您的模型移动的越快,它旋转的也越快。
当您使用此代码,您会发现两个漏洞。首先,您的模型绝不会放慢, 它没有一个最高速度。你想要的速度增加如图4-9 和达到在某一个最高速度。使用此代码,您模型将以同样的速度继续加快。
其次,如果模型会非常快朝一个方向,在您旋转模型后,它将仍然会朝同一方向。这很不错,如果您模型正在冰面上移动, 但总的来说,这不是你想要的。
增加摩擦
在现实生活中,你模型的速度将减少,因为在模型和空中,地面之间都有摩擦,当应用时,内部的机械摩擦。当模型停止加速,摩擦会导致速度下降,直到模型完全停止。 当你继续加速,摩擦将导致速度保持在某一个水平..
您可以获取摩擦,减少上一个速度在以往的基础上,最重要的是。那个下一行添加摩擦到你的模型中:
Keeping Only the Forward Component
虽然您的模型将加快用一个更加自然的方法,现在仍然动作有点笨拙当它旋转时(除非您要创建一个空间或冰打滑游戏) 。一般来说,您希望您的模型将只在其前进方向。
为此,你想知道有多少目前的速度矢量是沿模型的前进后退方向 。这正是一个dot product做的: 它设计的速度(V)向量在前进向量(F)所示,图4-10,并返回投影向量(M)的长度
在你更新你的速度之后,使用这个代码:
注意:forwardSpeed变量的一个额外优点是一个正数不管模型是前进还是后退。这对velcotiy.Length()是矛盾的,它总返回一个正值。
代码
Accelerate方法列出了模型下一个调整的位置,速度和旋转, 同时加速到一个值。您可能需要添加这些连同最大的加速度和模型结构内的旋转速度。此外,您需要传递用户的输入,以及摩擦价值。
课外阅读
你可以扩展物体的加速度,用多个加速度影响这个模型,例如重力。为此,您可以总和这些加速度并把这个总和作为forwardDir 。
4-4 使用加速控制速度
问题
您想使您的模型很好的加速,而不是将从停止到立即全速,反之亦然。图4-9显示了你想要的这种增加速度。
解决方案
加入加速速,您可以定义您的模型以多快的速度增加。这是一个数量值的速度你想把它添加到当前模型的每一祯的速度中。
它是如何工作的
您将需要掌握你的模型旋转和它的位置 ,因为您需要知道哪个方向是前进方向。在这个例子中,你让模型只围绕Up的y轴旋转,同时只能在X和Z坐标轴上移动他们的位置。见4-7节如果您想模型离开表面,这要完全根据X和Z坐标。
此外,由于模型的下一个速度基于你当前的速度,你会需要追踪当前的速度。而不是只储存了一些速度,你将存储速度矢量。这包含模型当前准备去的速度矢量的方向,而其长度显示的速度。因此,这三个变量添加到您的类中:
1 Vector3 modelPosition=new Vector3();
2 float modelYRot=0;
3 Vector3 modelVelocity=new Vector3();
您还可以定义模型的最大加速度和转弯速度:
2 float modelYRot=0;
3 Vector3 modelVelocity=new Vector3();
1 const float modelMaxAcceleration=30.0f;
2 const float modelMaxTurnSpeed=0.002f;
在你的Update方法中,检索的数量秒钟过去直到最后一祯,测试用户想要模型如何移动:
2 const float modelMaxTurnSpeed=0.002f;
1 float elapsedSeconds=(float)gameTime.ElapsedGameTime.Miliseconds/1000.0f;
2 float forwardReq=0;
3 float angleReq=0;
4 if(keyState.IsKeyDown(Keys.Up))
5 forwardReq+=1.0f;
6 if(keyState.IsKeyDown(Keys.Down))
7 forwardReq-=1.0f;
8 if(keyState.IsKeyDown(Keys.Left))
9 angleReq+=1.0f;
10 if(keyState.IsKeyDown(Keys.Right))
11 angleReq-=1.0f;
forwardReq值将会是正值,如果用户想要模型向前加速。它也可能会是负值如果模型减速或者向后加速。angleReq包含了模型是否应该向左还是向右。2 float forwardReq=0;
3 float angleReq=0;
4 if(keyState.IsKeyDown(Keys.Up))
5 forwardReq+=1.0f;
6 if(keyState.IsKeyDown(Keys.Down))
7 forwardReq-=1.0f;
8 if(keyState.IsKeyDown(Keys.Left))
9 angleReq+=1.0f;
10 if(keyState.IsKeyDown(Keys.Right))
11 angleReq-=1.0f;
Acceleration on Ice
这一段代码添加了加速的基础代码
1 Matrix rotMatrix=Matrix.CreateRotationY(angle);
2 Vector3 forwardDir=Vector3.Transform(new Vector3(0,0,-1),rotMatrix);
3 velocity=velocity+elapsedTime*forwardReq*maxAccel*forwardDir;
4 modelPosition+=velocity;
5 modeYRot+=rotationReq*maxRotSpeed*velocity.Length();
头两行计算当前模型的前进向量,这是需要知道到哪个方向模型的加速度。这个前进向量是靠将默认的(0,0,-1)前进向量围绕Up的y轴旋转得到。2 Vector3 forwardDir=Vector3.Transform(new Vector3(0,0,-1),rotMatrix);
3 velocity=velocity+elapsedTime*forwardReq*maxAccel*forwardDir;
4 modelPosition+=velocity;
5 modeYRot+=rotationReq*maxRotSpeed*velocity.Length();
注意:在此节,模型只能被围绕y轴旋转,所以前进的方向依靠围绕着Up的y轴旋转。见2-3,2-4节,如需有关计算前进向量的全三维或四元轮换参看上述章节。
第二行代码是计算速度,是最重要的一个。从上一个速度开始,而第二个周期内增加了一个新的载向量基于用户输入。更多的时间已过去了直到最后一祯,更需要调整这个速度。 此外,用户需要较大的加速度,更需要调整速度。作为最后的因素,你采取的最大加速度into account。您乘所有三个因素,给你一个值,表明您是否需要调整你的速度在这一祯中。因为你需要一个Vector3去增加这个速度,你乘这值用forwardDir去获取向量,要添加到此帧中的速度。
注意 如果没有旋转被应用,velocity和moveDirection都会指出相同的方向,这将导致velocity向量变大,模型速度变快。
最后,这Vector3添加到您模型的位置 ,和模型的旋转被调整。您的模型移动的越快,它旋转的也越快。
当您使用此代码,您会发现两个漏洞。首先,您的模型绝不会放慢, 它没有一个最高速度。你想要的速度增加如图4-9 和达到在某一个最高速度。使用此代码,您模型将以同样的速度继续加快。
其次,如果模型会非常快朝一个方向,在您旋转模型后,它将仍然会朝同一方向。这很不错,如果您模型正在冰面上移动, 但总的来说,这不是你想要的。
增加摩擦
在现实生活中,你模型的速度将减少,因为在模型和空中,地面之间都有摩擦,当应用时,内部的机械摩擦。当模型停止加速,摩擦会导致速度下降,直到模型完全停止。 当你继续加速,摩擦将导致速度保持在某一个水平..
您可以获取摩擦,减少上一个速度在以往的基础上,最重要的是。那个下一行添加摩擦到你的模型中:
1 velocity=velocity*(1-friction*elapsedTime)+elapsedTime*forwardReq*maxAccel*forwarDir;
时间越长之间的最后时限和这一祯,摩擦应对你的模型的影响,所以你乘摩擦价值所需的时间。 Keeping Only the Forward Component
虽然您的模型将加快用一个更加自然的方法,现在仍然动作有点笨拙当它旋转时(除非您要创建一个空间或冰打滑游戏) 。一般来说,您希望您的模型将只在其前进方向。
为此,你想知道有多少目前的速度矢量是沿模型的前进后退方向 。这正是一个dot product做的: 它设计的速度(V)向量在前进向量(F)所示,图4-10,并返回投影向量(M)的长度
在你更新你的速度之后,使用这个代码:
1 float forwardSpeed=Vector3.Dot(velocity,forwardDir);
2 velocity=forwardSpeed*forwardDir;
3 modelPosition+=velocity*elapsedTime;
4 modelYRot+=rotationReq*maxRotSpeed*forwardSpeed;
该forwardSpeed变量显示速度向量的前进组成部分的长度。您用前进方向乘以这个值和存储它作为新的速度向量。这样,你确信模型将只沿着它的前进方向移动。2 velocity=forwardSpeed*forwardDir;
3 modelPosition+=velocity*elapsedTime;
4 modelYRot+=rotationReq*maxRotSpeed*forwardSpeed;
注意:forwardSpeed变量的一个额外优点是一个正数不管模型是前进还是后退。这对velcotiy.Length()是矛盾的,它总返回一个正值。
代码
Accelerate方法列出了模型下一个调整的位置,速度和旋转, 同时加速到一个值。您可能需要添加这些连同最大的加速度和模型结构内的旋转速度。此外,您需要传递用户的输入,以及摩擦价值。
1 private float Accelerate(ref Vector3 position,ref float angle,ref Vector3 velocity,float forwardReq,float rotationReq,float elapsedTime,float maxAccel,float maxRotSpeed,float friction)
2 {
3 Matrix rotMatrix=Matrix.CreateRotationY(angle);
4 Vector3 forwardDir=Vector3.Transform(new Vector3(0,0,-1),rotMatrix);
5 velocity=velocity*(1-friction*elapsedTime)+elapsedTime*forwardReq*maxAccel*forwardDir;
6 float forwardSpeed=Vector3.Dot(velocity,forwardDir);
7 velocity=forwardSpeed*forwardDir;
8 modelPosition+=velocity*elapsedTime;
9 modelYRot+=rotationReq*maxRotSpeed*forwardSpeed;
10 return forwardSpeed;
11 }
该方法返回forwardSpeed变量,这是负数,如果该模型将向后面运动。2 {
3 Matrix rotMatrix=Matrix.CreateRotationY(angle);
4 Vector3 forwardDir=Vector3.Transform(new Vector3(0,0,-1),rotMatrix);
5 velocity=velocity*(1-friction*elapsedTime)+elapsedTime*forwardReq*maxAccel*forwardDir;
6 float forwardSpeed=Vector3.Dot(velocity,forwardDir);
7 velocity=forwardSpeed*forwardDir;
8 modelPosition+=velocity*elapsedTime;
9 modelYRot+=rotationReq*maxRotSpeed*forwardSpeed;
10 return forwardSpeed;
11 }
课外阅读
你可以扩展物体的加速度,用多个加速度影响这个模型,例如重力。为此,您可以总和这些加速度并把这个总和作为forwardDir 。