Espacios Contenedores de objetos de juego útiles

El punto entero de un espacio Es mantener objetos del juego. Los objetos del juego en un espacio no deberían tener alguna Es la forma de comunicarse con los objetos del juego en otro espacio, por lo que los espacios proporcionan un medio simple para separar diferentes grupos de objetos del juego. En este artículo, aprenderá los beneficios de tal arquitectura..

Si desea ver un ejemplo de la implementación de espacios, consulte el motor de juegos de código abierto SEL. Yo mismo soy autor activo de SEL y estoy orgulloso de presentarlo como un recurso completamente funcional para los lectores de este artículo.

Me gustaría agradecer a Sean Middleditch por enseñarme acerca de los beneficios de Spaces.

Propina: El termino espacio en el contexto de este artículo se refiere a un contenedor especial de objetos del juego. En realidad no soy consciente de un término oficial claramente definido. Si conoces alguna, por favor haz un comentario.!


Gestión de objetos convencionales

En un motor de juego convencional, los objetos del juego generalmente se almacenan en un solo contenedor. Dicho contenedor puede ser un asignador junto con un administrador de identificador. A veces el contenedor es solo una lista enlazada. No importa cuál sea la implementación real, puede haber un solo contenedor que contenga todos los objetos del juego, y cada objeto del juego creado siempre está en este contenedor.

Esto está bien y funciona totalmente, pero tiene algunos problemas de organización. Por ejemplo, imagina un juego tradicional de estado gerente. A menudo, entre la transición de un estado a otro, todos los objetos del juego cargados actualmente se liberan y los nuevos se leen desde el disco. Como optimización, los objetos del juego para el siguiente estado (o nivel) se pueden cargar en un hilo separado de antemano para que las transiciones de estado sean instantáneas.

Sin embargo, hay un problema molesto que surge comúnmente: ¿cómo representamos los elementos de la GUI para los menús? Quizás el jugador HUD está codificado utilizando objetos del juego y guiones adjuntos a estos objetos del juego. Una implementación ingenua de la administración estatal requeriría que todos los elementos de HUD se destruyeran y se recrearan en la transición de estado. Esto significa que se requerirá un código personalizado para manejar la transición de objetos particulares de un estado a otro.

O tal vez el diseño de un juego requiera paisajes de fondo alocados donde se libra una gran batalla, pero esta batalla no debe interferir con el primer plano (o el jugador) de ninguna manera..

A menudo, surgen soluciones extrañas para este tipo de cosas, como representar a los elementos de HUD como extremadamente lejos del resto del juego en el mundo. Los menús de pausa y similares simplemente se mueven a la vista cuando es necesario, y se alejan de otra manera. En general, se requiere un código personalizado para administrar y organizar los objetos del juego, ya que todos residen en una sola fábrica o contenedor..


Contenedores de objetos de juego múltiple

Una solución aceptable para este problema sería hacer uso de espacios (consulte la descripción del video adicional de mi colega Sean Middleditch). Dado que todos los objetos del juego en cada espacio tienen una interacción cero, los espacios se convierten en una forma natural de abordar la organización de los objetos del juego. Esto puede minimizar en gran medida la necesidad de un código especial para mantener un contenedor lógico separado dentro de un contenedor real (como se mencionó en la sección anterior).

Echemos un vistazo rápido a un ejemplo de cómo se vería una implementación de espacio en un lenguaje similar a C ++:

 class Space public: GameObject CreateObject (nombre de cadena); const cadena GetName (void) const; privado: cadena m_name; // Podría ser algún tipo de asignador, tal vez solo un std :: vector Container m_objects; ;

A menudo es útil poder buscar un espacio por nombre. Esto es especialmente bueno para los scripts donde un script puede utilizar código así:

 // Ejecute alguna lógica para el espacio local de fondo = GetSpace ("Fondo") tornado = espacio.CreateObject ("Tornado") // En otro lugar podemos hacer algo completamente aislado del fondo, // como recuperar al jugador (que para algunos la razón murió) y reproducir una // animación de muerte sobre el espacio local del jugador = GetSpace ("CurrentLevel") player = space.GetPlayer () space.CreateObjectAt ("DeathAnimation", jugador)
Diagrama que muestra la organización simple de los objetos del juego en contenedores aislados. No todos los espacios tienen la misma cantidad de objetos de juego, ni siquiera los mismos objetos de juego.

Qué objetos entran en los espacios?

La respuesta a esta pregunta es: ¡todos ellos! Cualquier tipo de objeto de juego será colocado en un espacio. Si está familiarizado con la agregación (o el diseño basado en componentes), un objeto de juego y sus componentes asociados residirán en el mismo espacio.

La idea es crear una característica arquitectónica que permita una forma simple y efectiva de agrupar objetos del juego y aislarlos de otros grupos..

