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.