W przypadku podstawowej pętli gry uruchomisz pętlę while, w której uzyskasz czas za pomocą nanoTime (), określisz ile czasu minęło od ostatniej klatki, a następnie zaktualizujesz swój gamestate i wyrenderujesz.
Korzystając z http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/System.html#nanoTime%28%29 , możesz odpytywać o upływ czasu. Gruntownie...
public static void main(String [ ] args)
{
long current_frame_time = system.nanoTime();
long last_frame_time = current_frame_time;
while(gameIsRunning)
{
last_frame_time = current_frame_time;
current_frame_time = system.nanoTime();
long timeTaken = current_frame_time - last_frame_time;
//update and render game here
}
}
Ta podstawowa metoda może zostać ulepszona, np. Http://www.koonsolo.com/news/dewitters-gameloop/ i http://gafferongames.com/game-physics/fix-your-timestep/ .
Alternatywnie można utworzyć licznik czasu i ustawić ten licznik, aby uruchamiał aktualizację i renderował co X milisekund. Ale istnieją pewne wady związane z budowaniem takiej gameloopu.
Według http://docs.oracle.com/javase/1.5.0/docs/api/java/util/Timer.html : „ Odpowiadający każdemu obiektowi Timer jest pojedynczy wątek w tle, który służy do wykonania wszystkich timerów zadania, sekwencyjnie. Zadania timera powinny się szybko kończyć. Jeśli zadanie timera zajmuje zbyt dużo czasu, „przerywa” wątek wykonywania zadania timera. To z kolei może opóźniać wykonywanie kolejnych zadań, co może „wiązać się” i wykonuj szybko po sobie, gdy (i jeśli) przestępcze zadanie w końcu się zakończy. ”
Zgodnie z http://docs.oracle.com/javase/1.5.0/docs/api/java/util/Timer.html#scheduleAtFixedRate%28java.util.TimerTask,%20java.util.Date,%20long%29 : „ W przypadku wykonania ze stałą szybkością każde wykonanie jest planowane w stosunku do zaplanowanego czasu wykonania pierwszego wykonania. Jeśli wykonanie zostanie opóźnione z jakiegokolwiek powodu (takiego jak wyrzucanie elementów bezużytecznych lub inne działanie w tle), dwa lub więcej wykonań nastąpi w krótkim odstępie czasu „dogonić”. W dłuższej perspektywie częstotliwość wykonywania będzie dokładnie odwrotnością określonego okresu (przy założeniu, że zegar systemowy leżący u podstaw Object.wait (długi) jest dokładny). ”
Ponieważ zwykle nie wiesz z góry, jak długo trwa pętla gry, ustawienie timera do wykonywania gameloopa co X milisekund (w zależności od docelowej częstotliwości klatek) może prowadzić do kilku grupowanych klatek, które byłyby wykonywane za każdym razem, gdy ramka jest zakończone zamiast kiedy planowana jest ramka. Kiedy tak się dzieje ... po co używać timera?
Nie zrozumcie mnie źle, licznik czasu nie jest złą klasą, ale zwykle lepiej nadaje się do małych zadań, które muszą być wykonywane okresowo lub w określonym czasie, np. Klient poczty może chcieć sprawdzać, czy nie ma nowej poczty co 5 minut lub licznik może się zmniejszać co sekundę, aby wyświetlać odliczanie przed rozpoczęciem wyścigu.
Nie umieszczałbym głównej pętli w zegarze. Zrobiłbym raczej pętlę „while”, która przetwarza każdą ramkę, a następnie użyłem pewnego rodzaju funkcji pomiaru czasu (brzmi to jak w Javie jako System.nanoTime), aby obliczyć, ile czasu minęło od ostatniej ramki / ostatniej iteracji pętla.
Niektóre języki są tutaj wyjątkami (np. JavaScript, ActionScript), ponieważ języki te działają w środowisku, które ma niejawną główną pętlę do podłączenia (np. Przeglądarka, Flash Player), ale ten wyjątek nie dotyczy Javy.
źródło