2011-02-06 10 views
6

Sto provando a simulare la gravità nel mio primo gioco xna 2d. Ho il seguenteXna aggiunge gravità a uno sprite 2d

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

Così sto cercando di spostare la sprite da una certa quantità, mentre l'elapsedAirTime < maxAirTime Tuttavia, c'è qualche problema in cui il mio codice sembra solo per spostare la sprite una volta e non più volte durante questo segmento di tempo. ecco il codice nella mia classe "player.cs", o il metodo di aggiornamento della classe.

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

Qualsiasi aiuto è molto apprezzato, per favore e grazie!

risposta

11

Per dare al tuo folletto la sensazione di gravità, devi aggiungere velocità e accelerazione alla tua classe Sprite. Quindi, crea un metodo di aggiornamento per Sprite e aggiungi l'accelerazione alla velocità ogni aggiornamento e la velocità aggiunta per posizionare ogni aggiornamento. La posizione non dovrebbe essere basata sulla quantità di tempo di volo trascorso. Puoi impostare l'accelerazione su un valore gravitazionale costante e quindi aggiungere alla velocità dello Sprite ogni volta che salti. Questo creerà un salto parabolico che sembra bello. Se vuoi includere il timing, puoi passare il GameTime al metodo di aggiornamento dello Sprite e usarlo come modificatore sulla velocità. Qui è un metodo di aggiornamento Esempio:

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

Se si utilizza tempistica, questo metodo è un po 'complicato. Devi tenere traccia di quanto tempo ha avuto l'aggiornamento, quindi dividerlo per la quantità media di tempo che un aggiornamento o un fotogramma dovrebbero impiegare per ottenere l'importo da cui dovresti regolare la tua velocità. Senza tempi, il metodo è molto semplice:

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

Io suggerirei di usare il metodo più semplice fino a quando non capire esattamente come funziona temporizzazione e perché è necessario per la sua attuazione.

+0

Perché calcolare un timeScalar e memorizzare il tempo di gioco precedente?Se questa funzione di aggiornamento viene chiamata ogni ciclo di gioco (come dovrebbe essere), gt.ElapsedGameTime fa già tutto il lavoro pesante per te. –

+1

Il motivo dell'utilizzo di timeScalar è a) se si desidera modificare la frequenza fotogrammi predefinita o b) se il computer è così lento da non riuscire a mantenere il 60 UPS/FPS XNA predefinito cercato. In entrambi i casi, se rimani indietro rispetto al tasso di aggiornamento del target, il tuo gioco sembrerà essere in ritardo senza il codice timeScalar. – Darkhydro

2

Sembra che questa linea è la colpa:

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

Penso che troverete che questo aggiorna la posizione sprites più velocemente di quanto si immagina, lo sprite si muoverà 330 pixel lo schermo in 10 aggiornamenti (supponendo Game.IsFixedTimeStep == true) 1 decimo di secondo in tempo reale

È probabile che si stia aggiornando così rapidamente che non si ottiene un cambiamento per vederlo aumentare prima che la condizione && position.Y < 3 passi e cambi il playerState.

Sembra che tu stia cercando di dire: saltare a una velocità di x pixel al secondo per un massimo di 8,5 secondi a condizione che lo spazio sia trattenuto.

Ciò che ti serve è cambiare il calcolo in this.position.y -= (float) (30 * gameTime.ElapsedGameTime.TotalSeconds), questo darà un movimento molto preciso all'azione di salto ma significherà che lo sprite salterà esattamente a 30 pixel al secondo.

Se Game.IsFixedTimeStep == true - che è l'impostazione predefinita - l'aggiornamento viene chiamato 60 volte al secondo, quindi gameTime.ElapsedGameTime.TotalSeconds sarà circa 0,1 ogni aggiornamento. Se succede qualcosa che causa un salto di aggiornamento (ad esempio problemi di rendering), l'aggiornamento verrà ritardato e gameTime.ElapsedGameTime.TotalSeconds potrebbe essere 0.3 (i 2 aggiornamenti saltati) ma il formular funzionerà ancora con la frequenza di salto corretta.