Personaje que rebota en el suelo debido a la gravedad

Implementando la gravedad en el juego, el personaje sigue rebotando un poco hacia arriba y hacia abajo cuando toca el suelo, luego de depurar el personaje esencialmente rebota dentro y fuera del suelo. No estoy muy seguro de cómo solucionar el problema, cualquier ayuda aquí sería muy apreciada.

El valor constante

private float gravity = 0.09f; 

agregando a la velocidad si el personaje está en el suelo

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

agregando la velocidad general de los personajes a la position general.

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

Parte del método de colisión que determina si el personaje está en el suelo o no.

 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; 

Me temo que aún no entiendo totalmente el código de colisión: si hay un error de píxel por pulgada en alguna parte, será difícil detectarlo. Pero su código de física ya necesita algunas correcciones:

  • las actualizaciones de velocidad deberían depender del paso del time, incluso si la gravedad es una constante
  • la velocidad vertical se debe establecer en cero si está en el suelo
  • agregar la "velocidad general" es incorrecta; es la velocidad promedio para la duración del último cuadro que debe agregarse. Este artículo debe explicar por qué .

Llevando al siguiente código:

 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;