Quiero hacer una pregunta sobre cómo se debe implementar el intercambio de información entre las partes del motor del juego.
El motor está separado en cuatro partes: lógica, datos, interfaz de usuario, gráficos. Al principio hice este intercambio a través de las banderas. Por ejemplo, si el nuevo objeto se agrega a los datos, la bandera isNew
en la clase de un objeto se establecerá como true
. Y después de eso, la parte de gráficos del motor verificará esta bandera y agregará el objeto al mundo del juego.
Sin embargo, con este enfoque, debía escribir mucho código para procesar cada bandera de cada tipo de objeto.
Pensé en usar algún sistema de eventos, pero no tengo suficiente experiencia para saber si esta sería la solución correcta.
¿Es el sistema de eventos el único enfoque apropiado, o debería usar algo más?
Estoy usando Ogre como motor gráfico, si eso importa.
fuente
Respuestas:
Mi estructura de motor de juego favorita es la interfaz y el modelo de componente de objeto <-> que usa mensajes para la comunicación entre casi todas las partes.
Tiene múltiples interfaces para las partes principales del motor, como su administrador de escena, cargador de recursos, audio, renderizador, física, etc.
Tengo al administrador de escena a cargo de todos los objetos en la escena / mundo 3D.
Object es una clase muy atómica, que contiene solo algunas cosas que son comunes a casi todo en su escena, en mi motor, la clase de objeto tiene solo posición, rotación, una lista de componentes y una ID única. La ID de cada objeto es generada por un int estático, de modo que no habrá dos objetos que tengan la misma ID, esto le permite enviar mensajes a un objeto por su ID, en lugar de tener que tener un puntero al objeto.
La lista de componentes en el objeto es lo que le da a los objetos sus propiedades principales. Por ejemplo, para algo que puede ver en el mundo 3D, le daría a su objeto un componente de representación que contiene la información sobre la malla de representación. Si desea que un objeto tenga física, le daría un componente de física. Si desea que algo actúe como una cámara, dele un componente de cámara. La lista de componentes puede seguir y seguir.
La comunicación entre interfaces, objetos y componentes es clave. En mi motor, tengo una clase de mensaje genérico que contiene solo una ID única y una ID de tipo de mensaje. La identificación única es la identificación del objeto al que desea que vaya el mensaje, y la identificación del tipo de mensaje es utilizada por el objeto que recibe el mensaje para que sepa qué tipo de mensaje es.
Los objetos pueden manejar el mensaje si lo necesitan, y pueden pasar el mensaje a cada uno de sus componentes, y los componentes a menudo harán cosas importantes con el mensaje. Por ejemplo, si desea cambiar la posición del objeto y le envía un mensaje SetPosition, el objeto puede actualizar su variable de posición cuando recibe el mensaje, pero el componente de representación puede necesitar un mensaje para actualizar la posición de la malla de representación, y el componente de física puede necesitar el mensaje para actualizar la posición del cuerpo de física.
Aquí hay un diseño muy simple de administrador de escena, objeto, componente y flujo de mensajes, que preparé en aproximadamente una hora, escrito en C ++. Cuando se ejecuta, establece la posición en un objeto, y el mensaje pasa a través del componente de representación, luego recupera la posición del objeto. ¡Disfrutar!
Además, he escrito una versión de C # y una versión de Scala del código a continuación para cualquier persona que pueda hablar con fluidez en lugar de C ++.
fuente
Creo que es la mejor manera de usar Scene Manager e Interfaces. Tiene implementado el mensaje pero lo usaría como un enfoque secundario. La mensajería es buena para la comunicación entre hilos. Utilice la abstracción (interfaces) siempre que pueda.
No sé mucho sobre Ogre, así que estoy hablando en general.
En esencia, tienes el bucle principal del juego. Obtiene señales de entrada, calcula la IA (desde el movimiento simple hasta la IA compleja y la lógica del juego), carga recursos [, etc.] y representa el estado actual. Este es un ejemplo básico, por lo que puede separar el motor en estas partes (InputManager, AIManager, ResourceManager, RenderManager). Y deberías tener SceneManager que contiene todos los objetos que están presentes en el juego.
Cada una de estas partes y sus subpartes tienen interfaces. Así que trate de organizar estas partes para hacer su trabajo y solo el suyo. Deben usar subpartes que interactúen internamente con el propósito de su parte principal. De esa manera no te enredarás sin posibilidad de desenrollarte sin una reescritura total.
ps si estás usando C ++ considera usar el patrón RAII
fuente