Como obter e usar o tempo delta

14

Eu tenho ratos olhando e andando no meu jogo, mas eles são muito lentos e difíceis de usar. Eu acho que é porque estou usando velocidade fixa. Ouvi dizer que em grandes projetos os desenvolvedores usam o tempo delta. Como faço para calcular o tempo delta no excesso? Como calculo a velocidade usando o tempo delta?

Mark Fedurin
fonte
C11 e C ++ 11 também têm relógios de nanossegundo agora: stackoverflow.com/a/36095407/895245 || stackoverflow.com/a/5524138/895245
Ciro Santilli deve ser executado em

Respostas:

18

O "tempo delta" costumava ser o tempo decorrido entre duas atualizações de quadros (mas também pode ser usado em outros contextos; geralmente é o resultado de uma subtração de tempo).

Você pode obter o tempo delta em excesso usando o método glutGet e o parâmetro GLUT_ELAPSED_TIME, além de algumas operações.

A linha a seguir retorna o número de milissegundos desde que glutInit foi chamado (ou primeira chamada para glutGet (GLUT_ELAPSED_TIME)):

int timeSinceStart = glutGet(GLUT_ELAPSED_TIME);

Portanto, se você registrar o timeSinceStart atual em cada loop de renderização, poderá conhecer o deltaTime subtraindo o antigo para o novo.

int oldTimeSinceStart = 0;

while( ... )
{
     int timeSinceStart = glutGet(GLUT_ELAPSED_TIME);
     int deltaTime = timeSinceStart - oldTimeSinceStart;
     oldTimeSinceStart = timeSinceStart;

     //... stuff to update using deltaTime
}

Você também pode fazer isso quase da mesma maneira, usando a biblioteca ctime C / C ++ com clock () e a expressão constante de macro CLOCKS_PER_SEC que especifica a relação entre um tique de relógio e um segundo.


Basicamente, você pode usar deltaTime para atualizar seus movimentos na proporção desse tempo decorrido, em vez de usar um valor de tempo fixo. Dessa forma, a velocidade de movimento do seu personagem deve ser quase a mesma se o seu programa for executado a 60 qps ou se a 10 qps.


Aqui está um pequeno exemplo: suponha que você queira mover algo em 10 unidades por segundo no eixo x. Você poderia fazer algo assim (se deltaTime usar milissegundos de fato).

Position.x += 10/1000 * deltaTime;

Dessa forma, se seu programa atualizou 2 ou 100 vezes, 1 segundo depois, a posição deve ser quase a mesma e o jogo é menos impactado pelos baixos fps de um computador pequeno do que se usasse valores fixos.

  • Com valores fixos ==> fps baixos = menos atualizações = movimentos lentos, enquanto fps alto = mais atualizações = movimentos muito rápidos.

  • Com deltaTime ==> "quase" os mesmos movimentos.


Por fim, você deve ler Etapa de tempo fixo versus Etapa de tempo variável em gamedev.stackexchange.

Valkea
fonte
Ele retorna milissegundos como um número inteiro? Bruto, e possivelmente não suficiente. Eu sempre tive que usar temporizadores específicos da plataforma e depois evitei o GLUT como uma praga, já que não é ótimo para jogos.
21813 Sean Middleditch
@Sean Eu também não uso o GLUT, mas isso foi o parâmetro da pergunta, então respondi com isso em mente;) No entanto, estou intrigado com sua posição em relação à "insuficiência" de int para lidar com milissegundos em jogos . A positive intcostumo ir até 2.147.483.647 se assinado e até 4.294.967.295 se não assinado ... por isso mesmo se considerarmos o menor, 2.147.483.647 milissegundos é quase 25 dias ... Deve ser o bastante para lidar com a maioria jogo temporizadores e, mesmo que não seja suficiente, ainda podemos usar razoavelmente unsigned int(~ 50 dias) ou até um long long(como eu costumo fazer).
Valkea
1
@Valkea O ponto não é o máximo, é a resolução na extremidade baixa. Como um único quadro a 60 FPS é de apenas 16 2/3 ms, uma precisão de 1 ms (representando milissegundos como números inteiros) representa uma margem de erro de mais de 5% - mais que o suficiente para gerar simulações distantes. Uma contagem inteira de microssegundos seria suportável, mas os milissegundos são muito grosseiros.
Steven Stadnicki
Sim, você precisa de um tempo abaixo de milissegundos para muitas coisas e um temporizador de alta resolução para descobrir isso, o que o GLUT não fornece (que eu saiba). Não é ruim escrever apenas um pequeno código de plataforma para usar QueryPerformanceCounterno Windows e gettimeofdayna maioria dos outros. Você precisará sujar as mãos e procurar um pouco mais do que o denominador menos comum das APIs da plataforma, especialmente em C e C ++.
23813 Sean Middleditch
Essa precisão não é útil para todos os jogos. No entanto, esta é uma explicação muito interessante que responde totalmente ao meu interrogatório sobre o seu ponto de vista sobre int e relógios. Eu nunca precisei de um relógio de alta precisão ainda, mas acho que é hora de aprofundar meu conhecimento sobre o assunto. Obrigado;)
Valkea 18/07/2013