Cambios de estado en entidades o componentes.

9

Tengo algunos problemas para encontrar la manera de tratar con la administración estatal en mis entidades.

No tengo problemas con la administración del estado del juego, como la pausa y los menús, ya que estos no se manejan como un sistema de componentes de la entidad; solo con estado en entidades / componentes.

Dibujando de Orcs Must Die como ejemplo, tengo mis entidades MainCharacter y Trap que solo tienen sus componentes como PositionComponent, RenderComponent, PhysicsComponent.

En cada actualización, la Entidad llamará a la actualización de sus componentes. También tengo un EventManager genérico con escuchas para diferentes tipos de eventos.

Ahora necesito poder colocar las trampas: primero seleccione la trampa y la posición de la trampa, luego coloque la trampa.

Al colocar una trampa, debe aparecer frente al personaje principal, renderizada de una manera diferente y siguiéndola. Cuando se coloca, debe responder a las colisiones y presentarse de la manera normal.

¿Cómo se maneja esto generalmente en sistemas basados ​​en componentes?

(Este ejemplo es específico, pero puede ayudar a descubrir la forma general de tratar con estados de entidades).

GriffinHeart
fuente
1
¿Se pueden agregar y eliminar componentes de entidades basados ​​en eventos de entrada? Quizás pueda cambiar los componentes de la trampa cuando cambian los estados. Por ejemplo, al colocar la trampa tendrá FollowComponent y RenderEffectComponnent. Cuando se coloca, elimina ambos componentes y agrega CollisionComponent. (Editar: Más claramente expresado por Martin Sojka)
Asakeron
Sí, puedo, cada entrada se traduce de un "HumanView" en eventos de juegos, que, la mayoría de ellos, primero son procesados ​​por mi clase GameLogic, que verificará, por ejemplo, si MainCharacter tiene suficiente dinero para colocar una trampa, cómo sucede después de eso es lo que estoy tratando de imaginar.
GriffinHeart

Respuestas:

6

Una aplicación interesante de un sistema de componentes es que puede cambiar los componentes de una entidad en tiempo de ejecución si la diseñó para poder manejarlos. El estado de una entidad se convierte así en la suma de los componentes que se le asignan y los valores que tienen.

Para su ejemplo, primero puede crear la trampa con un BuildControllerComponent(que rige la reacción a los controles del jugador en la fase de construcción), ay PositionComponenta RenderComponent. El último tiene un campo de datos que gobierna los sombreadores de píxeles utilizados, y uno de ellos le da a la trampa-a-ser-construir un aspecto "fantasmal". Notarás que todavía no hay componentes de física asignados.

Al colocar la trampa, los componentes se intercambian. El BuildControllerComponentya no es necesario, por lo que se elimina. Los RenderComponentsombreadores del 's se reemplazan con su vista estándar normal de la trampa. Finalmente, PhysicsComponentademás de lo que sea necesario para que funcione la trampa, se agregan a la entidad.

En un enfoque basado en la herencia, esto es equivalente a tener un constructor para una ActiveTrapEntityclase que toma una BuildTimeTrapEntityclase como argumento, el segundo se usa para representar la trampa durante su construcción, el primero se usa para la trampa después de que esté en su lugar .

Martin Sojka
fuente
Esto es inteligente
Cypher
1
Esta es una buena estrategia para aplicar el estado de una entidad. No aborda el problema de cómo rastrear el estado de cada entidad. ¿Cómo saber en qué estado se encuentra actualmente la entidad?
MichaelHouse
@MartinSojka Esto se acerca a lo que estaba pensando después de hacer la pregunta. Estaba considerando agregar un BuildTrapProcess (algo que se actualiza en GameLogic) que administrará el aspecto de tiempo de ejecución de los componentes cambiantes para lograr los cambios de estado necesarios para construir una trampa. Cuando se presiona el botón para construir una trampa, la lógica del juego creará el Proceso y lo iniciará. alguna idea sobre este enfoque?
GriffinHeart
@ Byte56: en general, puede consultar los componentes asociados y sus valores. En la práctica, a menudo solo necesita conocer el subconjunto relevante de todo el estado, por ejemplo "¿Tiene esta entidad BuildControllerComponent?" o "¿Cuál es la posición de esta entidad como se registra en su PositionComponent, si tiene alguna?" - los que hace al verificar la lista de componentes para los que le interesan y, opcionalmente, consultar (algunos de) sus valores.
Martin Sojka
1
@GriffinHeart: simplemente implementaría lo que sea necesario para "construir" la trampa en el sistema asociado con la administración de BuildControllerComponents. Ya necesita procesar los cambios en el punto de vista del personaje del jugador (o de la cámara) y los eventos de pulsación de tecla y mouse.
Martin Sojka
5

No me gusta la idea de que las entidades soliciten actualizaciones en sus componentes (los sistemas deberían estar haciendo el trabajo), y eso conducirá a problemas para mantener a los componentes inconscientes entre sí.

Puede agregar un componente adicional llamado "Estado". Sus sistemas de renderizado y colisión accederán a él. El componente de estado es solo un indicador que tiene varios estados disponibles. Para la situación que describe, los estados serían Playy Build. Cuando el sistema de renderizado ve que el estado es Build, dibujará el objeto translúcido. Cuando el sistema de colisión ve el Buildestado, no procesará colisiones con el jugador.

Pero realmente, si no tiene sistemas y depende de componentes para hacer todo el trabajo, se encontrará con muchos problemas. Los componentes no deberían conocerse entre sí y no deberían estar procesando.

MichaelHouse
fuente
Lo que estás diciendo es conflictivo, primero deben ignorar (lo que estoy de acuerdo) y luego seguir al tener un componente al que otros acceden. ¿Puedes aclarar? Mantengo componentes desacoplados por el sistema de eventos.
GriffinHeart
Estoy diciendo ambos. Estoy diciendo que no deberían ser conscientes e intentar adaptar mi respuesta a cómo creo que está manejando los componentes. Cuando dice "La entidad llamará a la actualización de sus componentes", me hace creer que no tiene entidades de procesamiento de sistemas. Eliminé el lenguaje confuso y solo hice que dijera sistemas. Estaba diciendo componentes porque entendía que así es como estaban actualizando.
MichaelHouse
Me gusta la idea de una StateComponentque puede ser consumida por múltiples sistemas.
Cypher
1
Es cortés proporcionar razonamiento para votos negativos. Gracias.
MichaelHouse
2
En una nota diferente, su objeción al enfoque del autor de la pregunta se basa en el supuesto de que todo diseño basado en componentes debe actualizar los componentes de sistemas separados (como el diseño de un sistema de entidad). Esa es una forma de hacerlo, pero ciertamente no es la única, y no hay ninguna razón para disuadir este enfoque para un juego que no necesita bucles de actualización de componentes que optimicen la memoria caché.
Sean Middleditch