Jak zdobyć i wykorzystać czas delta

14

W mojej grze myszy wyglądają i chodzą, ale są one bardzo wolne i trudne w użyciu. Myślę, że to dlatego, że używam stałej prędkości. Słyszałem, że w dużych projektach programiści używają czasu delta. Jak obliczyć czas delta w glut? Jak obliczyć prędkość na podstawie czasu delta?

Mark Fedurin
źródło
C11 i C ++ 11 mają teraz także zegary nanosekundowe: stackoverflow.com/a/36095407/895245 || stackoverflow.com/a/5524138/895245
Ciro Santilli 事件 改造 中心 法轮功 六四 事件

Odpowiedzi:

18

„Czas delta” to czas, który upłynął między dwiema aktualizacjami ramek (ale można go również wykorzystać w innych kontekstach; jest to zwykle wynik odejmowania czasu).

Czas delty można uzyskać w glut za pomocą metody glutGet i parametru GLUT_ELAPSED_TIME oraz niektórych operacji.

Poniższy wiersz zwraca liczbę milisekund od wywołania glutInit (lub pierwszego wywołania glutGet (GLUT_ELAPSED_TIME)):

int timeSinceStart = glutGet(GLUT_ELAPSED_TIME);

Jeśli więc zarejestrujesz bieżący timeSinceStart w każdej pętli renderowania, możesz poznać wartość deltaTime, odejmując starą od nowej.

int oldTimeSinceStart = 0;

while( ... )
{
     int timeSinceStart = glutGet(GLUT_ELAPSED_TIME);
     int deltaTime = timeSinceStart - oldTimeSinceStart;
     oldTimeSinceStart = timeSinceStart;

     //... stuff to update using deltaTime
}

Możesz to zrobić prawie w ten sam sposób, używając biblioteki ctime C / C ++ z clock () i wyrażeniem stałym makro CLOCKS_PER_SEC, które określa relację między taktowaniem zegara a sekundą.


Zasadniczo możesz użyć deltaTime, aby zaktualizować swoje ruchy w stosunku do tego czasu, który upłynął, zamiast używać stałej wartości czasu. W ten sposób prędkość ruchu twojej postaci powinna być prawie taka sama, jeśli twój program działa przy 60 fps lub jeśli działa przy 10 fps.


Oto mały przykład: załóżmy, że chcesz przesunąć coś o 10 jednostek na sekundę na osi x. Możesz zrobić coś takiego (jeśli deltaTime rzeczywiście używa milisekund).

Position.x += 10/1000 * deltaTime;

W ten sposób, bez względu na to, czy Twój program aktualizuje się 2 razy, czy 100 razy, 1 sekundę później pozycja powinna być prawie taka sama, a na grę wpływa mniejszy fps małego komputera niż przy użyciu stałych wartości.

  • Przy stałych wartościach ==> niskie fps = mniej aktualizacji = powolne ruchy, podczas gdy wysokie fps = więcej aktualizacji = bardzo szybkie ruchy.

  • Z deltaTime ==> „prawie” te same ruchy.


Na koniec powinieneś przeczytać Krok o stałym czasie vs Zmienny o czasie na gamedev.stackexchange.

Valkea
źródło
Zwraca milisekundy jako liczbę całkowitą? Brutto i być może niewystarczające. Zawsze musiałem używać czasomierzy zależnych od platformy, a potem unikałem GLUT jak zarazy, ponieważ nie jest to świetne do gier.
Sean Middleditch,
@Sean Nie używam GLUT, ale to było w parametrze pytania, więc odpowiedziałem o tym;) Intryguje mnie jednak twoja pozycja w kwestii „niewystarczalności” int do obsługi milisekund w grach . positive intZazwyczaj przejść do 2.147.483.647 jeśli podpisane i do 4.294.967.295 jeśli unsigned ... więc nawet jeśli weźmiemy pod uwagę mniejszy, 2.147.483.647 milisekund jest prawie 25 dni ... To powinno być dosyć obsłużyć większość gry timery i nawet jeśli to nie wystarczy, nadal możemy rozsądnie użyć unsigned int(~ 50 dni) lub nawet long long(jak zwykle to robię).
Valkea
1
@Valkea Nie chodzi o maksimum, ale o rozdzielczość na niskim poziomie. Ponieważ pojedyncza klatka przy 60 klatkach na sekundę to zaledwie 16 2/3 ms, dokładność 1 ms (od reprezentowania milisekund jako liczb całkowitych) reprezentuje margines błędu większy niż 5% - więcej niż wystarczający do wyrzucenia symulacji z daleka. Liczba całkowita w mikrosekundach byłaby do zniesienia, ale milisekundy są po prostu zbyt duże.
Steven Stadnicki
Tak, potrzebujesz czasu poniżej wielu milisekund dla wielu rzeczy i timera o wysokiej rozdzielczości, aby znaleźć to, czego GLUT nie zapewnia (o czym wiem). Nie jest źle napisać mały kod platformy do użycia QueryPerformanceCounterw systemie Windows i gettimeofdayna większości innych. Będziesz musiał ubrudzić sobie ręce i dążyć do nieco więcej niż najmniej wspólnego mianownika interfejsów API platformy, szczególnie w C i C ++.
Sean Middleditch
Taka precyzja nie jest przydatna we wszystkich grach. Jest to jednak bardzo interesujące wyjaśnienie, które w pełni odpowiada mojemu przesłuchaniu na temat twojego punktu widzenia dotyczącego int i zegarów. Jeszcze nigdy nie potrzebowałem precyzyjnego zegara, ale chyba czas na pogłębienie mojej wiedzy na ten temat. Dziękuję;)
Valkea,