7
votes

Refactoring: faire un moteur de jeu plus modulaire et comment

Mon moteur de jeu consiste en une gamme de modules couplés lâche, qui peuvent être chargés et déchargés.

Quelques exemples sont les suivants: le module de base, la gestion de la fenêtre de traitement et la réponse aux événements OS, Manager d'entité, Lua Manager, Gestionnaire de physique.

À l'heure actuelle, ces modules sont organisés en espaces de noms et leur état est défini par des variables locales dans les fichiers source respectifs. Chacun des espaces de noms a une fonction ouverte (), ferme () et mise à jour ().

Maintenant, je n'aime pas vraiment la solution avec espaces de noms plus.

  • Ce n'est pas assez flexible

  • Même si cela pourrait ne pas être nécessaire en réalité, la capacité évidente de créer plusieurs instances d'un module semble appropriée

  • Il semble que je ne utilise pas d'OOP ici - une classe de base de module avec une fonction de mise à jour virtuelle () Sonnerait plus raisonnable

  • Il est plus difficile de s'assurer que lorsque le module est fermé et rouvert, toutes les variables seront également réinitialisées (une classe avec constructeurs et destructeurs seraient plus faciles)

  • Vous ne pouvez pas avoir correctement géré les modules sans appeler explicitement ouverte (), fermer () et mettre à jour ()

    Donc, mon idée aurait été d'utiliser des classes pour chacun des modules, dérivé d'une classe de base du module. Les instances de classe de module seraient gérées par la classe Modulemanager, qui les met à jour.

    Mais la solution avec OOP soulève le problème de la manière dont les modules doivent communiquer. En ce moment, le module de base a dit au module de la console d'imprimer quelque chose via console :: print ()

    • Comment puis-je contourner ce problème sans avoir à utiliser quelque chose comme g_modulemanager.geconsolemodule () -> Imprimer () ?

    • Comment ce gestionnaire de module pourrait-il fonctionner en détail?

      et ma dernière question:

      • Avez-vous d'autres conseils pour moi sur le sujet d'écrire un moteur de jeu modulaire en C ++ avec OOP?

      • existe-t-il des modèles de conception qui pourraient m'aider dans cette situation ou peut-être même du matériel de lecture concret?


0 commentaires

3 Réponses :


1
votes

premier comme rappel général, rappelez-vous simplement d'utiliser l'héritage pour la substituabilité, pas la réutilisation du code. Cela signifie à peu près que tout ce qui hérite de votre module de base doit prendre en charge (principalement) les mêmes opérations et que si un utilisateur indique Ouvrir , fermeture ou sur n'importe quel module, il fournira des résultats escomptés.

Voulez-vous vraiment un gestionnaire de module? Il pourrait être préférable de dessiner un diagramme des relations entre vos différentes classes / modules et créer le lien là-bas plutôt qu'un gestionnaire de niveau supérieur. Ensuite, la boucle principale de l'application connaîtrait environ un ou plusieurs modules de niveau élevé et appeler les méthodes appropriées sur eux directement. Si vous le souhaitez, il pourrait même y avoir un module de haut niveau pour gérer ce haut niveau de délégation.

Pour votre exemple de console, en supposant que vous ne souhaitez pas prendre en charge plusieurs consoles, vous êtes probablement mieux que vous devez simplement garder l'espace de noms: il vous permet de désigner directement la console unique que vous interfaçons. Vous pouvez alargiment que vous pourriez avoir besoin d'une "console mère" dans chaque module créé et utilise cette console associée pour effectuer ses E / S le cas échéant. Cela vous donne une plus grande flexibilité au détriment de nécessaire pour vous assurer que vous devez conserver la console dans votre module de base.


1 commentaires

C'est le point: chaque module a déjà la fonctionnalité ouverte, fermeture et mise à jour, et ils font tous fondamentalement la même chose



0
votes
g_ModuleManager.GetConsoleModule()->print()
simple, as stated before me, you are most likely going to have to refactor a lot of things to take advantage of OOP. You want each class to have a distinctive relationship, not all managed on an equal playing field. Whoever is telling the the ConsoleModule to print should have its own print function that tell the ConsoleModule to print. This way you just say print()also think in term of "has a" for composition and "is a" for inheritance.
I would read the entire section 8: http://www.learncpp.com/cpp-tutorial/81-welcome-to-object-oriented-programming/As an example my current project: I have a board that "has" beatles, walls, and apples. Each of those "is an" icon

0 commentaires

2
votes

Les espaces de noms deviennent très inflexibles très rapidement.
Un moyen de garder les choses légèrement couplées est d'utiliser la messagerie via un répartiteur de message central; Plutôt que de dire console :: impression vous diriez que vous diriez messenger-> sendmessage (print_message, boutiques) .
La console s'inscrivait comme un auditeur à print_message s et agissez comme il le souhaite. L'expéditeur n'a pas besoin de se soucier de l'écoute de quelqu'un, et il pourrait même y avoir plusieurs auditeurs à chaque message (utile pour le débogage).

En ce qui concerne les matériaux de lecture, Jason Gregory's "Architecture du moteur de jeu" est plutôt bon, discute des avantages et des inconvénients de plusieurs architectures.


0 commentaires