Nota del traductor: este artículo ya tiene 17 años y es interesante solo desde un punto de vista histórico. Es interesante saber cómo los desarrolladores lograron lograr un juego en línea sin problemas en la era de los módems 28.8k y los primeros Pentiums.Este artículo habla sobre la arquitectura y la implementación, así como algunas lecciones aprendidas de la creación del código multiusuario (red) para los juegos
Age of Empires 1 y 2 . También describe los enfoques de arquitectura de red actuales y futuros utilizados por Ensemble Studios en sus motores de juego.
Multijugador Age of Empires: requisitos de estructura
Al comienzo del trabajo en el código multijugador
Age of Empires en 1996, nos fijamos objetivos muy específicos necesarios para la implementación del juego requerido.
- Batallas históricas a gran escala y épicas con muchas unidades militares diferentes
- Soporte para hasta 8 jugadores en modo multijugador.
- Simulación de juego sin problemas a través de LAN, a través de una conexión directa de módem y por Internet
- Soporte de plataforma de destino: Pentium 90 con 16 MB de RAM y módem de 28.8 kbps
- El sistema de comunicación debería funcionar con el motor existente (Genie)
- Estable 15 cuadros por segundo en máquinas con configuración mínima
El motor Genie ya estaba listo, y la jugabilidad en modo de usuario único comenzó a tomar sus formas. El motor Genie es un motor de bucle de juego de un solo subproceso bidimensional. Los sprites se representan en 256 colores en un mundo compuesto de mosaicos. Los mapas generados aleatoriamente están llenos de miles de objetos: desde árboles que se pueden cortar hasta gacelas galopantes. El desglose aproximado (después de la optimización) del tiempo para realizar tareas del motor: 30% para renderizar gráficos, 30% para IA y encontrar rutas, 30% para realizar simulaciones y tareas oficiales.
Ya en una etapa bastante temprana, el motor era relativamente estable, y las comunicaciones multiusuario tenían que funcionar con código listo sin la necesidad de un cambio significativo en la arquitectura (de trabajo) existente.
Para complicar la tarea, el tiempo necesario para completar cada paso de simulación podría variar mucho: el tiempo de representación dependía de si el usuario estaba mirando las unidades, desplazándose o mirando el área inexplorada, y las rutas largas o la planificación estratégica de la IA afectaron significativamente el tiempo de ejecución del movimiento del juego : las oscilaciones fueron de hasta 200 ms.
Breves cálculos mostraron que la transferencia de incluso un pequeño conjunto de datos sobre las unidades y los intentos de actualizarlos en tiempo real limitan en gran medida el número de unidades y objetos con los que el jugador puede interactuar. Si simplemente transfieres las coordenadas X e Y, estado, acción, dirección de visión y daño, entonces en el juego no puede haber más de 250 unidades móviles.
Queríamos que los jugadores pudieran destruir ciudades griegas con catapultas, arqueros y guerreros, mientras al mismo tiempo libraban asedios con trirremes desde el mar. Obviamente, necesitábamos algún otro enfoque.
Simulaciones simultáneas
En lugar de transmitir el estado de cada unidad del juego, queríamos realizar simulaciones absolutamente idénticas en cada máquina, pasando cada uno el mismo conjunto de comandos dados por los jugadores al mismo tiempo. Las computadoras de los jugadores, en esencia, tenían que sincronizar el juego en las mejores tradiciones de las películas de guerra, permitiendo a los jugadores emitir comandos y luego ejecutarlos de la misma manera y al mismo tiempo, asegurando la identidad de los juegos.
Inicialmente, una sincronización tan complicada fue difícil de implementar, pero como resultado, trajo ventajas inesperadas en otras áreas.
Mejora de modelo básicoEn el nivel conceptual más simple, implementar simulaciones simultáneas parece muy fácil. En algunos juegos que usan simulaciones con un paso fijo (paso de bloqueo) y tiempos constantes, incluso puede ser bastante posible.
Dado que con este enfoque debe asumir la responsabilidad de mover simultáneamente cientos o miles de objetos, el sistema debe seguir siendo viable incluso con fluctuaciones de retraso de 20 a 1000 milisegundos y lograr procesar los cambios durante el procesamiento del marco.
Enviar los comandos del jugador, confirmar todos los mensajes y luego procesarlos antes de pasar al siguiente movimiento sería una pesadilla desde el punto de vista del proceso del juego, con una espera constante y un lento intercambio de equipos. Necesitábamos un esquema que pudiera continuar procesando el juego en paralelo con el fondo esperando la finalización del proceso de intercambio de datos.
Mark [Terrano] utilizó un sistema para marcar comandos que deberían ejecutarse a través de dos "movimientos de intercambio de datos" en el futuro (los movimientos de intercambio de datos en
AoE se separaron de los propios marcos de representación).
Es decir, los comandos dados durante el curso 1000 se asignan para ejecutarse durante el curso 1002 (ver Fig. 1). En el curso de 1001, se ejecutan los comandos dados en el curso de 0999. Esto nos permitió recibir, confirmar y preparar mensajes para el procesamiento, mientras el juego continuaba dibujando animaciones y realizando simulaciones.
Figura 1. Marcado de comandos que se ejecutarán a través de dos "movimientos de intercambio de datos".Por lo general, los movimientos tomaron 200 ms, y los equipos fueron enviados durante este turno. Después de 200 ms, el movimiento se detuvo y comenzó un nuevo movimiento. En cada momento del juego, los equipos fueron procesados en un movimiento, recibidos y guardados para el siguiente movimiento, y luego enviados para su ejecución dos movimientos más tarde.
"Control de velocidad"
Figura 2. Control de velocidad.Dado que las simulaciones siempre deben tener exactamente la misma entrada, un juego no puede ejecutarse más rápido de lo que la máquina más lenta logra procesar el intercambio de datos, realizar un movimiento y enviar nuevos comandos. Llamamos al sistema que cambia la duración de la carrera para mantener animaciones y juegos sin problemas en condiciones de retraso de intercambio de datos variables y velocidad de procesamiento "Control de velocidad".
El juego se puede sentir "frenando" por dos razones: si la velocidad de fotogramas de una máquina cae (o es más baja que el resto), entonces otras máquinas procesan sus comandos, procesan todo en el tiempo asignado y como resultado tienen que esperar el próximo movimiento. En este caso, cualquier pausa se hace evidente de inmediato. Además, el juego se ralentiza por un retraso en el intercambio de datos: los jugadores tienen que esperar hasta que la máquina reciba suficientes datos para completar el movimiento.
Cada cliente calculó la velocidad de fotogramas que se consideraba constantemente alcanzable, que se calculó promediando el tiempo de procesamiento de varios fotogramas. Dado que este valor cambia durante el juego dependiendo del alcance, el número de unidades, el tamaño del mapa y otros factores, se transmitió en cada mensaje sobre la finalización del movimiento.
Además, cada cliente también midió el "tiempo de ping" de sí mismo a otros clientes y viceversa. También envió el ping promedio al cliente más largo en un mensaje sobre la finalización del movimiento (en total, se usaron 2 bytes para controlar la velocidad).
En cada movimiento, la máquina designada por el host analizó los mensajes de finalización, calculó la velocidad de fotogramas necesaria y la corrección por el retraso en la transmisión de datos a través de Internet. Luego, el host envió una nueva velocidad de cuadros y la duración del intercambio de datos. Las Figuras 3-5 muestran cómo se dividió el flujo de intercambio de datos en diferentes condiciones.
Figura 3. Flujo típico de intercambio de datos.Figura 4. Transmisión de datos de alta latencia a través de Internet a la velocidad normal de la máquina.Figura 5. Baja velocidad de la máquina con retraso de transferencia de datos normal.El "progreso del intercambio de datos", que era aproximadamente igual al tiempo de ping para el viaje de ida y vuelta para el mensaje, se dividió por el número de tramas de simulación que la máquina más lenta podía realizar en promedio durante este tiempo.
La duración del intercambio de datos se ponderó, por lo que podría aumentar rápidamente de acuerdo con los cambios en la latencia de la transmisión de datos a través de Internet y disminuir lentamente a la mejor velocidad promedio que se puede mantener constantemente. Por lo general, el juego se ralentizó y se ralentizó solo en los momentos de los peores picos: el retraso de transmisión de los comandos aumentó, pero se mantuvo suave (y aumentó solo unos pocos milisegundos por turno), porque el juego redujo gradualmente los retrasos a la mejor velocidad posible. Esto creó la mayor suavidad posible del juego, mientras que al mismo tiempo proporcionaba un ajuste a las condiciones cambiantes.
Entrega garantizada
Se usó UDP en la capa de red, y cada cliente estuvo involucrado en ordenar comandos, reconocimiento de pérdidas y retransmisión. Cada mensaje usaba un par de bytes, indicando el curso para el cual se planeó la ejecución de los comandos, y el número de serie del mensaje. Si se recibió un mensaje después del traslado, se rechazó y los mensajes entrantes se guardaron para su ejecución. Debido a la naturaleza de UDP, Mark utilizó el siguiente principio al recibir mensajes: “En caso de duda, debe considerar el mensaje perdido. Si los mensajes se reciben fuera de servicio, el destinatario envía inmediatamente una solicitud de retransmisión de mensajes perdidos. Si la confirmación de recepción se recibe más tarde que el tiempo previsto, el remitente simplemente envía el mensaje nuevamente, sin esperar una señal sobre su pérdida ".
Beneficios ocultos
Dado que los resultados calculados por el juego dependían de que todos los usuarios realizaran simulaciones idénticas, era increíblemente difícil para un cliente (o flujo de datos del cliente) piratear y engañar. Cualquier simulación realizada de manera diferente se marcó como "fuera de sincronización" y el juego se detuvo. Todavía era posible hacer trampa localmente para la divulgación de información, pero tales filtraciones se solucionaron con relativa facilidad en parches y revisiones posteriores. La seguridad se ha convertido en nuestra mayor victoria.
Problemas ocultos
Al principio, puede parecer que la misma ejecución de dos instancias del mismo código es fácil de implementar, pero no lo es. En las primeras etapas del proyecto, el gerente de producto de Microsoft Tim Znamenachek le dijo a Mark: “Cada proyecto tiene un error persistente que no se rinde hasta el final. Creo que en nuestro caso no estará sincronizado ”. Y tenía razón. Las dificultades de encontrar errores de sincronización se multiplicaron con cada pequeño cambio. El venado, cuya posición es ligeramente diferente al crear un mapa aleatorio, se moverá un poco diferente, y minutos después el cazador se moverá un poco fuera del camino o perderá una lanza, como resultado de regresar a casa sin carne. Por lo tanto, lo que a veces parecía ser solo una diferencia en las sumas de control de la cantidad de alimentos tenía razones que eran muy difíciles de rastrear.
Aunque revisamos el mundo, los objetos, buscamos rutas, apuntamos y todos los demás sistemas con sumas de verificación, siempre había algo que no podíamos tener en cuenta. Enormes (50 MB cada uno) volúmenes de rastreo de mensajes y volcados de objetos mundiales complicaron aún más el problema. Parte de las dificultades era conceptual: los programadores no estaban acostumbrados a escribir código que usaba la misma cantidad de llamadas generadoras de números aleatorios en una simulación (sí, también se generaban y sincronizaban números aleatorios).
Lecciones aprendidas
Al desarrollar la parte de la red de
Age of Empires, recibimos varias lecciones que se pueden aplicar al desarrollo de cualquier sistema multiusuario de juegos.
Conoce a tu usuario. Estudiar al usuario es el paso más importante para comprender sus expectativas con respecto a la velocidad del multijugador, los frenos percibidos y los retrasos en la transmisión de comandos. Cada género es individual, y debes comprender qué se adapta a tu estilo de juego y gestión.
En las primeras etapas del proceso de desarrollo, Mark y el diseñador principal prototiparon los retrasos en el intercambio de datos (este prototipo fue revisado varias veces durante el proceso de desarrollo). Como estaban jugando un juego para un solo jugador, fue muy fácil simular diferentes niveles de demoras en la transferencia del equipo y obtener retroalimentación de los jugadores (“el control parece bueno / lento / contracciones / simplemente horrible”).
Para los juegos del género RTS, los retrasos en la transmisión de comandos de 250 milisegundos ni siquiera se notan, a 250-500 ms la jugabilidad es bastante jugable, y los frenos se notan a 500 ms o más. También es interesante notar que los jugadores están acostumbrados al "ritmo del juego" y la expectativa mental de un retraso entre los clics del mouse y las reacciones de la unidad. Una respuesta retardada constante fue mejor que los saltos en los retrasos en la transmisión de comandos (por ejemplo, de 80 a 500 ms); en este caso, los retrasos constantes de 500 ms se percibieron como jugables, y los modificables parecían "nerviosos" y complicaban el juego.
Esto obligó a los programadores a dirigir sus esfuerzos para garantizar la suavidad: es mejor elegir una duración de carrera más larga y asegurarse de que todo sea suave y constante que realizar operaciones lo más rápido posible, frente a ralentizaciones regulares. Todos los cambios en la velocidad deben ser graduales y la tasa de crecimiento debe ser lo más pequeña posible.
También medimos los requisitos del usuario para el sistema: por lo general, daban órdenes (mover, atacar, cortar árboles) aproximadamente cada uno y medio o dos segundos, a veces con picos de 3-4 equipos por segundo durante feroces batallas. Como las acciones activas en nuestro juego están en constante crecimiento, los requisitos más altos para el intercambio de datos surgen en el medio y cerca del final del juego.
Si se toma el tiempo de estudiar el comportamiento de los usuarios, notará otras características de cómo juegan, y esto ayudará a configurar el juego en red. En
AoE durante los ataques, los usuarios hicieron clic rápidamente en el mouse (clic-clic-clic-clic - ¡adelante-adelante-adelante-adelante!), Lo que condujo a picos enormes en la cantidad de comandos emitidos. Además, enviaron grandes grupos de unidades que necesitan allanar el camino, también grandes picos en los requisitos para la transmisión de datos a través de la red. Un filtro simple, cortando comandos repetidos en un punto, redujo significativamente el impacto negativo de este comportamiento.
En general, monitorear usuarios le permitirá:
- Descubre las expectativas de los usuarios sobre los retrasos en los juegos
- Prototipo de aspectos multijugador en las primeras etapas de desarrollo
- Vea el comportamiento que va en detrimento de la velocidad del modo multiusuario.
La medición es lo más importante. Si introduce métricas en las primeras etapas del trabajo, aprenderá cosas sorprendentes sobre su sistema de intercambio de datos. Haga que las métricas sean legibles para los probadores y úselas para comprender lo que sucede dentro del motor de red.
Lección: Parte del problema con el intercambio de datos en AoE surgió cuando Mark dedujo las métricas demasiado pronto y no verificó los niveles del mensaje (longitud y frecuencia) nuevamente después de preparar el código final. Cosas inesperadas como carreras aleatorias entre IA, rutas difíciles de calcular y paquetes de comandos mal estructurados pueden causar grandes problemas de rendimiento, incluso cuando el sistema funciona bien.
Hacer que el sistema notifique a los probadores y desarrolladores de lo que parece ser un exceso de condiciones límite: los programadores y los probadores verán en el proceso de desarrollo qué tareas cargan el sistema; Esto resolverá los problemas en las primeras etapas de su aparición.
Tómese el tiempo para explicarles a los evaluadores cómo funciona el sistema de intercambio de datos, mostrarles y explicarles las métricas; es posible que se sorprendan de que noten cuando inevitablemente ocurren fallas extrañas en el código de red.
En general, las métricas deben tener las siguientes propiedades:
- Ser legible y comprensible para los evaluadores.
- Indicar cuellos de botella, frenos y problemas.
- Poco impacto en la ejecución y lanzamiento constante.
Formación de desarrolladores. Es muy difícil enseñar a los programadores que están acostumbrados a crear aplicaciones para un solo usuario a pensar en la separación entre dar, recibir y procesar un comando. Es fácil olvidar que puede pedir algo que no sucedió o lo que podría suceder unos segundos después de que se emitió el comando. Se debe verificar que los comandos sean correctos tanto al enviar como al recibirlos.
En un modelo síncrono, los programadores también deben considerar que dentro de la simulación, el código no debe depender de ningún factor local (como la disponibilidad de tiempo libre, equipo especial o diferentes configuraciones). La ejecución del código en todas las máquinas debe coincidir. Por ejemplo, la presencia de sonidos de terreno aleatorios dentro de una simulación puede conducir a un comportamiento de juego diferente.
Otras lecciones Este debería ser el sentido común habitual, pero si depende de una red de terceros (en nuestro caso, es DirectPlay), escriba una aplicación de prueba independiente que confirme que cuando los propietarios reclaman "entrega garantizada", los mensajes realmente obtienen ese "pedido de paquete garantizado" de hecho lo hay, y que el producto no tiene cuellos de botella ocultos o comportamiento extraño al procesar los datos transmitidos en su juego.
Prepárese para crear aplicaciones de simulación y simuladores de prueba de esfuerzo. Al final, creamos tres aplicaciones diferentes de prueba mínima que se utilizan para estudiar problemas individuales e importantes: inundaciones de conexión, problemas con conexiones simultáneas al seleccionar oponentes y paquetes garantizados perdidos.
Pruebe con módems (y, con suerte, con simuladores de módem) lo antes posible; Continúe con las pruebas de módem (no importa cuán doloroso pueda ser) durante todo el proceso de desarrollo.
Después de todo, es difícil aislar los problemas (¿cuál es la razón de la fuerte disminución de la velocidad: el proveedor, el juego, el software de comunicación, el módem, el servicio de búsqueda rival para el partido o algo más?), Y los usuarios no quieren molestarse con conexiones de marcado lento, acostumbrarse a velocidades de LAN instantáneas . Es vital que pruebe en las conexiones de módem con la misma persistencia que con los juegos LAN multijugador.Mejoras para Age of Empires 2
En Age of Empires 2: The Age of Kings, agregamos funciones multiusuario como grabación de juegos, transferencia de archivos y seguimiento constante de estadísticas en el sitio web de The Zone. También mejoramos los sistemas multijugador, como la integración de DirectPlay y el control de velocidad para tratar los errores y problemas de velocidad identificados después del lanzamiento de Age of Empires .La función de grabar juegos fue una de esas cosas que se inventaron originalmente para la depuración, y como resultado se convirtió en una "característica" completa del juego. Los juegos grabados son increíblemente populares en los sitios de fanáticos. Permiten a los jugadores compartir estrategias y analizarlas, ver batallas famosas y aprender los juegos en los que participaron. La grabación de juegos se ha convertido en una herramienta de depuración invaluable. Como nuestra simulación es determinista y los juegos grabados son sincrónicos en el mismo sentido que el modo multijugador, los juegos de grabación nos proporcionaron una excelente forma de jugar errores, porque cada vez se garantizaba que se jugaría de la misma manera.Nuestra integración con el servicio de búsqueda rival (emparejamiento) de The Zone se limitó en Age of Empires para simplemente lanzar el juego. En la era de los reyeslo expandimos y esto nos permitió controlar los parámetros de lanzamiento y proporcionar informes constantes sobre estadísticas. Esto permitió a los jugadores encontrar mejor los juegos que les interesaban, porque podían ver los parámetros del nivel de emparejamiento y no esperar a que la configuración del juego vaya a la pantalla de configuración del juego. En el backend, implementamos informes constantes y estadísticas de seguimiento. Proporcionamos a The Zone una estructura común que se rellenó y transfirió al servidor al final del juego. Los datos de esta estructura se utilizaron para crear clasificaciones de usuarios y mostrarlas en el sitio web de The Zone.Multijugador RTS3: tareas
RTS3 es el nombre en clave para el juego de estrategia de próxima generación Ensemble (aprox. Por: el juego fue lanzado bajo el nombre de Age of Mythology) . La estructura RTS3 se crea en base a la fórmula exitosa utilizada en la serie de juegos Age of Empires, con la adición de muchas características y requisitos nuevos para el modo multiusuario.- Basado en el conjunto de características de Age of Empires 1 y 2 . Requisitos obligatorios como jugar en Internet, mapas grandes y variados, miles de unidades administradas.
- 3D: RTS3 es un juego totalmente tridimensional con animaciones interpoladas y posiciones no discretas y rotaciones de unidades.
- Más jugadores: soporte para más de ocho jugadores.
- Soporte TCP / IP: Nuestro objetivo principal es una conexión a Internet TCP / IP de 56 / kbps.
- Soporte de red doméstica: soporte para configuraciones de red de usuario final, incluidos firewalls y NAT.
Incluso en las primeras etapas del desarrollo de RTS3, decidimos seguir el mismo modelo de red interna que en Age of Empires 1 y 2 , simulación sincrónica, porque la estructura RTS3 podrá aprovechar dicha arquitectura de muchas maneras. En AOE / AOK, utilizamos DirectPlay para los servicios de transferencia y administración de sesiones, pero para RTS3 decidimos crear una biblioteca de red básica utilizando procedimientos de socket exclusivamente básicos como base.La transición a un mundo totalmente tridimensional significa que debemos estar más atentos a los problemas con la velocidad de fotogramas y la suavidad general de la simulación en modo multiusuario. Sin embargo, esto también significa que el tiempo de actualización de la situación de simulación y la velocidad de fotogramas estarán aún más sujetos a la variabilidad, y que tendremos que dedicar más tiempo a la representación. En el motor Genie, las rotaciones de las unidades eran discretas, y las animaciones estaban vinculadas a la velocidad de fotogramas en BANG. La rotación arbitraria de la unidad y la animación suave son posibles, es decir, visualmente el juego será mucho más sensible a la influencia de los retrasos y saltos en la frecuencia de actualización.Finalizando la Era de los Reyes, queríamos abordar estas áreas críticas en las que el diseño cuidadoso y el trabajo con herramientas reducirían en gran medida el tiempo de depuración. También nos dimos cuenta de lo importante que es el proceso de prueba iterativa en el diseño de nuestros juegos, por lo que se le dio una alta prioridad a la conclusión más temprana posible del juego en línea.Arquitectura de comunicación RTS3
Figura 6. Arquitectura de red estricta orientada a objetos de RTS3.Enfoque orientado a objetos. La arquitectura de red de RTS3 está altamente orientada a objetos (ver Figura 6). Los requisitos de soporte para varias configuraciones de red le permiten aprovechar el enfoque OO, abstracto de los detalles de la plataforma, el protocolo y la topología que subyacen a un conjunto de objetos y sistemas generalizados.Las versiones específicas de protocolo y topología de los objetos de red contienen el menor código posible. La funcionalidad principal de estos objetos es abundante en los objetos principales de alto nivel. Para implementar el nuevo protocolo, expandimos solo aquellos objetos de red que necesitaban un código específico del protocolo (por ejemplo, para el cliente y la sesión, que deberían actuar de manera ligeramente diferente dependiendo del protocolo). Ningún otro objeto del sistema (como Channels, TimeSync, etc.) requirió cambios, ya que tenían una interfaz con el cliente y la sesión solo a través de sus interfaces abstractas de alto nivel.Topología de igual a igual.El motor Genie admite una topología de red punto a punto en la que todos los clientes de una sesión se conectan entre sí en una configuración en estrella. En RTS3, continuamos usando esta topología, porque cuando se implementa con un modelo de simulación síncrona, tiene ventajas inherentes.La topología punto a punto implica el uso de una configuración en estrella para clientes conectados en una sesión (Figura 7). Es decir, cada cliente está conectado a todos los demás clientes. El mismo esquema se utilizó en los años 1 y 2 .Figura 7. Configuración en estrella de clientes pares en una sesión.Beneficios de igual a igual:- Disminución de la latencia debido al esquema de mensajería de cliente a cliente en lugar de cliente-servidor-cliente.
- No hay un enlace débil central: si el cliente (incluso el host) se desconecta de la sesión, el juego puede continuar.
Desventajas de igual a igual:- Compuestos más activos en el sistema (suma de n = 0 a k-1 (n)), es decir, más enlaces débiles potenciales y mayores retrasos probables.
- La incapacidad de admitir algunas configuraciones NAT en dicho esquema.
Net.lib. Al desarrollar la arquitectura de intercambio de datos RTS3, nuestro objetivo era crear un sistema diseñado específicamente para juegos estratégicos, pero al mismo tiempo queríamos crear un sistema que pudiera usarse para nuestras herramientas internas, así como expandirlo para admitir juegos futuros. Para lograr este objetivo, hemos creado una arquitectura multicapa que admite objetos de nivel de juego como cliente y sesión, pero también admite objetos de transporte de bajo nivel como enlaces y direcciones de red.Figura 8. Cuatro capas de servicios en nuestro modelo de red.¡RTS3 se basa en nuestro motor BANG! Una nueva generación que utiliza arquitectura modular con bibliotecas de componentes como sonido, renderizado y redes. El subsistema de red está integrado aquí como un componente, ¡pero está conectado al motor BANG! (así como con varias herramientas internas). Nuestro modelo de red está dividido en cuatro capas de servicios, que son casi, pero no completamente, no similares al modelo de red OSI utilizado en el juego (ver Figura 8).Calcetines Nivel 1El primer nivel, Socks, proporciona una API fundamental de nivel de socket en C. Se abstrae para crear un conjunto genérico de procedimientos de red de bajo nivel para muchos sistemas operativos. La interfaz se asemeja a la interfaz de socket Berkeley. La capa Socks es utilizada principalmente por las capas superiores de la biblioteca de red y no está destinada a ser utilizada por el código de la aplicación.Enlace, Nivel 2Nivel 2, Enlace, proporciona servicios de capa de transporte. Los objetos en este nivel, como Link, Listener, NetworkAddress y Packet, son elementos útiles necesarios para establecer una conexión y enviar mensajes a través de ella (ver Figura 9).- Packet (): — , / ( ) .
- Link (): . , . send receive , , void*.
- Listener (): . .
- Data stream ( ): , , , .
- Dirección de red: una entidad de direccionamiento de red independiente del protocolo.
- Ping: una clase de ping simple. Informa un retraso de red presente cuando se comunica con el enlace.
Figura 9. Nivel de enlace.
Nivel multijugador 3El nivel multijugador es el nivel más alto de objetos y procedimientos presentes en la API net.lib. Esta es la capa con la que RTS3 interactúa al recopilar objetos de un nivel inferior, como enlaces y convertirlos en conceptos / objetos más útiles: clientes, sesiones, etc.¡Los objetos más interesantes de la biblioteca de la red BANG! son aquellos que están en el nivel multijugador. Aquí, la API proporciona un conjunto de objetos con los que el nivel del juego puede interactuar, pero proporciona una implementación independiente del enfoque del juego.- Client (): . () ( ). , .
- Session (): , , , . . host() join(), , , . / , .
- Channel Ordered Channel: . . TimeSync, .
- Shared Data: . , , .
- Time Sync: .
Game Communications Level 4La capa de comunicaciones es parte del RTS3. Esta es la colección principal de sistemas a través de los cuales el juego interactúa con la biblioteca de la red, viviendo dentro del código del juego. La capa de comunicaciones proporciona muchas funciones auxiliares útiles para crear y administrar objetos de red en el nivel multijugador, tratando de reducir las necesidades del juego multijugador a una interfaz pequeña y fácil de usar.Nuevas funciones y herramientas mejoradas.
Sistema de sincronización mejorado. Ninguno del equipo de desarrollo
de Age of Empires podría decir que no necesitamos mejores herramientas de sincronización. Como en cualquier proyecto, al analizar el proceso de desarrollo en la autopsia, resulta que la mayor parte del tiempo se dedicó a algunas áreas, pero podría ser mucho menos si los abordamos por adelantado. Al comienzo del desarrollo de RTS3, en la parte superior de la lista de tales áreas estaba la sincronización de depuración.
El sistema de seguimiento de sincronización RTS3 está dirigido principalmente a reconocer rápidamente errores de sincronización. Otras prioridades fueron la simplificación del uso, la capacidad de procesar cantidades arbitrariamente grandes de datos sincronizados que pasaron por el sistema, la capacidad de compilar completamente el código de sincronización en la versión de lanzamiento y, finalmente, la capacidad de cambiar completamente la configuración de prueba cambiando las variables en lugar de volver a compilar por completo.
La verificación de sincronización en RTS3 se realiza utilizando dos conjuntos de macros:
#define syncRandCode(userinfo)
gSync->addCodeSync(cRandSync, userinfo, __FILE__, __LINE__)
#define syncRandData(userinfo,
v) gSync->addDataSync(cRandSync, v, userinfo, __FILE__, __LINE__)
Ambas macros reciben el parámetro de cadena userinfo, que es el nombre o la indicación de un elemento sincronizado específico. Por ejemplo, una llamada de sincronización podría verse así:
syncRandCode("syncing the random seed", seed);
Comandos síncronos de consola y variables de configuración. Como puede confirmar cualquier desarrollador de mod de
Quake , los comandos de consola y las variables de configuración son muy importantes para el proceso de desarrollo. Los comandos de consola son llamadas a funciones simples realizadas utilizando el archivo de configuración de inicio, la consola del juego o la interfaz de usuario, que invocan funciones arbitrarias del juego. Las variables de configuración se denominan tipos de datos proporcionados a través de las funciones simples get, set, define y toggle, que usamos para todo tipo de pruebas y configuración de parámetros de configuración.
Paul creó versiones compatibles con multijugador de nuestros sistemas de comando de consola y configuraciones variables. Con su ayuda, podemos convertir convenientemente una variable de configuración regular (por ejemplo, enableCheating) en una variable de configuración multijugador agregando un indicador a la definición de la variable de configuración. Si este indicador está habilitado, la variable de configuración se transfiere dentro del juego multijugador, y las decisiones sincronizadas en el juego (por ejemplo, sobre la permisibilidad de la transferencia gratuita de recursos) pueden basarse en su valor. Los comandos de consola del modo multijugador tienen un principio similar: las llamadas a los comandos de consola del modo multijugador se transmiten a través de la red y se ejecutan sincrónicamente en todas las máquinas cliente.
Al usar estas dos herramientas, los desarrolladores pueden usar el sistema multijugador sin escribir código. Pueden agregar rápidamente nuevas herramientas de prueba y configuración e integrarlas fácilmente en un entorno en red.
Para resumir
La simulación sincronizada y el modelo de igual a igual se han utilizado con éxito en la serie de juegos Age of Empires. A pesar de la importancia crítica de invertir tiempo en la creación de herramientas y tecnologías para resolver los principales problemas de este enfoque (como la sincronización y las métricas de red), la experiencia ha demostrado la viabilidad de esta arquitectura en el género de las estrategias en tiempo real. Las mejoras posteriores que realizamos en RTS3 llevaron al hecho de que la jugabilidad multijugador es casi indistinguible de la de un solo jugador, incluso en las condiciones más terribles de las conexiones de red.