Per un ciclo di gioco di base, eseguiresti un ciclo while, all'interno del quale otterrai il tempo usando nanoTime (), determinando quanto tempo è trascorso dall'ultimo fotogramma, quindi aggiorni il tuo gamestate e il rendering.
Utilizzando http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/System.html#nanoTime%28%29 , puoi eseguire il polling per il tempo trascorso. Fondamentalmente...
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
}
}
Questo metodo di base può essere migliorato, ad esempio http://www.koonsolo.com/news/dewitters-gameloop/ e http://gafferongames.com/game-physics/fix-your-timestep/ .
In alternativa, è possibile creare un timer e impostarlo per eseguire l'aggiornamento e il rendering ogni X millisecondi. Ma ci sono alcuni aspetti negativi nella costruzione di un gameloop del genere.
Secondo http://docs.oracle.com/javase/1.5.0/docs/api/java/util/Timer.html : " Corrispondente a ciascun oggetto Timer è un singolo thread in background che viene utilizzato per eseguire tutti i timer attività, in sequenza. Le attività timer dovrebbero essere completate rapidamente. Se un'attività timer impiega troppo tempo per completarsi, "fa da padrone" al thread di esecuzione delle attività del timer. Ciò può, a sua volta, ritardare l'esecuzione delle attività successive, che possono "raggrupparsi" e eseguire in rapida successione quando (e se) l'attività offensiva si completa finalmente. "
Secondo http://docs.oracle.com/javase/1.5.0/docs/api/java/util/Timer.html#scheduleAtFixedRate%28java.util.TimerTask,%20java.util.Date,%20long%29 : " Nell'esecuzione a tariffa fissa, ogni esecuzione è pianificata in relazione al tempo di esecuzione pianificato dell'esecuzione iniziale. Se un'esecuzione è ritardata per qualsiasi motivo (come la garbage collection o altre attività in background), si verificheranno due o più esecuzioni in rapida successione "recuperare". A lungo termine, la frequenza di esecuzione sarà esattamente il reciproco del periodo specificato (supponendo che l'orologio di sistema sottostante Object.wait (long) sia preciso). "
Dato che di solito non sai in anticipo quanto tempo impiega un loop di gioco, l'impostazione di un timer per eseguire il gameloop ogni X millisecondi (a seconda della frequenza dei fotogrammi target) potrebbe portare ad alcuni frame raggruppati, che si eseguiranno ogni volta che un frame è finito anziché quando è programmato un frame. Quando ciò accade ... perché usare un timer?
Ora, non fraintendetemi, il timer non è una cattiva classe, ma di solito è più adatto a piccole attività che devono essere eseguite periodicamente o in un determinato momento, ad esempio un client di posta elettronica potrebbe voler controllare la nuova posta ogni 5 minuti, oppure un contatore potrebbe diminuire ogni secondo per visualizzare un conto alla rovescia prima dell'inizio di una gara.