He estado pensando en un juego RTS multijugador. La parte que parece que no puedo evitar es mantener sincronizados los movimientos de la unidad. Si muevo la unidad A para detectar XY, tengo que comunicarlo al servidor que lo retransmite al otro cliente.
Tengo curiosidad por cómo se verían las comunicaciones. ¿Le comunicaría al servidor que estoy moviendo la unidad A a XY desde JZ? ¿Quizás necesites comunicar el movimiento coord por coord en su lugar? ¿Cuál es la metodología más eficiente para comunicar el movimiento de unidades de un cliente a otro?
EDITAR
Esta es una pregunta publicada de stackoverflow . Descubrí que este sitio era probablemente un mejor lugar para la pregunta.
Una de las mejores respuestas de esa publicación:
¿Supongo que tiene la intención de usar el paradigma de red Cliente-Servidor? En cuyo caso no puede confiar en que los clientes manejarán el posicionamiento real de las unidades, debe delegar esa tarea al servidor. Luego toma la lista de comandos de cada cliente por tic y calcula el movimiento de cada unidad, una vez que se ha completado, el siguiente tic retransmite la posición de cada unidad relevante para cada cliente (ya sea en un mapa completo o por vista) e inicie el proceso nuevamente.
Respuestas:
No desea sincronizar las posiciones de todas las unidades del servidor a cada cliente; eso ocupará mucho más ancho de banda de lo que necesita. También tendría que ocuparse de los puestos de unidades de interpolación / extrapolación, etc. ¡ Casi ningún profesional de RTS utiliza cliente / servidor!
En cambio, solo quieres enviar los comandos de los jugadores. En lugar de mover las unidades inmediatamente cuando el jugador hace clic, colocará en cola el comando de movimiento para que se realice en algún momento en el futuro, generalmente solo un par de fotogramas. Todos envían sus comandos a todos. Un par de cuadros más tarde, todos ejecutan todos los comandos y, debido a que el juego es determinista, todos ven el mismo resultado.
La desventaja es que cada jugador es tan lento como el jugador más lento: si alguien se atrasa en el envío de comandos, todos deben reducir la velocidad y esperar a que se ponga al día (en Starcraft 2, este es el "XXX está ralentizando el juego"). " diálogo).
De hecho, hay una cosa más que generalmente se hace: eliminar el servidor por completo . Haga que cada cliente envíe sus comandos a todos los demás clientes. Esto reduce el retraso (en lugar de un comando que va desde usted -> servidor -> oponente, solo va desde usted -> oponente) y facilita la codificación, ya que ya no necesita codificar un servidor separado. Este tipo de arquitectura se llama punto a punto (P2P).
La desventaja es que ahora necesitas una forma de resolver conflictos, pero dado que los comandos de los jugadores son independientes entre sí en la mayoría de los RTS, esto generalmente no es un gran problema. Además, no se escala bien: cada vez que agrega un nuevo jugador, cada jugador debe enviarle sus comandos. No vas a hacer un MMO RTS usando P2P.
Esta configuración (enviando solo comandos usando P2P) es la forma en que funcionan la mayoría de los RTS, incluidos Starcraft, C&C y AoE, y es la única forma en que AoE podría admitir 1500 unidades en una conexión de 28.8 kbps .
Aquí hay algunos consejos más para escribir un P2P RTS:
rand()
,cos()
etc., sino que prácticamente todas las matemáticas de punto flotante están fuera de discusión (ver aquí , aquí y aquí ) . En ese caso, es mejor que use cliente-servidor.fuente
Hice un RTS en red TCP, en el que pasé los comandos ellos mismos, en lugar de los resultados de los comandos . Por ejemplo, un jugador da una orden de movimiento. Si la orden de movimiento es válida de acuerdo con ese cliente, se envía al servidor. El servidor luego lo envía de vuelta a todos los clientes, quienes lo validan y ejecutan.
Entonces, todas las máquinas cliente ejecutan el juego ellas mismas, el código del servidor acepta mensajes y los envía de vuelta a todos los clientes. Si un cliente da una orden de movimiento, no comenzará a ejecutarla hasta que la reciba del servidor.
El servidor también envía un número de 'tick' para ejecutar el comando, que se encuentra unos pocos tics antes del tick 'actual'. De esta forma, todos los comandos se pueden ejecutar con el mismo 'tic' en todas las máquinas.
Un beneficio de este método es que no depende de ninguna máquina cliente individual para validar el comando. Si supero los resultados del movimiento, podría piratearlo para mover mis unidades más rápido. Todos los clientes tienen que ejecutar el mismo comando y si una máquina lo ejecuta de manera diferente, será obvio.
No es necesario validar el comando del lado del cliente antes de enviarlo al servidor, pero en teoría ahorra tráfico de red. Usé el mismo código de validación para decirle a la interfaz de usuario que el movimiento era posible, por lo que no requería escribir código adicional.
En cuanto a cómo se verían los mensajes. No me preocupaba la ultraeficiencia, ya que era mi primer juego en red. Pasé comandos como cadenas. Los comandos se formatearían así:
"<player_id>:<command>:<parameters>"
Para un ejemplo artificial, un comando de desplazamiento podría tener este aspecto:
"3:move:522:100:200"
. Esto significa que el jugador3
quieremove
unir522
a (100
,200
).El servidor pasa el mando a todos los clientes, entre ellos el que lo envió, con un número garrapata como esto:
"153238:3:move:522:100:200"
.Entonces, todos los clientes ejecutarán este comando cuando se ejecute la marca 153238.
fuente