2011-02-06 15 views
6

Próbuję symulować grawitację w mojej pierwszej grze Xna 2d. Mam następującyXna dodawanie grawitacji do sprite'a 2d

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

Więc staram się przenieść ikonki przez pewien okres, gdy elapsedAirTime < maxAirTime Jednak istnieje jakiś problem z mojego kodu tylko wydaje się przesuwać ikonki się raz, a nie wielokrotność razy w tym okresie czasu. tutaj jest kod w mojej klasie "player.cs" lub metoda aktualizacji klasy.

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

Każda pomoc jest doceniana, proszę i dziękuję!

Odpowiedz

11

Aby nadać swojemu sprite'owi wrażenie grawitacji, powinieneś dodać prędkość i przyspieszenie do swojej klasy Sprite. Następnie utwórz metodę aktualizacji dla Sprite i dodaj przyspieszenie do każdej prędkości, a prędkość dodawaj do każdej aktualizacji. Pozycja nie powinna być oparta na ilości wykorzystanego czasu antenowego. Możesz ustawić przyspieszenie na stałą wartość grawitacji, a następnie dodać do prędkości Sprite za każdym razem, gdy skaczesz. Stworzy to płynny skok paraboliczny, który wygląda ładnie. Jeśli chcesz uwzględnić czas, możesz przekazać GameTime do metody aktualizacji Sprite i użyć go jako modyfikatora prędkości. Oto przykład metoda Update:

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

Jeśli używasz rozrządu, ta metoda jest trochę skomplikowana. Musisz śledzić, ile czasu zajęło aktualizowanie, a następnie podzielić go przez średnią ilość czasu, jaką powinna wykonać aktualizacja lub ramka, aby uzyskać kwotę, którą powinieneś dostosować swoją prędkość. Bez czasu, metoda jest bardzo prosta:

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

Sugerowałbym użyciu prostsze metody, aż dokładnie zrozumieć, jak działa i dlaczego rozrządu trzeba go wdrożyć.

+0

Po co obliczać czasScalar i przechowywać starą godzinę gry?Jeśli ta funkcja aktualizacji zostanie wywołana w każdej pętli gry (tak jak powinna być), gt.ElapsedGameTime wykona już dla ciebie wszystkie ciężkie ćwiczenia. –

+1

Powodem użycia timeScalar jest a) jeśli chcesz zmienić domyślną liczbę klatek na sekundę, lub b) jeśli twój komputer jest tak wolny, że nie może nadążyć za domyślnymi 60 próbami UPS/FPS XNA. W obu przypadkach, jeśli nie otrzymasz docelowej częstotliwości aktualizacji, twoja gra będzie wyglądać tak, jakby była opóźniona bez kodu czasowegoScalar. – Darkhydro

2

Wygląda na tej linii jest uszkodzony:

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

myślę, okaże się, że ten aktualizuje pozycję ikonek szybciej niż można sobie wyobrazić, ikonki ruszy 330 pikseli ekran 10 aktualizacjach (zakładając, Game.IsFixedTimeStep == true), czyli 1 dziesiąta sekundy czasu rzeczywistego

Jest to prawdopodobnie tylko aktualizacja tak szybko, że nie dostaniesz żadnej zmiany, aby zobaczyć, jak wzrośnie, zanim warunek && position.Y < 3 włączy się i zmieni odtwarzacz.

Wygląda na to, że próbujesz powiedzieć - przeskakuj z prędkością x pikseli na sekundę przez 8,5 sekundy, o ile miejsce jest zatrzymane.

To, czego potrzebujesz, to zmienić obliczenie na this.position.y -= (float) (30 * gameTime.ElapsedGameTime.TotalSeconds), spowoduje to bardzo liniowy ruch akcji skoku, ale będzie to oznaczać, że duszek skacze dokładnie o 30 pikseli na sekundę.

Jeśli Game.IsFixedTimeStep == true - co jest domyślnie - aktualizacja zostaje wywołana 60 razy na sekundę, więc gameTime.ElapsedGameTime.TotalSeconds będzie około 0,1 każdej aktualizacji. Jeśli wydarzy się coś, co spowoduje pominięcie aktualizacji (na przykład problemy z renderowaniem), aktualizacja zostanie opóźniona, a parametr gameTime.ElapsedGameTime.TotalSeconds może wynosić 0.3 (dwie aktualizacje zostały pominięte), ale formular nadal działa poprawnie.