1
\$\begingroup\$

I'm relatively new to programming velocity and such as I used to use Unity so it was already implemented. Right now, I'm using MonoGame and have an issue with my velocity code. Whenever I decelerate, my "velocity.X" never becomes 0 it just keeps going down to numbers like "-8.775121E-10". I tried to check if it's less than or equal to 0.05 but that just causes issues.

Movement Code:

currentState = Keyboard.GetState();

        deltaTime = (float)gameTime.ElapsedGameTime.TotalSeconds;

        bounds.X = (int)position.X;
        bounds.Y = (int)position.Y;

        position.X += velocity.X;
        position.Y += velocity.Y;

        if (velocity.X >= MAX_ACCELERATION)
            velocity.X = MAX_ACCELERATION;
        if (velocity.X <= -MAX_ACCELERATION)
            velocity.X = -MAX_ACCELERATION;

        if (currentState.IsKeyDown(Keys.A))
        {
            if (velocity.X > -MAX_ACCELERATION)
                velocity.X -= acceleration * deltaTime;
        }
        else if (currentState.IsKeyDown(Keys.D))
        {
            if (velocity.X < MAX_ACCELERATION)
                velocity.X += acceleration * deltaTime;
        }

        Console.WriteLine("Velocity: " + velocity);
        Console.WriteLine("Current KeyState: " + currentState.IsKeyUp(Keys.A));

        prevState = currentState;

        Console.WriteLine("Prev KeyState: " + prevState.IsKeyDown(Keys.A));

        SlowDown();

SlowDown Method:

            /*if (!prevState.IsKeyUp(Keys.A) && currentState.IsKeyUp(Keys.A))
        {
            if (velocity.X >= -0.5f)
                velocity.X = 0;
        }*/

        velocity.X *= FRICTION;
\$\endgroup\$
0
\$\begingroup\$

The math around drag usually slows things down as a function of how fast it is already going, hence your velocity.X *= FRICTION; which seems generally right. The problem is that with that math, mathematically, it will never come to a complete stop. Half of 1 is 1/2, half of that is 1/4, half of that is 1/8, ... 1/1024, 1/2048, 1/4096... Mathematically, you never hit 0. There's nothing strictly wrong with that, unless you do something to assume that something can only be done if you're completely stopped. (Since computers can't represent minuscule numbers, it will eventually become 0. It just might take a minute.)

What I typically do in these situations, if I want it to go to 0, is just move the value to 0 if it is already sufficiently small. Something like:

velocity.X *= FRICTION;
if(Math.Abs(velocity.X) < 0.001) // Pick your favorite small number here...
    velocity.X = 0;

This covers the situation regardless of if you're really small and positive, or really small and negative, which you might have been having some issues with originally. I believe this also makes it so you don't have to put the bit about isRight that you had in your own answer.

\$\endgroup\$
1
  • \$\begingroup\$ Thank you! This is a much better solution than the one I had. \$\endgroup\$ – Callum Jan 7 '20 at 23:31
0
\$\begingroup\$

Fixed it. For anyone having the same issue, I just added a bool variable called "isRight" and made it true when I am pressing the right key and false when pressing the left key. Then I check the velocity to see if it is less than or greater than (depending on the bool) 0.5 in the SlowDown method and set it to 0.

Code:

velocity.X *= FRICTION;

        if (isRight && velocity.X <= 0.5f)
        {
            velocity.X = 0;
        }

        if (!isRight && velocity.X >= -0.5f)
        {
            velocity.X = 0;
        }
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.