Cómo obtener y usar el tiempo delta

14

Tengo ratones mirando y caminando en mi juego, pero son muy lentos y difíciles de usar. Creo que es porque estoy usando velocidad fija. Escuché que en grandes proyectos los desarrolladores usan el tiempo delta. ¿Cómo calculo el tiempo delta en exceso? ¿Cómo calculo la velocidad usando el tiempo delta?

Mark Fedurin
fuente
C11 y C ++ 11 también tienen relojes de nanosegundos ahora: stackoverflow.com/a/36095407/895245 || stackoverflow.com/a/5524138/895245
Ciro Santilli 新疆 改造 中心 法轮功 六四 事件

Respuestas:

18

El "tiempo delta" solía ser el tiempo transcurrido entre dos actualizaciones de trama (pero también se puede usar en otros contextos; esto generalmente es el resultado de una resta de tiempo).

Puede obtener el tiempo delta en glut utilizando el método glutGet y el parámetro GLUT_ELAPSED_TIME, más algunas operaciones.

La siguiente línea devuelve el número de milisegundos desde que se llamó a glutInit (o la primera llamada a glutGet (GLUT_ELAPSED_TIME)):

int timeSinceStart = glutGet(GLUT_ELAPSED_TIME);

Entonces, si registra el tiempo actualSinceStart en cada bucle de representación, puede conocer el tiempo delta restando el antiguo al nuevo.

int oldTimeSinceStart = 0;

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

     //... stuff to update using deltaTime
}

También puede hacerlo casi de la misma manera, utilizando la biblioteca C / C ++ ctime con clock () y la expresión de macro constante CLOCKS_PER_SEC que especifica la relación entre un tic del reloj y un segundo.


Básicamente, puede usar deltaTime para actualizar sus movimientos en proporción a este tiempo transcurrido en lugar de usar un valor de tiempo fijo. De esta manera, la velocidad de movimiento de tu personaje debería ser casi la misma si tu programa se ejecuta a 60 fps o si se ejecuta a 10 fps.


Aquí hay un pequeño ejemplo: suponga que desea mover algo 10 unidades por segundo en el eje x. Podría hacer algo como esto (si deltaTime usa milisegundos).

Position.x += 10/1000 * deltaTime;

De esta manera, ya sea que su programa se actualice 2 o 100 veces, 1 segundo después, la posición debería ser casi la misma, y ​​el juego se ve menos afectado por los bajos fps de una computadora pequeña que si usa valores fijos.

  • Con valores fijos ==> fps bajo = menos actualizaciones = movimientos lentos, mientras que fps alto = más actualizaciones = movimientos muy rápidos.

  • Con deltaTime ==> "casi" los mismos movimientos.


Finalmente, debe leer el paso de tiempo fijo frente al paso de tiempo variable en gamedev.stackexchange.

Valkea
fuente
Devuelve milisegundos como un entero? Asqueroso, y posiblemente no suficiente. Siempre tuve que usar temporizadores específicos de la plataforma y luego evité GLUT como la peste, ya que no es genial para los juegos.
Sean Middleditch
@Sean, tampoco uso GLUT, pero eso estaba en el parámetro de la pregunta, así que respondí con esto en mente;) Sin embargo, estoy intrigado por su posición con respecto a la "insuficiencia" de int para manejar milisegundos en los juegos . Por lo positive intgeneral, sube a 2.147.483.647 si está firmado y hasta 4.294.967.295 si no está firmado ... así que incluso si consideramos el más pequeño, 2.147.483.647 milisegundos son casi 25 días ... Debería ser suficiente para manejar la mayoría de los juegos temporizadores e incluso si no es suficiente, todavía podemos usar razonablemente unsigned int(~ 50 días) o incluso un long long(como lo hago habitualmente).
Valkea
1
@Valkea El punto no es el máximo, es la resolución en el extremo inferior. Dado que un solo cuadro a 60 FPS es solo 16 2 / 3rms ms, una precisión de 1 ms (de representar milisegundos como enteros) representa un margen de error de más del 5%, más que suficiente para lanzar simulaciones fuera de control. Un recuento entero de microsegundos sería soportable, pero los milisegundos son demasiado gruesos.
Steven Stadnicki
Sí, necesita un tiempo inferior al milisegundo para muchas cosas y un temporizador de alta resolución para encontrar eso, que GLUT no proporciona (que yo sepa). No está mal solo escribir un pequeño código de plataforma para usar QueryPerformanceCounteren Windows y gettimeofdayen la mayoría de los demás. Tendrá que ensuciarse las manos y apuntar a un poco más que el denominador menos común de las API de plataforma, especialmente en C y C ++.
Sean Middleditch
Tal precisión no es útil para todos los juegos. Sin embargo, esta es una explicación muy interesante que responde completamente a mi interrogatorio sobre su punto de vista sobre int y relojes. Todavía no necesitaba un reloj de alta precisión, pero creo que es hora de profundizar mi conocimiento del asunto. Gracias ;)
Valkea