Forma elegante de simular grandes cantidades de entidades dentro de un mundo de juego.

33

Suponga que tiene un juego en el que hay muchas (muchas, muchas) entidades que desempeñan algunas funciones, no todas las cuales son constantemente necesarias o deben considerarse en cada marco. El problema concreto en el que estoy trabajando en el que está presente este problema es una simulación detallada de un cuerpo que incluye sus órganos.

En el juego, cada criatura tiene su propio cuerpo que está separado en partes más pequeñas (torso, piernas, etc.) y, a veces, estas partes contienen órganos, que cumplen una función específica dentro del cuerpo. Si un órgano actualmente cumple o no un propósito o si está activo, nunca está claro. Después de todo, un animal puede tener el estómago vacío, por lo que no necesita digerir nada. Sería bastante ridículo verificar o simular cada objeto en cada cuadro y muy costoso tan pronto como tenga muchas criaturas en el mundo. Así que estaba pensando en una forma de diferenciar inteligentemente entre los objetos que necesitan actualizarse y los que no.

Lo que se me ocurrió parece una solución al menos aceptable. Crea una cola / pila simple (lo esencial es que cada elemento se elimine tan pronto como se lea; el orden es irrelevante) llamado "pila de atención" donde residen los objetos que necesitan ser simulados. Los objetos que necesitan atención simplemente se colocarían en la pila o otros objetos los colocarían allí. Estos objetos probablemente implementarían una interfaz simple con una función simulate ().

Aplicado a mi ejemplo de digestión anterior, esto significaría:

El jugador elige algo para comer (supongamos que es pan) del inventario y lo pone en la boca de su personaje y la boca se coloca en la pila de atención. En el siguiente cuadro, la boca se toma de la pila y se llama a su función simulate (). Como es una boca, sería razonable simular masticar aquí. Esto podría continuar durante unos pocos cuadros en los que la boca sigue poniéndose en la pila hasta que decida que la comida está lista para ser tragada. En este caso, la boca pone el pan masticado en el estómago (sé que no va allí directamente, pero el esófago se deja para simplificar), que luego se coloca en la pila de atención. En el siguiente cuadro se inicia la simulación del proceso de digestión. Y así sucesivamente para el resto de los órganos necesarios.

Un problema previsible con esto son los objetos inactivos. Un animal dormido es un buen ejemplo de esto. Podría hacerse como se describió anteriormente manteniendo al animal dormido en la pila y verificando cada vez si necesita despertarse, pero eso parece un desperdicio ya que eso es lo único que se hace. Para hacer que los objetos inactivos fueran más eficientes, estaba planeando agregar una especie de programación que almacena los trabajos que se realizarán en un momento específico. Si un animal se duerme, colocaría un trabajo en ese horario, que se programaría durante un cierto tiempo después de que el animal se durmiera. Este trabajo se encargaría de poner nuevamente al animal dormido en la pila de atención. Ahora, se podría decir que un animal dormido que no está en la pila de atención podría perder ser atacado por algo porque su IA no es simulada,

Ahora, honestamente, no sé si esto está cerca de una solución elegante a este problema debido a la falta de experiencia. ¿Estoy cerca de algo utilizable? ¿Cómo se hace esto o alguien tiene alguna sugerencia o mejores soluciones?

Marc Müller
fuente

Respuestas:

10

Esta es exactamente la forma en que resolvimos este problema en Stendhal . En nuestro caso, hay muchas cosas que suceden periódicamente, pero no todos los turnos: hechizos de curación, plantas que crecen un poco más, degeneración de cadáveres, objetos en el suelo que caducan.

Tenemos un número de turno que aumenta en cada turno. Y mantenemos un mapa de números de turnos futuros que apuntan a un conjunto de objetos que deben notificarse en ese turno.

Hendrik Brummermann
fuente
¿Qué pasa si algo más interactúa con el objeto mientras tanto? Por ejemplo, el animal dormido puede ser despertado por una piedra que golpea. ¿Deberías eliminar el horario del animal en ese caso?
Emiliano
Eso depende de la situación: si la acción realizada es inofensiva (como despertarse mientras ya está despierto), simplemente dejamos que suceda. Pero si la acción usa algún recurso, buscamos en la cola pendiente y la eliminamos.
Hendrik Brummermann
14

Suena como un problema similar al de las entradas: tiene más de 100 teclas en el teclado pero no desea verificar cada tecla individual en cada cuadro, entonces, ¿qué hace?

Dos respuestas: encuestas o mensajes del sistema.

Sondeo = en cualquier momento en el que realmente importe en el juego, consulta el estado de las teclas del teclado (o de los objetos, en tu caso). El resto del tiempo, ignóralos.

Mensajes = hacer que cada tecla del teclado (objeto) ponga algo en una cola de mensajes cuando se presiona o se suelta (cuando necesita atención). En cada iteración del ciclo del juego, mira a través de la cola y resuelve todos los mensajes antes de continuar.

Ian Schreiber
fuente
10

