Xna adding gravity to a 2d sprite

Aziz picture Aziz · Feb 6, 2011 · Viewed 14.1k times · Source

I am trying to simulate gravity in my first xna 2d game. I have the following

        //Used for Jumping
    double elapsedAirTime = 0.0;
    double maxAirTime = 8.35;
    //End Jumping

So I am trying to move the sprite up by a certain amount while the elapsedAirTime < maxAirTime However, there is some issue where my code only seems to move the sprite up once and not multiple times during this segment of time. here is the code in my "player.cs" class, or the update method of the class.

if (newState.IsKeyDown(Keys.Space))
        {
            if(oldState.IsKeyUp(Keys.Space))
            {
                //if we are standing or jumping then change the velocity
                if (playerState == PlayerStates.Standing)
                {
                    playerState = PlayerStates.Jumping;
                    this.position.Y -= (float)(30.0 + ((1.2)*elapsedAirTime)*elapsedAirTime);
                }
            }
        }
        //if we are jumping give it some time
        if (playerState == PlayerStates.Jumping)
        {
            if ((elapsedAirTime < maxAirTime) && position.Y < 3)
            {
                this.position.Y -= (float)(30.0 + ((1.2) * elapsedAirTime)*elapsedAirTime);
                elapsedAirTime += gameTime.ElapsedGameTime.TotalSeconds;
            }
            //otherwise time to fall
            else
            {
                playerState = PlayerStates.Falling;
            }

        }

        //add gravity to falling objects
        if (playerState == PlayerStates.Falling || playerState == PlayerStates.Standing)
        {
            //if we are above the ground
            if (this.position.Y < windowBot - 110)
            {
                //chnage state to falling
                playerState = PlayerStates.Falling;
                this.position.Y += 3.0f + ((float)(gameTime.ElapsedGameTime.TotalSeconds));
            }
            else
            {
                playerState = PlayerStates.Standing;
                elapsedAirTime = 0.0f;
            }
        }

Any help is much appreciated, please and thank you!

Answer

Darkhydro picture Darkhydro · Feb 7, 2011

To give your sprite the feel of gravity, you should add velocity and acceleration to your Sprite class. Then, create an Update method for the Sprite, and have acceleration be added to your velocity every update, and velocity added to position every update. Position should not be based on the amount of elapsed air time. You can set the acceleration to a constant gravitational value, and then add to the velocity of the Sprite whenever you jump. This will create a flowing parabolic jump that looks nice. If you want to include timing, you can pass the GameTime into the Sprite's Update method, and use it as a modifier on the velocity. Here is an example Update method:

void Update(GameTime gt)
{
    int updateTime = gt.ElapsedGameTime.TotalMilliseconds - oldgt.ElapsedGameTime.TotalMilliseconds;
    float timeScalar = updateTime / AVG_FRAME_TIME;
    this.velocity += this.acceleration * timeScalar;
    this.position += this.velocity;
    oldgt = gt;
}

If you use timing, this method is a little complicated. You have to keep track of how much time the update took, then divide it by the average amount of time an update or frame should take to get the amount you should adjust your velocity by. Without timing, the method is very simple:

void Update()
{
    this.velocity += this.acceleration;
    this.position += this.velocity;
}

I would suggest using the simpler method until you understand exactly how timing works and why you need to implement it.