2013-06-23 31 views
5

Używam czasu delta więc mogę uczynić mój program frame rate niezależne. Jednak nie mogę uzyskać wysokości skoku, która jest taka sama, postać zawsze skacze wyżej przy niższej liczbie klatek na sekundę.Jak zachować wysokość skoku podczas używania czasu delta?

Zmienne:

const float gravity = 0.0000000014f; 
const float jumpVel = 0.00000046f; 
const float terminalVel = 0.05f; 
bool readyToJump = false; 
float verticalVel = 0.00f; 

kodów logicznych:

if(input.isKeyDown(sf::Keyboard::Space)){ 
    if(readyToJump){ 
     verticalVel = -jumpVel * delta; 
     readyToJump = false; 
    } 
} 

verticalVel += gravity * delta; 
y += verticalVel * delta; 

Jestem pewien czas delta jest prawidłowe, ponieważ postać porusza się poziomo w porządku.

Jak mogę dostać mój charakter, aby przejść taki sam bez względu na ilość klatek na sekundę?

+0

Jaką jednostką/typem jest "delta"? –

Odpowiedz

6

Wzór do obliczenia nowej pozycji:

position = initial_position + velocity * time 

Biorąc pod uwagę wagę, co zmniejsza prędkość według funkcji:

velocity = initial_velocity + (gravity^2 * time) 

uwaga: ciężkości w tym przypadku nie jest taki sam jako grawitacja. Ostateczna formuła staje się wówczas:

position = initial_position + (initial_velocity + (gravity^2 * time) * time 

Jak widać z powyższego równania, initial_position i initial_velocity nie ma wpływu na czas. Ale w twoim przypadku ustawiasz początkową prędkość równą -jumpVelocity * delta.

Im mniejsza liczba klatek na sekundę, im większa jest wartość delta będzie, dlatego postać przeskoczy wyżej. Rozwiązaniem jest zmiana

if(readyToJump){ 
    verticalVel = -jumpVel * delta; 
    readyToJump = false; 
} 

do

if(readyToJump){ 
    verticalVel = -jumpVel; 
    readyToJump = false; 
} 

EDIT:

Powyższe powinno dać dość dobre oszacowanie, ale to nie jest do końca prawidłowe. Zakładając, że jest to pozycja p(t) (w tym przypadku wysokość) Po czasie t, wówczas prędkość podaje v(t) = p'(t)', and the acceleration is given by a (t) = V '(t) = s' '(t) `. Ponieważ wiemy, że przyspieszenie jest stałe; czyli grawitacja, otrzymujemy następujące:

a(t) = g 
v(t) = v0 + g*t 
p(t) = p0 + v0*t + 1/2*g*t^2 

Jeśli teraz obliczyć p(t+delta)-p(t), czyli zmiany położenia z jednym przypadku w czasie do drugiego otrzymujemy następujące:

p(t+delta)-p(t) = p0 + v0*(t+delta) + 1/2*g*(t+delta)^2 - (p0 + v0*t + 1/2*g*t^2) 
       = v0*delta + 1/2*g*delta^2 + g*delta*t 

Oryginalny kod nie wziąć pod uwagę kwadraturę delta lub dodatkowy termin g*delta*t*. Bardziej dokładnym podejściem byłoby zapisanie wzrostu delty, a następnie użycie wzoru podanego powyżej.

Przykładowy kod:

const float gravity = 0.0000000014f; 
const float jumpVel = 0.00000046f; 
const float limit = ...; // limit for when to stop jumping 

bool isJumping = false; 
float jumpTime; 

if(input.isKeyDown(sf::Keyboard::Space)){ 
    if(!isJumping){ 
     jumpTime = 0; 
     isJumping = true; 
    } 
    else { 
     jumpTime += delta; 
     y = -jumpVel*jumpTime + gravity*sqr(jumpTime); 
     // stop jump 
     if(y<=0.0f) { 
      y = 0.0f; 
      isJumping = false; 
     } 
    } 
} 

UWAGA: Nie skompilowany lub przetestowane w powyższy kod.

+0

Dziękujemy! Chociaż przykładowy kod naprawdę mi nie pasował, ponieważ nie miałem pojęcia, gdzie weszła w życie verticalVel. Jednak twoja odpowiedź pomogła mi znaleźć rozwiązanie mojego problemu. – user2513924

+0

Przepraszam, tęsknię za tą linią. To nie miało wpływu. Usunięto go w mojej aktualizacji. – TAS

0

Przez "czas delta" rozumiesz jako zmienne kroki czasowe? Jak w każdej klatce obliczasz krok czasu, który może być zupełnie inny od poprzedniego?

Jeśli tak, to NIE.

Przeczytaj to: http://gafferongames.com/game-physics/fix-your-timestep/

TL; DR: używać stałych kroków czasowych dla stanu wewnętrznego; w razie potrzeby interpoluj ramki.