Pareces haber comenzado con algunas buenas ideas sobre la sincronización, pero es posible que haya dos problemas que te encuentres superpuestos: la sincronización de los relojes de juego y la sincronización de gamestate.
(1) la sincronización de los relojes de juego necesita alguna representación del 'tiempo de juego' para su juego. para un juego de 2 jugadores es muy razonable simplemente declarar una autoridad.
así en el cliente de autoridad:
OnUpdate()
gameTime = GetClockTime();
msg.gameTime = gameTime
SendGameTimeMessage(msg);
por otro cliente podría ser algo como:
OnReceivGameTimeeMessage(msg)
lastGameTimeFromNetwork = msg.gameTime;
lastClockTimeOfGameTimeMessage = GetClockTime();
OnUpdate()
gameTime = lastGameTimeFromNetwork + GetClockTime() - lastClockTimeOfGameTimeMessage;
hay complicaciones como saltar/deslizamiento (es decir, conseguir tiempos desde la red que van hacia adelante/hacia atrás demasiado) que requieren más trabajo, pero espero que entiendas la idea. Haga un seguimiento con otra pregunta si lo necesita.
Nota: este ejemplo no diferencia 'ticks' contra 'segundos' ni está vinculado a su protocolo de red ni al tipo de dispositivo en el que se ejecuta su juego (guarde el requisito 'el dispositivo tiene un reloj local')
(2) sincronizando el juego de estado después de tener un reloj de juego constante, todavía necesita averiguar cómo simular y propagar consistentemente su estado de juego. para sincronizar gamestate usted tiene un par de opciones:
asíncronos
- cada unidad de gamestate es 'propiedad' de un proceso. solo ese proceso está permitido para cambiar ese estado del juego. esos cambios se propagan a todos los demás procesos.
- si todo es propiedad de un solo proceso, esto a menudo se denomina juego 'cliente/servidor'.
- Nota: con este modelo, cada cliente tiene una visión diferente del mundo del juego en cualquier momento.
- ejemplo, juegos: Quake, World of Warcraft
para optimizar el ancho de banda y latencia piel, a menudo se puede hacer algo de simulación local para campos con una alta frecuencia de actualización. ejemplo:
drawPosition = lastSyncPostion + (currentTime - lastSyncTime) * lastSyncVelocity
por supuesto que tiene que reconciliar nueva información con su versión simulada en este caso.
síncrono
- cada unidad de gamestate es idéntico en todos los procesos.
- Los comandos de cada proceso se propagan entre sí con su tiempo de inicio deseado (en algún momento en el futuro).
- en su forma más simple, un proceso (a menudo llamado el host) envía mensajes especiales que indican cuándo adelantar el tiempo del juego. cuando todos reciben ese mensaje, pueden simular el juego hasta ese momento.
- el requisito "en el futuro" conduce a una alta latencia entre el comando de entrada y el cambio del estado del juego.
- en juegos en tiempo no real como la civilización, esto está bien. en un juego como Starcraft, normalmente el sonido que reconoce la entrada viene inmediatamente, pero la acción que afecta el estado del juego realmente se retrasa. este estilo no es apropiado para juegos como shooters que requieren acciones sensibles al tiempo (en la escala de ~ 100 ms).
síncrono con resimulation
- cada unidad de gamestate es idéntico en todos los procesos.
- cada proceso envía a todos los otros procesos su entrada con su marca de tiempo actual. además, periódicamente se envía un mensaje de 'nada sucedió'.
- cada proceso tiene 2 copias del sistema de juego.
- copia 1 del estado del juego se propaga al 'último mensaje más antiguo' que ha recibido de todos los demás clientes. esto es equivalente al modelo síncrono, pero tiene la debilidad de que representa un estado de juego de 'hace un momento'
- copia 2 del estado del juego es copia 1 más todos los mensajes restantes.es una predicción de lo que es el estado del juego en el momento actual en el cliente, suponiendo que nada nuevo sucede.
- el jugador interactúa con alguna combinación de los dos gamestate (idealmente 100% copia 2, pero algunos se debe tener cuidado para evitar estallidos como los nuevos mensajes lleguen)
- Juegos Ejemplo: Street Fighter 4 (reproducción a Internet)
Según su descripción, las opciones (1) y (3) parecen corresponder a su problema. nuevamente si tiene más preguntas o requiere más detalles, solicite un seguimiento.
¡Muchas gracias por la explicación! – user387184
La explicación del reloj del juego me parece clara. Si entiendo correctamente, básicamente le envía tiempo a los servidores para que el cliente adapte su tiempo de juego en consecuencia. Si esto sucede a través de BT o la red local, se puede ignorar el tiempo que requieren los mensajes de sincronización del servidor. Por ejemplo, si el servidor está en el momento 123 -> lo envía al cliente -> el cliente también puede establecer su propio tiempo en 123 (el retraso entre recibir el tiempo del servidor y actualizar el propio tiempo puede ignorarse si todo sucede en el mismo método) ¿Es esto correcto? – user387184
Mi pregunta restante es, ¿funcionará esto a través del GameCenter de Apple? Desde la introducción de Apple GameCenter entiendo que tienen una versión de GKtank worling sobre GameCenter. Pero, ¿cómo se sincronizan si los mensajes entre los dos jugadores toman más tiempo? ¿Pausa el juego? Gracias de nuevo – user387184