Gestión de listas de diferentes tipos de entidades: ¿hay una mejor manera?

9

Estoy desarrollando un juego espacial en 2D para dispositivos móviles, pero se vuelve realmente complejo y mi solución es realmente confusa y produce muchos segmentos de código repetidos.

Tengo una clase mundial en la que tengo listas de diferentes objetos como:

List<Enemy> enemys;
List<Projectile> projectiles;
List<Collectable> collectables;
List<Asteroid> asteroids;
List<Effect> effects;
..

Cada lista se actualiza por la clase mundial. pero eso no es todo. Cada enemigo tiene una lista de motores y una lista de buscadores de armas que el enemigo actualiza. Ahora cada motor agrega algunos efectos de fuego a los 'efectos' de la lista mundial, y cada lanzador de armas agrega proyectiles a los 'proyectiles' de la lista mundial. Todas estas clases tienen parámetros diferentes, por lo que necesito una actualización adicional Y una función de renderización adicional para cada clase.

Al menos, todos son elementos secundarios de 'GameObject' que les proporciona elementos básicos como vectores de posición, velocidad y aceleración, polígonos delimitadores y funciones como applyForce y una máquina de estados finitos.

¿Hay una forma mejor o más común de hacer esto? como una clase catch-all que contiene todos los parámetros y métodos posibles para todos los objetos diferentes. (Creo que esto produciría un código aún más confuso)

Nuez
fuente
Esto es similar a mi pregunta: gamedev.stackexchange.com/questions/22559/… Sugiero mirar las respuestas que se le dieron.
Derek

Respuestas:

5

¿Hay una forma mejor o más común de hacer esto? como una clase catch-all que contiene todos los parámetros y métodos posibles para todos los objetos diferentes.

Sí, se llama arquitectura . Echa un vistazo aquí para más detalles.

Esto permitiría solo una lista de entidades en su clase mundial:

List<Entity>

Es un ejemplo de Composición sobre herencia .

Laurent Couvidou
fuente
3

Dentro de los límites de su pregunta original, una opción sería dividir las listas en Acciones en lugar de Tipos como lo que tiene. Por ejemplo, tendría el List<HasAI>y uno para List<Collidable>y cuando cree un nuevo objeto, se agregará a la lista de acciones que necesite, cuando el objeto se destruya, se eliminará de esas listas. Un objeto puede estar en varias listas.

El segundo paso de esa opción es refactorizar sus clases de una jerarquía a una que use interfaces, por lo que su tipo HasAI es una clase que implementa la interfaz IBrains como ejemplo. Coincidencia que List<HasAI>solo requiere que los objetos tengan la interfaz IBrains.

Eso debería ayudar a limpiar parte de la complejidad.

Patrick Hughes
fuente
2

Creo que lo que debe hacer es abstraer la representación en sus propias clases, creo que una para el jugador y otra para el enemigo (o tal vez solo una para el jugador, y luego crear una instancia para el jugador y el enemigo, no 100% seguro) del diseño de tu juego).

Podría usar un patrón de visitante para dejar que el renderizador recorra los diversos objetos y decida qué dibujar, eso podría ser menos complejo.

nycynik
fuente
2

Usar una clase base y confiar en el polimorfismo es una muy buena idea. Pero hay algunos enfoques alternativos. Hay dos artículos de Noel Llopis que vale la pena leer. He estado mirando el diseño orientado a datos últimamente y creo que tiene algún mérito.

Los artículos están aquí y aquí . Puede simplificar su código un poco más que el polimorfismo. Pero como cualquier cosa de YMMV, eche un vistazo y vea si encaja con lo que está tratando de lograr. El polimorfismo usa la herencia y el DOD usa la agregación, ambos tienen ventajas y desventajas, así que elija su veneno.

Britchie
fuente
1

Puede hacerlo utilizando OOP y especialmente el polimorfismo.

Básicamente, debes crear una clase base, de la cual todas las entidades del juego heredan. Esta clase base, es lo más abstracta posible, contendrá cosas como una función de Creación, Actualización y Quizás una Destrucción.

Luego deriva todos los demás objetos del juego de esta clase. Probablemente también necesitará agregar algún tipo de reflexión en su código si su idioma no lo admite, para hacer algunas cosas más avanzadas, pero es evitable si sabe cómo estructurar su herencia correctamente.

Marlock
fuente
1
Él ya hizo esto: todas sus clases son hijos de GameObject. Solo necesita convertir su serie de listas en una sola lista de GameObjects.
SomeGuy