Terminología

Los espacios son bastante similares a algunos otros conceptos que han estado flotando por un tiempo. Se ha dicho que los espacios son similares a la lista de visualización en Flash. Si está familiarizado con los portales para la selección de procesadores (especialmente importante en juegos 3D con muchas salas interiores), la idea es bastante similar aquí también..

Sin embargo, hay una distinción importante para hacer aquí. Los espacios son no una forma de partición espacial como se hace con los portales u otra partición espacial (como el popular árbol BSP) para la oclusión de render. Los espacios son un arquitectónico Característica para permitir el aislamiento de objetos generales del juego..

Personalmente, me gusta pensar en espacios como las capas de Photoshop: todas las capas se pueden ver (o escuchar) simultáneamente, pero cuando se pinta en una capa, ninguna otra capa se ve afectada directamente; Cada capa es única y aislada..

Sistemas y espacios

El concepto de un sistema, a los efectos de este artículo, se puede describir como un conjunto de funcionalidades (funciones o métodos) que opera sobre los objetos del juego de un espacio. De esta manera, se entrega un espacio a un sistema para realizar alguna acción; Un sistema en particular es global para todo el juego..

Diagrama que ejemplifica la simplicidad de permitir que un sistema opere en un espacio como entrada.

Imagina un sistema gráfico que contiene un void Graphics :: DrawWorld (Space Space) función. Esta DrawWorld La función giraría sobre los objetos dentro del espacio dado que se pueden representar y los dibujará en la pantalla..

La idea es ahora escribir código (sistemas) que funcione con una entrada determinada de objetos del juego. Ningún seguimiento especial o gestión de objetos de juego tiene que ocurrir dentro de tales sistemas. Un sistema no debería hacer nada excepto realizar operaciones en objetos del juego..

Este estilo le brinda algunos beneficios realmente agradables, como se detalla en la siguiente sección.


Beneficios de los espacios

El beneficio más inmediato de implementar espacios dentro de un motor es que el manejo de los elementos o menús de la GUI se torna trivial. Podemos construir un espacio dedicado a un menú en particular y, cuando este menú está inactivo, los sistemas simplemente no necesitan operar sobre el contenido del espacio. Cuando un menú está inactivo, se coloca en la memoria (los objetos del juego que conforman la memoria se encuentran dentro del espacio del menú) y no hace nada; no es actualizado por un sistema lógico ni es renderizado por un sistema de gráficos.

Cuando este menú vuelve a estar activo, puede ser simplemente entregado a los sistemas apropiados. El menú se puede actualizar y representar adecuadamente. Al mismo tiempo, el juego que se está ejecutando detrás del menú puede dejar de actualizarse de cualquier manera, aunque quizás aún se haya pasado al sistema de gráficos para ser renderizado. Esto implementa de forma trivial un elegante y robusto tipo de funcionalidad de pausa y reanudación que viene implícitamente debido a la forma en que se definen los espacios..

Niveles aislados

A menudo, en juegos estilo RPG como Pokémon, el jugador entrará y saldrá de casas y chozas. En lo que respecta a la jugabilidad, estas casas diferentes suelen estar completamente aisladas; Pequeñas casas o cuevas son un escenario ideal para aplicar espacios. Se puede construir un espacio completo para contener los objetos del juego de una casa particular, y estos pueden cargarse e inicializarse en la memoria y descansar hasta que sea necesario. Las transiciones instantáneas se pueden lograr simplemente cambiando el espacio que se entrega a los distintos sistemas de motores.

Una buena idea para juegos en 2D como los juegos de plataformas (o incluso juegos en 3D) podría ser simular niveles reales y enemigos del juego en segundo plano. Esto podría dar vida al mundo de una manera que en realidad no requiere ningún contenido adicional, y casi ningún tiempo de desarrollo adicional. El mejor ejemplo que pude encontrar de esto es Rayman Legends:


Los enemigos reales, al igual que el jugador ve normalmente, podrían estar saltando o arrastrándose en las paredes en la distancia. Las transiciones entre estas diferentes "capas" podrían proporcionar algunas posibilidades de diseño muy interesantes.

Este tipo de posibilidades son bastante raras para encontrar ejemplos y la idea de espacios no está realmente aceptada por los modernos estudios o motores AAA. Sin embargo, el diseño es sólido y los beneficios son reales..

Multijugador local

En muchos juegos con soporte multijugador donde ambos jugadores juegan con el mismo cliente de juego, existen algunas limitaciones. A menudo los jugadores no pueden ir a un área nueva sin que ambos estén cerca uno del otro. A veces los jugadores ni siquiera pueden salir de la pantalla del otro. Esto podría deberse al diseño del juego, pero tengo la sospecha de que a menudo se debe a limitaciones arquitectónicas.

