Estoy haciendo un pequeño rastreador de mazmorras en el espacio, y me gustaría escuchar algunos consejos sobre cómo hacer que el motor del motor sea más agradable. Básicamente, actualmente todo se basa en una gran cantidad de gerentes:
- BackgroundManager: tiene un
AddBackground(image, parallax)método para crear efectos de fondo geniales. - ConfigManager: lee / crea el archivo de configuración y también contiene los datos leídos de ese archivo de configuración.
- DrawManager: tiene un
Draw(sprite)método para dibujar cosas en la pantalla y cosas comoSetView(view),GetView()etc. - EntityManager: contiene todas las entidades activas y tiene métodos para agregar, eliminar y encontrar entidades.
- DungeonManager (en realidad se llama un GridManager, pero esto es por simplicidad): tiene métodos como
GenerateDungeon(),PlaceEnemies(),PlaceFinish()etc.
Ahora ni siquiera estoy a la mitad de la lista de todos mis gerentes, así que creo que esto tiene que cambiar. Mi juego también se basa en pantallas, lo que lo hace más molesto porque no necesito la mitad de las cosas que mis gerentes están administrando, por ejemplo, el menú principal (no necesito física / entidades / mazmorras en mi menú principal) !)
Ahora pensé en hacer que los gerentes no sean estáticos, y darle a ScreenMainGame una instancia de todos los gerentes específicos del juego. Pero eso hace que llamar / hacer algo relacionado con los gerentes sea un gran desastre ... por ejemplo, si quisiera sacar mi mazmorra de cualquier lugar que no esté ScreenMainGame.Draw(), tendría que hacer esto ...
((ScreenMainGame)ScreenManager.CurrentScreen).GridManager.Draw()
Eso es realmente feo.
Entonces, compañeros desarrolladores de juegos, ¿alguno de ustedes tiene una idea de cómo resolver este desastre? Se lo agradeceria!
fuente

Respuestas:
¿Qué pasa con un motor basado en componentes ?
Tendría una clase principal llamada
Engine, que mantendría una lista deGameScreens, que ellos mismos tendrían una lista deComponents.El motor tiene un
Updatey unDrawmétodo y ambos llaman losGameScreen'sUpdatey losDrawmétodos, que pasan por cada componente y llamanUpdateyDraw.Presentado así, estoy de acuerdo en que suena como un diseño pobre y repetitivo. Pero créanme, mi código se volvió mucho más limpio mediante el uso de un enfoque basado en componentes que con todas mis antiguas clases de administrador .
También es mucho más simple mantener dicho código, ya que solo está pasando por una gran jerarquía de clases y no tiene que buscar
BackgroundManagertodos los diferentes fondos específicos. Sólo tienes unaScrollingBackground,ParallaxBackground,StaticBackground, etc, todos ellos derivados de unaBackgroundclase.Eventualmente construirá un motor bastante sólido que puede reutilizar en todos sus proyectos con muchos componentes y métodos auxiliares de uso frecuente (por ejemplo,
FrameRateDisplayercomo una utilidad de depuración, unaSpriteclase como sprite básico con una textura y métodos de extensión para vectores y generación de números aleatorios).Ya no tendrías una
BackgroundManagerclase, sino unaBackgroundclase que se administraría sola.Cuando comienza tu juego, todo lo que tienes que hacer es básicamente esto:
Y eso es todo para el código de inicio del juego.
Luego, para la pantalla del menú principal:
Tienes la idea general.
También mantendría la referencia de
Enginedentro de todas susGameScreenclases, para poder agregar nuevas pantallas incluso dentro de unaGameScreenclase (por ejemplo, cuando el usuario hace clic en el botón StartGame mientras está dentro de suMainMenuScreen, puede hacer la transición aGameplayScreen).Lo mismo ocurre con la
Componentclase: debe contener la referencia de su padreGameScreen, para tener acceso tanto a laEngineclase como a su padreGameScreenpara agregar nuevos componentes (por ejemplo, puede hacer una clase relacionada con HUD llamadaDrawableButtonque contiene unDrawableTextcomponente y unStaticBackgroundcomponente).Incluso puede aplicar otros patrones de diseño después de eso, como el "patrón de diseño de servicios" (no estoy seguro sobre el nombre exacto) donde puede mantener diferentes servicios útiles dentro de su
Engineclase (simplemente mantiene una lista deIServicesy permite que otras clases agreguen servicios ellos mismos) ) Por ejemplo, mantendría unCamera2Dcomponente en todo mi proyecto como un servicio para aplicar su transformación al dibujar otros componentes. Esto evita tener que pasarlo como parámetro en todas partes.En conclusión, ciertamente puede haber otros mejores diseños para un motor, pero el motor propuesto por este enlace me pareció muy elegante, extremadamente fácil de mantener y reutilizar. Yo personalmente recomendaría al menos intentarlo.
fuente
GameComponentservicios y servicios. No hay necesidad de unaEngineclase separada .Lo que desea hacer es separar su código en componentes y servicios. XNA ya tiene soporte incorporado para estos.
Vea este artículo sobre
GameComponentsy servicios. Luego vea esta respuesta sobre el uso de servicios en XNA, y esta respuesta más general sobre servicios en cualquier idioma.fuente
El hecho de que sean estáticos o globales no significa que siempre tengan que cargarse / inicializarse. Use un patrón Singleton y permita que los gerentes puedan liberarse y cargarse nuevamente bajo demanda.
fuente