Le codage n'est pas si difficile en fait . La partie difficile est d'écrire du code qui a du sens, qui est lisible et compréhensible. Je veux donc obtenir un meilleur développeur et créer une architecture solide.
Je veux donc créer une architecture pour les PNJ dans un jeu vidéo. Il s'agit d'un jeu de stratégie en temps réel comme Starcraft, Age of Empires, Command & Conquers, etc. etc. J'aurai donc différents types de PNJ. Un PNJ peut avoir un à plusieurs capacités (méthodes) de celles - ci: Build()
, Farm()
etAttack()
.
Exemples:
travailleur peut Build()
et Farm()
guerrier peut Attack()
citoyen peut Build()
, Farm()
et Attack()
pêcheur peut Farm()
etAttack()
J'espère que tout est clair jusqu'à présent.
Alors maintenant, j'ai mes types de PNJ et leurs capacités. Mais revenons à l'aspect technique / programmatique.
Quelle serait une bonne architecture programmatique pour mes différents types de PNJ?
D'accord, je pourrais avoir une classe de base. En fait, je pense que c'est une bonne façon de s'en tenir au principe DRY . Je peux donc avoir des méthodes comme WalkTo(x,y)
dans ma classe de base car chaque PNJ pourra se déplacer. Mais maintenant, venons-en au vrai problème. Où dois-je mettre en œuvre mes capacités? (rappelez - vous: Build()
, Farm()
et Attack()
)
Puisque les capacités seront constituées de la même logique, il serait ennuyeux / de casser le principe SEC pour les implémenter pour chaque PNJ (Ouvrier, Guerrier, ..).
D'accord, je pourrais implémenter les capacités au sein de la classe de base. Cela nécessiterait une sorte de logique qui vérifie si un PNJ peut utiliser X. capacité IsBuilder
, CanBuild
.. Je pense qu'il est clair ce que je veux exprimer.
Mais je ne me sens pas très bien avec cette idée. Cela ressemble à une classe de base gonflée avec trop de fonctionnalités.
J'utilise C # comme langage de programmation. L'héritage multiple n'est donc pas une option ici. Moyens: Avoir des classes de base supplémentaires comme Fisherman : Farmer, Attacker
ne fonctionnera pas.
la source
Réponses:
La composition et l'héritage d'interface sont les alternatives habituelles à l'héritage multiple classique.
Tout ce que vous avez décrit ci-dessus et commençant par le mot «peut» est une capacité qui peut être représentée par une interface, comme dans
ICanBuild
ouICanFarm
. Vous pouvez hériter d'autant de ces interfaces que vous pensez en avoir besoin.Vous pouvez passer des objets de construction et d'agriculture "génériques" via le constructeur de votre classe. C'est là que la composition entre en jeu.
la source
ICanBuild
. Le fait que vous disposiez également d'outils pour la construction est une préoccupation secondaire dans la hiérarchie des objets.Comme d'autres affiches l'ont mentionné, une architecture de composants pourrait être la solution à ce problème.
Dans ce cas, étendez la fonction de mise à jour pour implémenter toutes les fonctionnalités que le NPC devrait avoir.
L'itération d'un conteneur de composants et la mise à jour de chaque composant permettent d'appliquer la fonctionnalité spécifique de chaque composant.
Comme chaque type d'objet est souhaité, vous pouvez utiliser une forme de modèle d'usine pour construire les types individuels que vous souhaitez.
J'ai toujours rencontré des problèmes car les composants deviennent de plus en plus complexes. Garder la complexité des composants faible (une responsabilité) peut aider à atténuer ce problème.
la source
Si vous définissez des interfaces comme celles-ci,
ICanBuild
votre système de jeu doit inspecter chaque PNJ par type, ce qui est généralement mal vu dans la POO. Par exemple:if (npc is ICanBuild)
.Vous êtes mieux avec:
Ensuite:
... ou bien sûr, vous pouvez utiliser un certain nombre d'architectures différentes, comme une sorte de langage spécifique au domaine sous la forme d'une interface fluide pour définir différents types de NPC, etc., où vous construisez des types de NPC en combinant différents comportements:
Le constructeur de PNJ pourrait implémenter un
DefaultWalkBehavior
qui pourrait être annulé dans le cas d'un PNJ qui vole mais ne peut pas marcher, etc.la source
if(npc is ICanBuild)
etif(npc.CanBuild)
. Même quand je préférerais lanpc.CanBuild
voie à mon attitude actuelle.Je mettrais toutes les capacités dans des classes distinctes qui héritent de la capacité. Ensuite, dans la classe de type d'unité, ayez une liste de capacités et d'autres choses comme l'attaque, la défense, la santé maximale, etc.
Définissez tous les types d'unités dans un fichier de configuration ou une base de données, plutôt que de le coder en dur.
Ensuite, le concepteur de niveaux peut facilement ajuster les capacités et les statistiques des types d'unités sans recompiler le jeu, et les gens peuvent également écrire des mods pour le jeu.
la source