Con espacios, podemos admitir a dos jugadores, quizás con pantallas divididas, que viajan de un nivel a otro. Cada jugador puede residir en el mismo espacio, o en dos espacios separados. Cuando cada jugador está en un edificio diferente, ambos pueden estar en dos espacios separados. Una vez que convergen en la misma área, el motor puede transferir uno de los objetos del juego del jugador al espacio opuesto..

Soporte del editor

Este es definitivamente mi ejemplo favorito de cómo los espacios son impresionantes. En los editores a menudo hay secciones donde puede desarrollar un nuevo tipo de objeto. Este objeto en la creación usualmente tendrá una ventana para obtener una vista previa de la creación a medida que el desarrollo zumba.

Puede ser imposible para la mayoría de los motores admitir naturalmente un editor de este tipo. ¿Qué pasa si el usuario modifica la posición y de repente choca con la simulación y golpea las cosas, o activa alguna IA? Se debe crear un código personalizado para manejar con gracia el objeto en la memoria de alguna manera. El código de aislamiento de casos especiales, o algún formato intermedio, debe ser editado y traducido desde el editor a la simulación real. Los pasos intermedios pueden ser alguna forma de serialización o un "objeto proxy" ficticio no intrusivo complejo. Los objetos proxy a menudo pueden requerir la introspección avanzada de código para implementarse de una manera útil. Estas opciones pueden ser caras o innecesarias para muchos proyectos..

Sin embargo, si uno tiene espacios a su disposición, un objeto de cámara y el objeto en creación se pueden colocar en un espacio aislado. Este espacio puede ser entregado a cualquier sistema necesario y manejado de manera elegante. No sería necesario ningún código de caso especial o creación adicional en tal escenario.

Se pueden mantener múltiples niveles dentro de los editores con facilidad. Múltiples vistas y simulaciones se pueden ejecutar de forma simultánea de forma aislada. ¿Qué pasaría si un desarrollador quisiera dividir la pantalla del desarrollo de dos niveles para cambiar de un lado a otro rápidamente? Esto podría ser una tarea de ingeniería de software difícil, o la arquitectura del editor podría implementar algún tipo de espacio.


Ideas de implementación

Administracion del espacio

¿Qué gestiona todos los espacios? Muchos desarrolladores de juegos pueden tener en su práctica que todo debe poder ser "propiedad" de algún administrador. Todos los espacios deben poder ser gestionados por esta entidad única, ¿verdad? En realidad, este tipo de paradigma no es necesario. todo el tiempo.

En el motor SEL, los espacios se construyen desde una ubicación y se pueden buscar por nombre con un diccionario, pero puede ser mejor para la mayoría de los proyectos dejar que los espacios se administren caso por caso. A menudo, solo tiene sentido crear un espacio dentro de un script aleatorio, mantenerlo durante un tiempo y luego liberar el espacio. Otras veces se crea un espacio y se guarda en la memoria toda la duración del tiempo de ejecución del juego.

Una buena recomendación sería dejar que el usuario asigne un espacio y lo libere a voluntad. Probablemente sería bueno usar un solo asignador para este comportamiento. Sin embargo, la administración de la instancia espacial en sí misma, como se encuentra a través de la experiencia, podría ser mejor no preocuparse; dejalo al usuario.

Nota: Cuando se destruye un espacio, ¡se deben limpiar todos los objetos dentro! No confunda la falta de un gerente con una falta de gestión de por vida.

Componentes y subespacios

Los componentes a menudo se registran con sus respectivos sistemas en un motor basado en componentes. Sin embargo, con espacios esto se vuelve innecesario. En su lugar, cada espacio debe contener lo que se llama un subespacio. Un subespacio puede ser muy trivial para implementar, por ejemplo, como un vector de objetos componentes. La idea es simplemente contener varios tipos de contenedores de componentes dentro de cada espacio. Cada vez que se construye un componente, solicita el espacio con el que se va a asociar y se registra en el subespacio..

Un espacio no necesariamente tiene que tener cada tipo de subespacio dentro de sí mismo. Por ejemplo, un espacio de menú probablemente no necesitará ninguna simulación física y, por lo tanto, puede que no tenga una instancia completa de un mundo físico que represente un subespacio físico..

Por último, debe tenerse en cuenta que en una arquitectura basada en componentes, los objetos del juego deben tener un controlador o un puntero al espacio en el que residen. De esta manera, el espacio se convierte en parte del identificador único del objeto del juego en sí..


Conclusión

Los espacios son extremadamente simples de implementar y proporcionan muchos beneficios importantes. Para casi todos los juegos y motores de juegos existentes, la adición de espacios será positiva debido a la facilidad de implementación. Usa espacios, incluso para proyectos muy pequeños y juegos muy pequeños.!

Como recurso, mi propia implementación de espacios es de código abierto para visualización pública dentro del motor de juego SEL.