I’m not asking how to implement this, it’s simple enough concept. What I’m having trouble with is floats. Here is my code:
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);
mFriction is 0.2F.
The problem is, if I move the player with a positive velocity (X or Y), the friction works as it should and his velocity reduces to 0.0. However, if I move him with a negative velocity, the friction adds, and for some reason, does not stop at 0.0, but goes up to 0.2 before stopping. Because of this, I have a player moving, and then when I let go of the keys, he begins sliding slowly in the opposite direction. Why is this? How can I fix it?
In addition, I tried this code for test:
if (mVelocity.X == 0.2F)
mVelocity.X = 0.0F;
if (mVelocity.Y == 0.2F)
mVelocity.Y = 0.0F;
But it gives me the exact same results as if I hadn’t added the code. Apparently, 0.2F is not equal to 0.2F. What could this be?
Finally, in the debug output, when the player is at rest from moving positively (stopped supposedly) his speeds for both x and y (depending on how I moved him) are 2.980232E-08. I don’t understand this. If I set his speed to 1, and I subtract exactly 0.2 every frame, why would it go any other way than 1.0, 0.8, 0.6, 0.4, 0.2, 0.0? Following that, if he is at rest from moving negatively, his speeds for x and y (again, depending on how I move him) are 0.2. Why would it not go -1, -0.8, -0.6, -0.4, -0.2, 0.0? Instead of going from 0.0 to 0.2 in excess.
This all is making next to no sense to me, and if anyone could clear this up for me I would be grateful. Any alternate solutions are also accepted. If any more code, or clarification is needed, I would be happy to provide it.
The problem is that your equality test fails because of imprecision, so the character keeps moving for one extra frame, for instance.
Floating-point numbers are fundamentally imprecise, so theoretically, 2.0f * 5.0f is not necessarily == 10.0f. It might be 9.999999f or 10.000001f. Don’t test if two floating point numbers are equal: test if they are within a sufficiently small interval, i.e.:
Also read http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html