Timestep semi-fixo ou totalmente fixo?

15

Estou criando um iphone shmup e tentando decidir que tipo de loop de jogo usar. Desejo usar timestep semi-fixo ou timestep totalmente fixo.

Com o timestep semi-fixo, farei zero ou mais chamadas de atualização (FIXED_INTERVAL) seguidas por uma chamada de atualização (dt) em que dt <= FIXED_INTERVAL por loop do jogo. Pelo que entendi, as desvantagens desse método são que minha lógica de atualização física (dt) será mais difícil de programar, porque basicamente preciso assumir uma variável dt para cada atualização. E também ouvi dizer que cada execução do meu jogo será um pouco diferente devido aos valores de ponto flutuante não serem os mesmos todas as vezes.

Então, com timestep totalmente fixo, estou fazendo zero ou mais chamadas de atualização (FIXED_INTERVAL) seguidas de uma chamada de interpolação (dt / FIXED_INTERVAL) em que dt <FIXED_INTERVAL por loop do jogo.

Então parece que a grande decisão que realmente tenho que tomar é: quero enfrentar o desafio de implementar uma atualização (dt) com uma variável dt ou quero enfrentar o desafio de implementar a interpolação?

Agora, pelo que li, a maioria das pessoas está dizendo para usar totalmente fixo e fazer a interpolação. Mas quando penso em implementar a interpolação, parece que eu seria muito mais complexo do que uma atualização (dt) com a variável dt. Isso ocorre porque, se eu usar a interpolação, tenho que lembrar o estado anterior e o atual. Então, se eu quiser usar a interpolação, tenho que criar uma camada adicional de indireção que abstraia estados individuais inteiros do jogo. Enquanto no timestep semi-fixo, onde não preciso usar a interpolação, não preciso criar uma abstração do estado do jogo, porque sempre há apenas um estado do jogo e são simplesmente as "matrizes globais" que representam meus inimigos e inimigos. balas etc.

Então, qual é a opção mais prática: eu o implemento semifixo, sabendo que minhas atualizações de física podem ficar complicadas com a variável dt. Ou eu uso totalmente fixo e tento criar uma abstração de estado do jogo para poder acompanhar o estado anterior e o estado atual para executar a interpolação?

Ryan
fonte
Coberto muito bem aqui: gamedev.stackexchange.com/questions/1589/...
michael.bartnett
11
Eu li essa discussão e os links lá várias vezes. É realmente como eu vim para este post. Minha pergunta tem a ver principalmente com a maneira de implementar estados de jogos para obter interpolação - o que não é abordado em nada nessa discussão.
Ryan

Respostas:

12

Totalmente fixo

Você perde a maioria dos benefícios de um passo fixo ao lançar uma etapa variável uma vez a cada quadro.

Noel Lopis tem uma ótima descrição de como ele implementou uma etapa de tempo fixo em seu jogo Casey's Contraptions . Como bônus para você, ele é desenvolvedor de iphone, embora sua técnica não seja específica para iphone.

Alguns destaques do artigo

  • Use um acumulador de tempo.
  • Use a taxa física de 120Hz para uma taxa de quadros de 60Hz.
  • Simule uma etapa fixa no futuro e use a acumulação restante no tempo para lerp desenhar o código entre o estado físico atual e o estado físico futuro.
  • várias dicas
deft_code
fonte
2

O que você chama de timestep "semi-fixo" e "totalmente fixo" são, na minha opinião, ambos timestap fixo - o dt que você está passando para a sua updatechamada não muda entre os quadros.

Portanto, sua pergunta é realmente "eu quero implementar interpolação para fins de renderização?" A resposta é: provavelmente não .

A interpolação é algo que você só gostaria de fazer se o seu updatetimestep fixo for significativamente diferente do rendertimestep de destino . Não é incomum que jogos com uma updatefase extenuante chamem apenas updatea, digamos, 10Hz, mas renderizem na taxa de quadros máxima.

Como você está escrevendo um shmup do iPhone, nem a sua updatenem a sua rendernecessidade exigem muito uso de CPU; você pode bloquear facilmente a taxa de quadros em 30Hz ou 60Hz, não se incomodar com a implementação e ainda ter um jogo de aparência suave.

Blair Holloway
fonte
Eu não entendo. Você está dizendo que eu posso bloquear o grande dt que eu computaria no loop do jogo - que minha física consome? Como faço isso? Posso fazer isso com o CADisplayLink? Quero dizer, qual% de CPU você está assumindo que estou usando? Você realmente deve assumir o loop de jogo bloqueado dt?
Ryan
O que estou dizendo realmente se resume a isso: faça a coisa menos complicada que funcionaria.
Blair Holloway
11
Elaboração: usar uma variável dtpara updatee renderé a coisa mais simples que funcionaria, mas geralmente evitada ao usar mecanismos de física pela instabilidade que ela causa. Portanto, chamar updatecom um valor fixo dte renderizar na mesma taxa (ao mesmo tempo em que elimina os quadros se o updatetempo for longo) geralmente é a coisa mais simples que funcionaria. Escrever código para interpolar objetos entre updatechamadas adiciona complexidade ao seu código; complexidade que você está adicionando para resolver nenhum problema em particular.
Blair Holloway