我不是问如何实现这个,这很简单的概念。我遇到的问题是花车。这是我的代码:
Position += mVelocity;
if (!Keyboard.GetState().IsKeyDown(Keys.Left) && !Keyboard.GetState().IsKeyDown(Keys.Right) && !Keyboard.GetState().IsKeyDown(Keys.Down) && !Keyboard.GetState().IsKeyDown(Keys.Up))
{
if (mVelocity.X != 0.0F)
{
if (mVelocity.X > 0.0F)
mVelocity.X -= mFriction;
if (mVelocity.X < 0.0F)
mVelocity.X += mFriction;
}
if (mVelocity.Y != 0.0F)
{
if (mVelocity.Y > 0.0F)
mVelocity.Y -= mFriction;
if (mVelocity.Y < 0.0F)
mVelocity.Y += mFriction;
}
}
Console.WriteLine(mVelocity.X + ", " + mVelocity.Y);
m摩擦力为0.2F。
问题是,如果我以正速度(X或Y)移动玩家,摩擦力应该正常,并且他的速度降低到0.0。但是,如果我以负速度移动他,摩擦会增加,并且出于某种原因,不会停在0.0,而是在停止之前上升到0.2。因此,我有一个移动的玩家,然后当我松开钥匙时,他开始在相反的方向缓慢滑动。为什么是这样?我该如何解决?
此外,我尝试使用此代码进行测试:
if (mVelocity.X == 0.2F)
mVelocity.X = 0.0F;
if (mVelocity.Y == 0.2F)
mVelocity.Y = 0.0F;
但它给了我完全相同的结果,好像我没有添加代码。显然,0.2F不等于0.2F。这可能是什么?
最后,在调试输出中,当玩家处于静止状态时(正在停止)他的x和y的速度(取决于我如何移动他)是2.980232E-08。我不明白这一点。如果我将速度设置为1,并且每帧减去0.2,那为什么它会以1.0,0.8,0.6,0.4,0.2,0.0之外的其他方式去除?接下来,如果他因为负面移动而处于休息状态,他对x和y的速度(再次,取决于我如何移动他)是0.2。为什么它不会变为-1,-0.8,-0.6,-0.4,-0.2,0.0?而不是超过0.0到0.2。
这一切对我来说毫无意义,如果有人能为我清楚这一点,我将不胜感激。任何替代解决方案也被接受。如果需要更多代码或澄清,我很乐意提供它。
答案 0 :(得分:5)
问题在于你的相等测试因为不精确而失败,所以角色会继续移动一个额外的帧,例如。
浮点数基本上是不精确的,所以从理论上讲,2.0f * 5.0f不一定是== 10.0f。它可能是9.999999f或10.000001f。不要测试两个浮点数是否相等:测试它们是否在足够小的区间内,即:
// test approximate equality between f1 and f2
bool areEqual(float f1, float f2) {
return Math.Abs(f1 - f2) < EqualityThreshold; // where EqualityThreshold is a small constant
}
另请阅读http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html
答案 1 :(得分:1)
您需要使用一些阈值来获得最低速度。在现实生活中,我们有动摩擦和静摩擦。前者是对我们起作用的力量,后者是我们克服任何动作发生的力量。
你在那里有动能摩擦,但你却缺少静电。
我意识到你的问题纯粹是浮点精度,但是如果你正在构建强大的物理学,请记住两种类型的摩擦,以及关于力和运动的其他规则。