Estoy escribiendo un juego que tiene muchos aspectos basados en el tiempo. Utilizo el tiempo para ayudar a estimar las posiciones de los jugadores cuando la red se detiene y los paquetes no están pasando (y el tiempo entre la recepción y la recepción de los paquetes). Es un juego de tipo pacman en el sentido de que un jugador elige una dirección y no puede dejar de moverse, por lo que el sistema tiene sentido (o al menos eso creo).
Entonces tengo dos preguntas: 1) ¿Cómo sincronizo los relojes de los juegos al principio ya que hay un retraso en la red? 2) ¿Está bien NO sincronizarlos y simplemente asumir que son iguales (mi código es independiente de la zona horaria)? No es un juego súper competitivo en el que las personas cambien sus relojes para hacer trampa, pero aún así.
El juego se está programando en Java y Python (desarrollo paralelo como proyecto)
Respuestas:
Creo que definitivamente no está bien sincronizar el reloj en el sistema . El usuario no espera que toque la configuración del sistema y muchos sistemas ni siquiera lo dejan.
Todo lo que necesita es tener una correlación para convertir la marca de tiempo del reloj de un lado al reloj del otro lado. Por otro lado, necesita que esta correlación sea bastante precisa, digamos al menos una centésima de segundo, si desea usarla para predecir las posiciones de los jugadores. El reloj del sistema nunca estará tan bien correlacionado entre máquinas aleatorias. Por lo tanto, debe establecer la correlación usted mismo, utilizando alguna variación en el tema NTP , probablemente incrustado en sus otros mensajes para conservar el ancho de banda de la red.
La idea básica podría ser que con cada paquete que envió la marca de tiempo lo envió y el número de secuencia y la marca de tiempo cuando recibió el último paquete del otro lado. A partir de esto, calcula el viaje de ida y vuelta: por ejemplo, si el paquete Q dice que se envió a 1000 y el paquete P se recibió a 500, luego de que usted envió el paquete P a 0 y está recibiendo Q a 800, el viaje de ida y vuelta es (800 - 0 ) - (1000 - 500) = 300. No hay forma de conocer la asimetría, por lo que simplemente asume que el paquete toma la mitad (150) de ticks en cualquier dirección. Y esa marca de tiempo remota está por delante de la local en 1000 - (800 - 150) = 350 ticks. El viaje de ida y vuelta variará. Si asume que el reloj es razonablemente preciso, debe usar un promedio a largo plazo de la correlación.
Tenga en cuenta que tampoco desea utilizar el reloj del sistema para el reloj. Es posible que se vuelvan a sincronizar a mitad de camino, lo que lo desviará del camino. Debería usarlo
clock(CLOCK_MONOTONIC)
en Unix oGetTickCount
en Windows (no estoy seguro de cómo esas API están envueltas en Java o Python en este momento).Nota: La
SO_TIMESTAMP
opción de socket (ver socket (7) mencionado por ott-- en el comentario sobre la pregunta) sería útil para separar el efecto de latencia del bucle de eventos que recibe los paquetes. Si vale la pena el esfuerzo depende de cuán buena precisión necesite.fuente
¿Cómo sabes qué reloj de jugador es correcto? No, así que usa un reloj de referencia .
NTP es excesivo aquí: solo necesita una precisión de ~ 1 segundo, así que use rdate o elija algo de uno de los muchos algoritmos de sincronización de reloj.
Una vez que haya elegido un método, haga que la máquina de cada jugador recoja el tiempo por ese método (sin cambiar el reloj de su sistema). Cualquier diferencia que haya entre la hora UTC de referencia y la hora UTC del reloj del sistema de los jugadores es su compensación efectiva. Cada vez que realice cálculos relacionados con el tiempo para, por ejemplo, extrapolar movimientos de bot o viñetas de trazado de rayos, tendrá en cuenta este desplazamiento después de obtener la hora del sistema. El uso de UTC eliminará los factores de zona horaria.
fuente
En segundo lugar, declaro que no debe usar NTP ni acercarse al reloj del sistema para esto. Si realmente examina este requisito, encontrará que tiene las siguientes necesidades:
Este es un esquema simplificado: no intento abordar problemas como la latencia / paquetes descartados / etc., pero es el marco básico en el que se debe basar todo.
Nada de esto debe acercarse al reloj del sistema o preocuparse por asuntos tales como diferentes zonas horarias, aunque el último elemento puede usar una zona horaria si lo desea. Lo importante es que los tiempos transcurridos reales se miden utilizando un temporizador de alta resolución basado en cero, por lo que son completamente independientes de las diferencias de zona horaria. ¿Quieres encontrar la hora actual en el servidor? Simplemente agregue el tiempo transcurrido al tiempo base de referencia y ya lo tiene. Igualmente para el cliente.
fuente