Programmazione di giochi 2D in Java: approcci diversi per creare un loop di gioco


10

Sono nuovo nella programmazione di giochi Java, ma più leggo più sono confuso, perché ho visto diversi approcci per creare un loop di gioco: 1. L'approccio standard, che utilizza la classe Timer (sembra essere inferiore precisi). 2. L'approccio più preciso che utilizza System.nanoTime. 3. Un approccio semplice che utilizza scheduleAtFixedRate.

Quale dovrebbe essere generalmente preferito e dove sono i vantaggi / gli svantaggi di ciascun approccio? Grazie in anticipo per qualsiasi informazione.

Risposte:


7

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.


La domanda riguardava i loop di gioco, quindi le informazioni awt / swing sono fuori tema. Tuttavia sembrava che le informazioni fossero rilevanti a causa di una linea irrilevante e confusa nella domanda, quindi l'ho rimosso.
jhocking

Ho adattato la mia risposta per riflettere le modifiche apportate alla domanda.
Exilyth

7

Non metterei il loop principale in un timer. Piuttosto farei un ciclo 'while' che elabora ogni fotogramma e quindi utilizzi una sorta di funzionalità di cronometraggio (sembra che in Java sarebbe System.nanoTime) per calcolare quanto tempo è trascorso dall'ultimo fotogramma / ultima iterazione del ciclo continuo.

Alcuni linguaggi sono eccezioni qui (ad es. JavaScript, ActionScript) perché tali linguaggi operano in un ambiente che ha un ciclo principale implicito da agganciare (ad es. Il browser, il Flash Player) ma tale eccezione non si applica a Java.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.