Así que voy a dar un paso atrás de la implementación y revisar la pregunta desde una perspectiva de diseño. ¿Tiene un plan sólido para mostrar todos los detalles que desea incluir en esta simulación?

Por ejemplo:

  • ¿Puede el jugador notar la diferencia entre un animal con el estómago vacío y un animal con el estómago lleno?
  • ¿Les importa esta información de alguna manera, cuando toman decisiones de interacción dentro de su juego?
  • ¿Podría un jugador que observa al animal predecir constantemente el resultado de sus eventos simulados, o sería suficiente un número aleatorio?

Básicamente, la regla general es no hacer que su simulación sea más complicada que sus resultados. Al final del día, si las únicas animaciones que tienes para las ovejas son pastar, dormir, huir. Entonces realmente no importa cuántos factores intervienen en la decisión sobre qué estado elegir. Todos los jugadores verán ovejas que duermen de noche, corran del peligro y coman durante el día.

La simulación de comportamiento es muy divertida, pero siempre tenga en cuenta la experiencia del usuario final.

Wkerslake
fuente
Sí, el jugador podrá notar la diferencia y hay algunos efectos que esto tiene en el juego, pero en este momento es más un 'truco' para divertirse. Algo así como el sistema de heridas en Dwarf Fortress, que también es muy detallado pero insignificante. Pero como ya mencionaste, es muy divertido trabajar en eso y ese es mi enfoque principal en este momento.
Marc Müller el
9

Tuve un problema similar en un juego en el que trabajé hace unos años: la simulación de objetos era compleja y no podía realizarse en detalle en cada objeto del mundo.

La solución fue utilizar el concepto LOD para la simulación. Los objetos dentro de la vista del jugador ejecutarían la simulación completa. Los objetos muy alejados del jugador ejecutaban una simulación altamente simplificada periódicamente. A medida que los objetos entraban en la vista del jugador, pasarían del curso, la actualización periódica de la simulación a actualizaciones detalladas y regulares.

Skizz
fuente
2

La solución con un horario es buena. Tenga en cuenta que cada entidad debe tener una lista de punteros a sus acciones futuras, lo que da la posibilidad de invalidar acciones futuras si es necesario. Es decir. el animal dormido se despierta instantáneamente cuando es atacado, por lo que debe invalidar su acción de despertar en el futuro.

usuario2047
fuente
1

Hay un patrón de diseño para esto. Creo que se llama objetos de base de datos?

Básicamente, mantienes una oveja "plantilla" que puede representar a todas las ovejas no especiales en el mundo del juego, las dibujas de la misma manera, manteniendo los datos únicos dentro del objeto de la plantilla, por ejemplo, como una tabla de ubicaciones y / o tiempo de ovejas -desde cizalla. Luego, cada vez que necesite hacer que una oveja sea única, puede crear una instancia específica para rastrear esa oveja única.

Lo mismo ocurre con las animaciones. Si se trata de una animación o evento inactivo común a cada instancia, puede residir en la instancia de plantilla, donde se pueden programar animaciones más específicas por separado.

Hace mucho tiempo, escribí un juego para un concurso de programación cuyo ciclo principal acababa de llamarse animate () en toda la escena. Usó punteros de función para reemplazar animaciones inactivas con otras según sea necesario, y utilizó la técnica para admitir animaciones heredadas (por ejemplo, girar un personaje que está parado en un disco giratorio).

Es similar en naturaleza al uso de un delegado para la animación.

davenpcj
fuente
3
Patrón de peso mosca, ¿quieres decir?
vertical
0

¿Funcionaría una máquina de estado? El animal se encuentra, por ejemplo, en estado de sueño, estado de alimentación, estado de ejecución, etc. Para cada estado se asocia una lista de órganos activos. Entonces, cada cuadro que visita a cada animal, enciende el estado, busca la lista de órganos para ese estado y ejecuta la actualización en cada uno de los órganos.

Erik Engheim
fuente
Creo que eso complicaría las cosas porque tiene que ser posible que ocurran múltiples cosas dentro del animal. Por ejemplo, solo porque el estómago está digiriendo algo no significa que el corazón deje de latir o que el animal deje de caminar. Claro, podría definir un conjunto de estados, cada uno de los cuales tiene en cuenta ciertas funciones, pero la cantidad de estados sería increíblemente enorme.
Marc Müller el
Pueden suceder varias cosas por estado, porque almacena todos los órganos activos en un estado y ejecuta cada uno de los cuadros. Sin embargo, mucho de lo que sucede en su simulación parece encajar con las transiciones de estado. Por ejemplo, masticar -> digerir. Pero supongo que tienes razón en que un animal no puede tener un solo estado. Hay transiciones de estado que ocurren, por ejemplo, con las extremidades que no están relacionadas con las transiciones de estado que ocurren en el sistema digestivo. Pero tal vez sea más complicado que lo que tienes. Solo pensé que podría ser algo a considerar.
Erik Engheim el