2011-02-06 7 views
6

Estoy tratando de simular la gravedad en mi primer juego xna 2d. Tengo el siguienteXna agregando gravedad a un sprite 2d

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

así que estoy tratando de mover el sprite por una cierta cantidad mientras que el elapsedAirTime < maxAirTime Sin embargo, hay un cierto problema por el que el código sólo parece mover el sprite una vez y que no sea múltiplo veces durante este segmento de tiempo. aquí está el código en mi clase "player.cs", o el método de actualización de la clase.

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; 
      } 
     } 

¡Cualquier ayuda es muy apreciada, por favor y gracias!

Respuesta

11

Para darle a tu sprite la sensación de gravedad, debes agregar velocidad y aceleración a tu clase de Sprite. A continuación, cree un método de actualización para el Sprite y añada aceleración a su velocidad en cada actualización y velocidad agregada para posicionar cada actualización. La posición no debe basarse en la cantidad de tiempo de aire transcurrido. Puede configurar la aceleración a un valor gravitacional constante y luego aumentar la velocidad del Sprite cada vez que salta. Esto creará un salto parabólico fluido que se ve bien. Si desea incluir el tiempo, puede pasar el tiempo de juego en el método de actualización del Sprite y usarlo como un modificador de la velocidad. He aquí un ejemplo del método de actualización:

 
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; 
} 

Si utiliza la sincronización, este método es un poco complicado. Debe hacer un seguimiento de cuánto tiempo tomó la actualización y luego dividirla por la cantidad promedio de tiempo que una actualización o fotograma debe tomar para obtener la cantidad en la que debe ajustar su velocidad. Sin tiempo, el método es muy simple:

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

se recomienda usar el método más simple hasta que entienda exactamente cómo temporización de las obras y por qué necesita para ponerlo en práctica.

+0

¿Por qué calcular un timeScalar y almacenar el tiempo de juego anterior?Si esta función de actualización se llama cada ciclo de juego (como debería ser), gt.ElapsedGameTime ya hace todo el trabajo pesado por ti. –

+1

La razón para usar timeScalar es a) si desea cambiar la velocidad de fotogramas predeterminada, o b) si su computadora es tan lenta que no puede mantenerse al día con los 60 UPS/FPS predeterminados que intenta XNA. En cualquier caso, si te quedas atrás de la tasa de actualización objetivo, tu juego se verá retrasado sin el código timeScalar. – Darkhydro

2

Parece que esta línea tiene la culpa:

this.position.Y -= (float)(30.0 + ((1.2) * elapsedAirTime)*elapsedAirTime); 

Creo que usted encontrará que esto actualiza la posición sprites más rápido de lo que imaginas, el sprite se moverá 330 píxeles hasta la pantalla en 10 actualizaciones (suponiendo Game.IsFixedTimeStep == true) que es 1 décima de segundo en tiempo real

Es probable que esto se esté actualizando tan rápido que no se obtenga un cambio para ver que suba antes de que la condición && position.Y < 3 se active y cambie el playerState.

Parece que está intentando decir: salte a una velocidad de x píxeles por segundo hasta 8,5 segundos, siempre que se mantenga espacio.

Lo que necesitas para eso es cambiar el cálculo a this.position.y -= (float) (30 * gameTime.ElapsedGameTime.TotalSeconds), esto dará un movimiento muy delineador a la acción del salto pero significará que el sprite salta a exactamente 30 píxeles por segundo.

Si es Game.IsFixedTimeStep == true - que es el valor predeterminado - la actualización se llama 60 veces por segundo, por lo que gameTime.ElapsedGameTime.TotalSeconds va a ser aproximadamente 0,1 cada actualización. Si sucede que algo causa que una actualización se salte (problemas de representación, por ejemplo), la actualización se retrasará y gameTime.ElapsedGameTime.TotalSeconds puede ser 0.3 (las 2 actualizaciones omitidas) pero el formulario aún resuelve la tasa de salto correcta.