Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

Implementing gravity in the game, the character keeps bouncing up and down slightly when he hits the ground, upon debugging the character is essentially bouncing on and off the ground. Not quite sure how to iron out the issue any help here would be greatly appreciated.

The constant value

private float gravity = 0.09f;

adding to the velocity if the character is on the ground

if (!isOnGround)
 velocity.Y += gravity;

adding the characters overall velocity to the overall position.

position += velocity * (float)gameTime.ElapsedGameTime.TotalSeconds;

Part of the collision method which determines if the character is on the ground or not.

for (int y = topTile; y <= bottomTile; ++y)
            {
                for (int x = leftTile; x <= rightTile; ++x)
                {
                    // If this tile is collidable,
                    TileCollision collision = Level.GetCollision(x, y, tileMap);
                    if (collision != TileCollision.Passable)
                    {
                        // Determine collision depth (with direction) and magnitude.
                        Rectangle tileBounds = Level.GetBounds(x, y);
                        Vector2 depth = RectangleExtensions.GetIntersectionDepth(bounds, tileBounds);
                        float elapsed = (float)gameTime.ElapsedGameTime.TotalSeconds;

                        if (depth != Vector2.Zero)
                        {
                            float absDepthX = Math.Abs(depth.X);
                            float absDepthY = Math.Abs(depth.Y);

                            // Resolve the collision along the shallow axis.
                            if (absDepthY <= absDepthX || collision == TileCollision.Platform)
                            {
                                // If we crossed the top of a tile, we are on the ground.
                                if (previousBottom <= tileBounds.Top)
                                    isOnGround = true;
share|improve this question
1  
Why not use an existing physics engine? Farseer takes about a day to get comfortable with and can do just about anything you will even need. –  ClassicThunder Dec 14 '11 at 3:32
add comment

1 Answer

up vote 9 down vote accepted

I am afraid I do not fully understand your collision code yet: if there is an off-by-one-pixel error somewhere, it will be hard to spot. But your physics code needs a few fixes already:

  • velocity updates should depend on the timestep, even if gravity is a constant
  • vertical velocity should be set to zero if on the ground
  • adding the “overall velocity” is incorrect; it’s the average velocity for the duration of the last frame that needs to be added. This article should explain why.

Leading to the following code:

Vector2 oldvelocity = velocity;

if (!isOnGround)
    // This will require tweaking the gravity value
    velocity.Y += gravity * (float)gameTime.ElapsedGameTime.TotalSeconds;
else
    velocity.Y = 0.0;

position += 0.5 * (oldvelocity + velocity)
                * (float)gameTime.ElapsedGameTime.TotalSeconds;
share|improve this answer
    
+1 For the bit about using Verlet integration over Euler integration. I have always overlooked or forgotten about this before. –  David Gouveia Dec 14 '11 at 4:17
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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