Programação de jogos em Java 2D: diferentes abordagens para fazer um loop de jogo


10

Eu sou novo na programação de jogos Java, mas quanto mais leio, mais confuso, porque já vi várias abordagens diferentes para fazer um loop de jogo: 1. A abordagem padrão, que usa a classe Timer (parece ser menos preciso). 2. A abordagem mais precisa que usa System.nanoTime. 3. Uma abordagem simples que usa scheduleAtFixedRate.

Qual deve ser geralmente preferido e onde estão as vantagens / desvantagens de cada abordagem? Agradecemos antecipadamente por qualquer informação.

Respostas:


7

Para um loop de jogo básico, você executaria um loop while, no qual obteria o tempo usando nanoTime (), determinaria quanto tempo se passou desde o último quadro, atualize seu estado de jogo e renderize.

Usando http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/System.html#nanoTime%28%29 , você pode pesquisar o tempo decorrido. Basicamente...

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
    }
}

Esse método básico pode ser aprimorado, por exemplo, http://www.koonsolo.com/news/dewitters-gameloop/ e http://gafferongames.com/game-physics/fix-your-timestep/ .

Como alternativa, você pode criar um cronômetro e configurá-lo para executar sua atualização e renderizar cada X milissegundos. Mas há algumas desvantagens na construção de um gameloop como esse.

De acordo com http://docs.oracle.com/javase/1.5.0/docs/api/java/util/Timer.html : " Correspondente a cada objeto Timer é um único thread de segundo plano usado para executar todos os timers sequencialmente. As tarefas de timer devem ser concluídas rapidamente. Se uma tarefa de timer demorar muito para ser concluída, "monopoliza" o encadeamento de execução de tarefas do timer. Isso pode, por sua vez, atrasar a execução de tarefas subseqüentes, que podem executar em rápida sucessão quando (e se) a tarefa incorreta finalmente terminar. "

De acordo com http://docs.oracle.com/javase/1.5.0/docs/api/java/util/Timer.html#scheduleAtFixedRate%28java.util.TimerTask,%20java.util.Date,%20long%29 : " Na execução de taxa fixa, cada execução é agendada em relação ao tempo de execução agendado da execução inicial. Se uma execução for atrasada por qualquer motivo (como coleta de lixo ou outra atividade em segundo plano), duas ou mais execuções ocorrerão em rápida sucessão para "recuperar o atraso". A longo prazo, a frequência de execução será exatamente o recíproco do período especificado (assumindo que o relógio do sistema subjacente a Object.wait (long) seja preciso). "

Como você geralmente não sabe com antecedência quanto tempo leva um loop do jogo, definir um cronômetro para executar seu gameloop a cada X milissegundos (dependendo da taxa de quadros-alvo) pode levar a alguns quadros agrupados, que são executados sempre que um quadro é terminou em vez de quando um quadro está agendado. Quando isso acontece ... por que usar um timer em primeiro lugar?

Agora, não me interpretem mal, o timer não é uma classe ruim, mas geralmente é mais adequado para pequenas tarefas que precisam ser realizadas periodicamente ou em um determinado horário, por exemplo, um cliente de email pode querer procurar novos emails a cada 5 minutos ou um contador pode ser diminuído a cada segundo para exibir uma contagem regressiva antes do início de uma corrida.


A pergunta era sobre loops de jogos, de modo que as informações awt / swing são fora de tópico. No entanto, parecia que essa informação era relevante por causa de uma linha irrelevante e confusa na pergunta, então eu a removi.
Jhocking

Adaptei minha resposta para refletir as alterações feitas na pergunta.
Exilyth 14/04

7

Eu não colocaria o loop principal em um timer. Em vez disso, eu faria um loop 'while' que processa todos os quadros e, em seguida, usava algum tipo de funcionalidade de cronometragem (soa como em Java que seria System.nanoTime) para calcular quanto tempo se passou desde o último quadro / última iteração do ciclo.

Certas linguagens são exceções aqui (por exemplo, JavaScript, ActionScript) porque essas linguagens operam em um ambiente que possui um loop principal implícito para conectar (por exemplo, o navegador, o Flash Player), mas essa exceção não se aplica ao Java.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.