Estoy leyendo Game Coding Complete y el autor recomienda la comunicación dirigida por eventos entre los objetos y módulos del juego.
Básicamente, todos los actores de los juegos vivos deberían comunicarse con los módulos clave (Física, IA, Game Logic, Game View, etc.) a través de un sistema interno de mensajes de eventos. Esto significa tener que diseñar un administrador de eventos eficiente. Un sistema mal diseñado consume ciclos de CPU, que afectan especialmente a las plataformas móviles.
¿Es este un enfoque probado y recomendado? ¿Cómo debo decidir si usarlo?
architecture
software-engineering
events
Bunkai.Satori
fuente
fuente
libuv
Recientemente ha surgido como una exitosa biblioteca de eventos. (Está en C. Node.js es su caso de uso más famoso.)Respuestas:
Esta es una expansión de mi comentario a una respuesta completa, como se sugiere.
Sí , simple y llanamente. La comunicación debe suceder y, aunque hay situaciones en las que "¿Ya llegamos?" -tipo de sondeo, hacer que las cosas verifiquen para ver si deberían estar haciendo otra cosa generalmente desperdicia tiempo. En su lugar, podría hacer que reaccionen a las cosas que se les dice que hagan. Además, una vía de comunicación bien definida entre objetos / sistemas / módulos aumenta significativamente las configuraciones paralelas.
He presentado una descripción general de alto nivel de un sistema de mensajería de eventos en Stack Overflow . Lo he usado desde la escuela en títulos de juegos profesionales y ahora en productos que no son de juego, adaptados al caso de uso cada vez, por supuesto.
EDITAR : para responder una pregunta de comentario sobre cómo sabe qué objetos deben recibir el mensaje : los propios objetos deben
Request
ser notificados sobre los eventos. SuEventMessagingSystem
(EMS) necesitará unaRegister(int iEventId, IEventMessagingSystem * pOjbect, (EMSCallback)fpMethodToUseForACallback)
coincidenciaUnregister
(haciendo una entrada única para uniEventId
puntero y devolución de llamada fuera del objeto). De esta manera, cuando un objeto quiere saber acerca de un mensaje, puede hacerloRegister()
con el sistema. Cuando ya no necesita saber sobre los eventos, puedeUnregister()
. Claramente, desearía un grupo de estos objetos de registro de devolución de llamada y una forma efectiva de agregarlos / eliminarlos de las listas. (Por lo general, he usado matrices de pedido automático; una forma elegante de decir que rastrean sus propias asignaciones entre una pila de agrupación de objetos no utilizados y matrices que cambian sus tamaños en su lugar cuando es necesario).EDITAR : para un juego completamente funcional con un ciclo de actualización y un sistema de mensajería de eventos, es posible que desee ver un proyecto mío de la vieja escuela . La publicación de desbordamiento de pila vinculada anteriormente también se refiere a ella.
fuente
Mi opinión es que deberías comenzar a hacer tu juego e implementar aquello con lo que te sientas cómodo. Mientras lo hace, se encontrará utilizando MVC en algunos lugares, pero no en otros; eventos en algunos lugares, pero no en otros; componentes algunos lugares, pero herencia otros; diseño limpio en algunos lugares, y diseño rudo en otros.
Y está bien, porque cuando termines, tendrás un juego, y un juego es mucho más genial que un sistema de transmisión de mensajes.
fuente
Una mejor pregunta es, ¿qué alternativas hay? En un sistema tan complejo con módulos adecuadamente divididos para física, inteligencia artificial, etc., ¿de qué otra manera puede orquestar estos sistemas?
La transmisión de mensajes parece ser la "mejor" solución a este problema. No puedo pensar en alternativas en este momento. Pero hay muchos ejemplos de mensajes que pasan en la práctica. De hecho, los sistemas operativos utilizan el paso de mensajes para varias de sus funciones. De Wikipedia :
(La comunicación entre procesos es la comunicación entre procesos (es decir, ejecución de instancias de programas) dentro del entorno del sistema operativo)
Entonces, si es lo suficientemente bueno para un sistema operativo, probablemente sea lo suficientemente bueno para un juego, ¿verdad? También hay otros beneficios, pero dejaré que el artículo de Wikipedia sobre la transmisión de mensajes explique.
También hice una pregunta sobre Stack Overflow, "¿Estructuras de datos para pasar mensajes dentro de un programa?" , que es posible que desee leer de nuevo.
fuente
Los mensajes generalmente funcionan bien cuando:
Cuanto más coincidan sus necesidades con esa lista, mejores serán los mensajes adecuados. A un nivel muy general, son bastante buenos. Hacen un buen trabajo al no desperdiciar los ciclos de la CPU solo para no hacer nada a diferencia del sondeo u otras soluciones más globales. Son fantásticos para desacoplar partes de una base de código, lo que siempre es útil.
fuente
Grandes respuestas hasta ahora de James y Ricket, solo respondo para agregar una nota de precaución. La comunicación impulsada por mensajes / eventos es ciertamente una herramienta importante en el arsenal del desarrollador, pero se puede usar en exceso fácilmente. Cuando tienes un martillo, todo parece un clavo, y así sucesivamente.
Absolutamente, 100%, debe pensar en el flujo de datos alrededor de su título y ser plenamente consciente de cómo la información pasa de un subsistema a otro. En algunos casos, pasar mensajes es claramente mejor; en otros, puede ser más apropiado que un subsistema opere sobre una lista de objetos compartidos, permitiendo que otros subsistemas también operen en la misma lista compartida; y muchos más métodos además.
En todo momento debe saber qué subsistemas necesitan acceso a qué datos y cuándo deben acceder a ellos. Esto afecta su capacidad de paralelizar y optimizar, además de ayudarlo a evitar los problemas más insidiosos cuando diferentes partes de su motor se entrelazan demasiado. Debe estar pensando en minimizar la copia innecesaria de datos y en cómo su diseño de datos afecta su uso de caché. Todo lo cual lo guiará a la mejor solución en cada caso.
Dicho esto, casi todos los juegos en los que he trabajado han tenido un sólido sistema de notificación de eventos / pases de mensajes asíncronos. Le permite escribir código sucinto y eficiente que se pueda mantener, incluso ante necesidades de diseño complejas y que cambian rápidamente.
fuente
Bueno, sé que esta publicación es bastante antigua, pero no pude resistirme.
Recientemente construí un motor de juego. Utiliza bibliotecas de fiestas en 3D para renderizar y física, pero escribí la parte central, que define y procesa las entidades y la lógica del juego.
El motor seguramente sigue un enfoque tradicional. Hay un ciclo de actualización principal que llama a la función de actualización para todas las entidades. Las colisiones se informan directamente por devolución de llamada en las entidades. Las comunicaciones entre entidades se realizan utilizando punteros inteligentes intercambiados entre entidades.
Hay un sistema de mensajes primitivo, que procesa solo un pequeño grupo de entidades para generar mensajes. Es preferible que esos mensajes se procesen al final de una interacción del juego (por ejemplo, la creación o destrucción de una entidad) porque pueden interferir con la lista de actualizaciones. Entonces, al final de cada ciclo del juego, se consume una pequeña lista de mensajes.
A pesar del sistema de mensajes primitivo, diría que el sistema está en gran medida "basado en bucles de actualización".
Bien. Después de usar este sistema, creo que es muy simple, rápido y bien organizado. La lógica del juego es visible y autónoma dentro de las entidades, no dinámica como un mensaje quewe. Realmente no lo haría impulsado por eventos porque, en mi opinión, los sistemas de eventos introducen una complejidad innecesaria en la lógica del juego y hacen que el código del juego sea muy difícil de entender y depurar.
Pero también creo que un sistema puro "basado en bucles de actualización" como el mío también tiene algunos problemas.
Por ejemplo, en algunos momentos, una entidad puede estar en un "estado de no hacer nada", puede estar esperando que el jugador se acerque o algo más. En la mayoría de esos casos, la entidad quema el tiempo del procesador por nada y es mejor apagar la entidad y encenderla cuando ocurre un determinado evento.
Entonces, en mi próximo motor de juego, voy a adoptar un enfoque diferente. Las entidades se registrarán para las operaciones del motor, como actualizaciones, dibujos, detección de colisiones, etc. Cada uno de estos eventos tendrá listas separadas de interfaces de entidad para las entidades reales.
fuente
Si. Es una forma muy eficiente para que los sistemas de juego se comuniquen entre sí. Los eventos lo ayudan a desacoplar muchos sistemas y permiten incluso compilar cosas por separado sin conocer la existencia de los demás. Esto significa que sus clases pueden crear prototipos más fácilmente y los tiempos de compilación son más rápidos. Más importante aún, terminas con un diseño de código plano en lugar de un desastre de dependencia.
Otro gran beneficio de los eventos es que se transmiten fácilmente a través de una red u otro canal de texto. Puede grabarlos para su posterior reproducción. Las posibilidades son infinitas.
Otro beneficio: puede tener varios subsistemas escuchando el mismo evento. Por ejemplo, todas sus vistas remotas (jugadores) pueden suscribirse automáticamente al evento de creación de entidades y generar entidades en cada cliente con poco trabajo de su parte. Imagine cuánto más trabajo sería si no utilizara los eventos: tendría que hacer
Update()
llamadas en algún lugar o tal vez llamarview->CreateEntity
desde la lógica del Juego (donde el conocimiento sobre la vista y la información que requiere no pertenecen). Es difícil resolver ese problema sin eventos.Con los eventos, obtienes una solución elegante y desacoplada que admite un número infinito de objetos de tipos ilimitados que pueden suscribirse a los eventos y hacer lo suyo cuando algo sucede en tu juego. Por eso los eventos son geniales.
Más detalles y una implementación aquí .
fuente
Por lo que he visto, no parece ser muy común tener un motor completamente basado en mensajes. Por supuesto, hay subsistemas que se prestan muy bien a dicho sistema de mensajería, como redes, GUI y posiblemente otros. Sin embargo, en general, hay algunos problemas en los que puedo pensar:
Con el enfoque común de los desarrolladores de juegos de "tiene que ser lo más eficiente posible", este sistema de mensajería no es tan común.
Sin embargo, estoy de acuerdo en que debes seguir adelante y probarlo. Ciertamente, hay muchas ventajas con este sistema y la potencia de cómputo está disponible a bajo precio hoy en día.
fuente