Esta es una pregunta de diseño ... Estoy seguro de que esto podría generalizarse más, pero me está costando mucho. Me pregunto sobre el diseño para las interacciones de objetos del juego: aquí está mi ejemplo (rompecabezas 2D-plataforma).
Digamos que el jugador está intentando progresar a través de un nivel. Hay muchas luces que pueden apuntar en diferentes direcciones. Aquí hay un ejemplo de cómo estos objetos ligeros podrían interactuar ...
- One light proyecta una plataforma que permite al jugador cruzar una brecha
- Una luz disminuye los coeficientes de fricción de todo lo que toca, otra la aumenta.
- Una luz anula los efectos de todas las luces, lo que haría que la plataforma desapareciera mientras la luz está encendida y anulara los modificadores de fricción.
- Etc ...
¿Cuál es la mejor manera de abordar este problema cuando se utiliza una arquitectura de componentes? Los componentes para cada objeto principal parecen obvios, así como una forma limpia de definir sus efectos en el medio ambiente. ¿Una clase para "resolver" la interacción (parece que eso podría convertirse en un desastre rápidamente)? ¿Algún uso del patrón decorador para crear objetos combinados para aquellos que están interactuando en un momento dado? ¿Una estructura de datos que se presta a esto?
Además, ¿conectar audio a estas interacciones? Parece que conectar audio al sistema sería como conectar cualquier otra propiedad, como la visibilidad o el movimiento / colisión del jugador.
Obviamente, a medida que se agreguen más componentes, sería bueno si hubiera un sistema robusto que pudiera manejar otros nuevos con poca modificación, pero no estoy familiarizado con cómo diseñarlo.
Otra información: El motor que estoy usando es un motor XNA llamado IceCream .
fuente
Respuestas:
En un sistema orientado a objetos, la única respuesta real a la pregunta de cuál es la mejor manera de hacer X es que debe hacerlo de la manera más directa que pueda pensar para poner en marcha algo y luego cambiarlo cuando se hace más fácil la expresión. Preocuparse por elegir el patrón correcto antes de escribir cualquier código es una buena manera de cargar con la respuesta incorrecta desde el principio; deje que todos los pensamientos sobre patrones y componentes se desvanezcan y solo siga estos pasos, comenzando desde donde se encuentra hoy (suponiendo que haya implementado un componente ligero):
En este punto, (probablemente) tendrá un montón de código duplicado. Extraiga código común en funciones u otra clase (tal vez una clase base) o lo que parezca apropiado. Sin embargo, el hecho de que haya comenzado con un "componente ligero" no significa que LightComponent sea una base adecuada; podría ser que cualquier código que componga el componente ligero no sea realmente un "componente" per se y tal vez eso esté mejor representado por un conjunto de funciones o incluso una clase separada que se agregue a sus nuevos componentes (como una variable miembro )
fuente
En términos generales, cuando un objeto de tipo A interactúa con un objeto de tipo B, desea tener algún efecto C. Esto se llama "despacho doble" y es muy difícil de hacer de manera elegante en lenguajes tipo C.
La forma efectiva pero difícil de mantener es solo un montón de instrucciones de cambio y if, dependiendo de los tipos de sus objetos. Te sentirás sucio al escribirlo, pero hará el trabajo.
El patrón de visitante es una solución más robusta que oculta el cambio de tipo desagradable, pero puede ser complicado de configurar.
Normalmente, cualquier tipo de cambio de tipo en su código es un olor, pero aquí está tratando de generalizar el polimorfismo, que normalmente cambia las funciones basadas en un solo tipo, para cambiar las funciones basadas en dos tipos. El polimorfismo es una base de OOP, por lo que no es un olor.
fuente
Déjame ver. Esto es algo que cociné en mi cabeza mientras escribía, lo siento si me falta algo.
Obtenga todos los nodos de luz a una distancia razonable alrededor de su amigo.
Para cada luz, representa un polígono que representa su área de efecto a un objeto framebuffer. Entonces, un cono de luz crearía un cono de un tipo de píxeles en su FBO. Haga que cada tipo de nodo pase en prioridad apropiada Podrías codificar información en cada píxel como si el canal verde pudiera ser fricción, el rojo sería la gravedad, el azul y el alfa serían otra cosa.
Las técnicas inteligentes de mezcla de colores podrían crear efectos interesantes. Cada nivel podría tener sus propias reglas de mezcla. También puede agregar sombreado de fragmentos para efectos dinámicos psicodélicos como la gravedad pulsante, etc.
Por último, solo verifique qué píxeles está tocando su mandude y vuelva a calcular el mapa de bits cada vez que se acerque a los bordes del área precalculada.
Scetch áspero hecho en 2 minutos para ilustrar mi idea:
Editar: en la práctica, esto significa que lo único que necesita es un componente de luz que emita un determinado color. Las reglas conectadas a qué color hace lo que puede estar en otro lugar por completo. Puede codificar una gran cantidad de datos en los 32 bits que tiene por píxel. Alternativamente, puede tener múltiples FBO que contienen diferentes atributos que no se afectan entre sí. Podría tener un FBO de gravedad / fricción y un FBO de colisión de 1 bit. Si elige esto, por supuesto, tendrá que marcar en qué FBO debe representar su luz.
fuente
Patrón de observador es una de las mejores soluciones. El mensaje se enviará solo a aquellos objetos (componentes) que realmente estén interesados en él. Por lo tanto, el receptor debe suscribirse en este tipo de mensaje / evento.
Hay muchas implementaciones de señal / ranura. Por ejemplo, en C ++ hay una biblioteca sigslot
Para obtener más información, lea acerca de las señales Qt y las ranuras .
fuente