Je fais un petit robot de donjon dans l'espace, et j'aimerais entendre quelques conseils sur la façon de rendre le backend du moteur plus agréable. Fondamentalement, actuellement, tout est basé sur un crapload de gestionnaires:
- BackgroundManager: possède une
AddBackground(image, parallax)
méthode pour créer des effets de fond sympas. - ConfigManager: lit / crée le fichier de configuration et contient également les données lues à partir de ce fichier de configuration.
- DrawManager: a une
Draw(sprite)
méthode pour dessiner des choses à l'écran, et des choses commeSetView(view)
,GetView()
etc. - EntityManager: contient toutes les entités actives et propose des méthodes pour ajouter, supprimer et rechercher des entités.
- DungeonManager ( en fait appelé GridManager, mais cela est pour la simplicité): a des méthodes comme
GenerateDungeon()
,PlaceEnemies()
,PlaceFinish()
etc.
Maintenant, je ne suis même pas à mi-chemin de la liste de tous mes managers, donc je pense que cela doit changer. Mon jeu est également basé sur les écrans, ce qui le rend plus ennuyeux car je n'ai pas besoin de la moitié des choses que mes managers gèrent, par exemple, le menu principal (je n'ai pas besoin de physique / d'entités / de donjons dans mon menu principal !)
Maintenant, j'ai pensé à rendre les gestionnaires non statiques et à donner à mon ScreenMainGame une instance de tous les gestionnaires spécifiques au jeu. Mais cela fait d'appeler / d'obtenir quoi que ce soit lié aux gestionnaires un énorme gâchis ... par exemple, si je voulais tirer mon donjon de n'importe quel endroit qui n'est pas ScreenMainGame.Draw()
, je devrais le faire ...
((ScreenMainGame)ScreenManager.CurrentScreen).GridManager.Draw()
C'est vraiment moche.
Alors, chers développeurs de jeux, l'un de vous a-t-il une idée de comment résoudre ce gâchis? J'apprécierais!
Réponses:
Qu'en est-il d'un moteur basé sur des composants ?
Vous auriez une classe principale nommée
Engine
, qui conserverait une liste deGameScreens
, qui détiendrait elle-même une liste deComponents
.Le moteur a une
Update
et uneDraw
méthode à la fois et les appelsGameScreen
« sUpdate
et desDraw
méthodes qui se passent par chaque composant et appelUpdate
etDraw
.Présenté comme ça, je conviens que cela ressemble à un design pauvre et répétitif. Mais croyez-moi, mon code est devenu beaucoup plus propre en utilisant une approche basée sur les composants qu'avec toutes mes anciennes classes de gestionnaire .
Il est également beaucoup plus simple de conserver un tel code, car vous passez simplement par une grande hiérarchie de classes et vous n'avez pas à parcourir
BackgroundManager
tous les arrière-plans spécifiques. Vous avez juste unScrollingBackground
,ParallaxBackground
,StaticBackground
, etc. , qui tous proviennent d'uneBackground
classe.Vous finirez par créer un moteur assez solide que vous pouvez réutiliser sur tous vos projets avec de nombreux composants et méthodes d'assistance fréquemment utilisés (par exemple, un
FrameRateDisplayer
utilitaire de débogage, uneSprite
classe comme sprite de base avec une texture et des méthodes d'extension pour les vecteurs). et génération de nombres aléatoires).Vous n'auriez plus de
BackgroundManager
classe, mais uneBackground
classe qui se gérerait à la place.Lorsque votre jeu démarre, tout ce que vous avez à faire est essentiellement:
Et c'est tout pour votre code de démarrage de jeu.
Ensuite, pour l'écran du menu principal:
Vous avez l'idée générale.
Vous conserveriez également la référence de la
Engine
au sein de toutes vosGameScreen
classes, pour pouvoir ajouter de nouveaux écrans même au sein d'uneGameScreen
classe (par exemple, lorsque l'utilisateur clique sur le bouton StartGame dans votreMainMenuScreen
, vous pouvez passer auGameplayScreen
).Il en va de même pour la
Component
classe: elle doit contenir la référence de son parentGameScreen
, pour avoir à la fois accès à laEngine
classe et à son parentGameScreen
pour ajouter de nouveaux composants (par exemple, vous pouvez créer une classe liée au HUD appeléeDrawableButton
qui contient unDrawableText
composant et unStaticBackground
composant).Vous pouvez même appliquer d'autres modèles de conception après cela, comme le "modèle de conception de service" (pas sûr du nom exact) où vous pouvez conserver différents services utiles dans votre
Engine
classe (vous gardez simplement une liste deIService
s et laissez les autres classes ajouter des services elles-mêmes ). Par exemple, je garderais unCamera2D
composant sur tout mon projet en tant que service pour appliquer sa transformation lors du dessin d'autres composants. Cela évite d'avoir à le passer partout en paramètre.En conclusion, il peut certainement y avoir d'autres meilleures conceptions pour un moteur, mais j'ai trouvé le moteur proposé par ce lien très élégant, extrêmement facile à entretenir et réutilisable. Je recommanderais personnellement au moins de l'essayer.
la source
GameComponent
s et de services. Pas besoin d'uneEngine
classe séparée .Ce que vous voulez faire, c'est séparer votre code en composants et services. XNA a déjà un support intégré pour ces derniers.
Voir cet article sur
GameComponents
et services. Consultez ensuite cette réponse sur l'utilisation des services dans XNA, et cette réponse plus générale sur les services dans n'importe quelle langue.la source
Ce n'est pas parce qu'ils sont statiques ou globaux qu'ils doivent toujours être chargés / initialisés. Utilisez un modèle Singleton et permettez aux gestionnaires d'être libérables et chargés à nouveau sur demande.
la source