Je commence tout juste à me familiariser avec la conception basée sur les composants. Je ne sais pas quelle est la "bonne" façon de procéder.
Voici le scénario. Le joueur peut équiper un bouclier. Le bouclier est dessiné comme une bulle autour du joueur, il a une forme de collision séparée et réduit les dégâts que le joueur reçoit des effets de zone.
Comment un tel bouclier est-il conçu dans un jeu basé sur des composants?
Là où je suis confus, c'est que le bouclier a évidemment trois composants associés.
- Réduction / filtrage des dommages
- Un sprite
- Un collisionneur.
Pour l'aggraver, différentes variations de bouclier pourraient avoir encore plus de comportements, qui pourraient tous être des composants:
- augmenter la santé maximale du joueur
- régénération de la santé
- déviation du projectile
- etc
Suis-je trop réfléchir à cela? Le bouclier ne devrait-il être qu'un super composant?
Je pense vraiment que c'est une mauvaise réponse. Donc, si vous pensez que c'est la voie à suivre, veuillez expliquer.Le bouclier doit-il être sa propre entité qui suit l'emplacement du joueur?
Cela pourrait rendre difficile la mise en œuvre du filtrage des dommages. Cela brouille également les lignes entre les composants et les entités attachés.Le bouclier devrait-il être un composant qui abrite d'autres composants?
Je n'ai jamais vu ou entendu quelque chose comme ça, mais c'est peut-être commun et je ne suis pas encore assez profond.Le bouclier ne devrait-il être qu'un ensemble de composants ajoutés au joueur?
Peut-être avec un composant supplémentaire pour gérer les autres, par exemple afin qu'ils puissent tous être supprimés en tant que groupe. (laissez accidentellement le composant de réduction des dégâts, maintenant ce serait amusant).Quelque chose d'autre qui est évident pour quelqu'un avec plus d'expérience en composants?
la source
Réponses:
Edit: Je pense qu'il n'y a pas assez de "comportement autonome" pour une entité séparée. Dans ce cas spécifique, un bouclier suit la cible, fonctionne pour la cible et ne survit pas à la cible. Bien que j'aie tendance à convenir qu'il n'y a rien de mal avec le concept d'un "objet bouclier", dans ce cas, nous avons affaire à un comportement, qui s'intègre très bien dans un composant. Mais je suis également un défenseur des entités purement logiques (par opposition aux systèmes d'entités à part entière dans lesquels vous pouvez trouver des composants de transformation et de rendu).
Le voir dans une perspective différente; l'ajout d'un composant ajoute également d'autres composants, et lors de la suppression, les composants supplémentaires ont également disparu.
Cela pourrait être une solution, cela favoriserait la réutilisation, mais il est également plus sujet aux erreurs (pour le problème que vous avez mentionné, par exemple). Ce n'est pas nécessairement mauvais. Vous pourriez découvrir de nouvelles combinaisons de sorts avec essais et erreurs :)
Je vais développer un peu.
Je pense que vous avez remarqué que certains composants devraient être prioritaires, peu importe quand ils ont été ajoutés à une entité (cela répondrait également à votre autre question).
Je vais également supposer que nous utilisons la communication basée sur les messages (pour les besoins de la discussion, ce n'est qu'une abstraction sur un appel de méthode pour le moment).
Chaque fois qu'un composant de bouclier est "installé", les gestionnaires de messages de composant de bouclier sont enchaînés avec un ordre spécifique (supérieur).
Le composant "stats" installe un gestionnaire de messages "dommages" à l'index In / Invariant / Normal. Chaque fois qu'un message de "dommage" est reçu, diminuez les HP de sa valeur "value".
Comportement assez standard (insérez une résistance aux dommages naturels et / ou des traits raciaux, peu importe).
Le composant de bouclier installe un gestionnaire de messages "dommages" à l'index In / Pre / High.
Vous pouvez voir que cela est assez flexible, même si cela nécessiterait une planification minutieuse lors de la conception de l'interaction des composants, car vous devrez déterminer dans quelle partie du gestionnaire de messages le gestionnaire d'événements de message du composant de pipeline est installé.
Logique? Faites-moi savoir si je peux ajouter plus de détails.
Edit: concernant plusieurs instances de composants (deux composants d'armure). Vous pouvez soit garder une trace du nombre total d'instances dans une seule instance d'entité (cela tue toutefois l'état par composant) et simplement continuer d'ajouter des gestionnaires d'événements de message, ou vous assurer que vos conteneurs de composants autorisent à l'avance les types de composants en double.
la source
Cela dépend peut-être de la réutilisabilité de votre code et de sa pertinence.
Pas à moins que ce bouclier ne soit une sorte de créature qui puisse se promener indépendamment à un moment donné.
Cela ressemble beaucoup à une entité, donc la réponse est non.
C'est probable.
la source
Un bouclier, en tant qu'entité physique , n'est pas différent de toute autre entité physique , par exemple un drone qui tourne autour de vous (et qui, en fait, pourrait lui-même être un type de bouclier!). Faites donc du bouclier une entité logique distincte (lui permettant ainsi de contenir ses propres composants).
Donnez à votre bouclier quelques composants: un composant physique / spatial pour représenter sa forme de collision et un composant DamageAffector qui contient une référence à une entité à laquelle il appliquera des dommages accrus ou réduits (par exemple, votre personnage de joueur) à chaque fois que l'entité tenir DamageAffector subit des dégâts. Ainsi, votre joueur subit des dégâts "par procuration".
Réglez la position de l'entité bouclier sur la position du joueur à chaque tick. (Écrivez une classe de composants réutilisable qui fait cela: écrire une fois, utiliser plusieurs fois.)
Vous devrez créer l'entité bouclier, par exemple. sur la collecte d'un bonus. J'utilise un concept générique appelé émetteur, qui est un type de composant d'entité qui engendre de nouvelles entités (généralement grâce à l'utilisation d'un EntityFactory auquel il fait référence). L'endroit où vous décidez de localiser l'émetteur dépend de vous - par exemple. mettez-le sur une mise sous tension et faites-le déclencher lorsque la mise sous tension est collectée.
Il existe une fine ligne entre les sous-composants logiques (spatial, AI, emplacements d'armes, traitement d'entrée, etc., etc.) et les sous-composants physiques. Vous devez décider de quel côté de celui-ci vous vous tenez, car cela définit fortement le type de système d'entité que vous avez. Pour moi, le sous-composant physique de mon entité gère les relations physico-hiérarchiques (telles que les membres dans un corps - pensez aux nœuds scénographiques), tandis que les contrôleurs logiques indiqués ci-dessus sont généralement ceux qui sont représentés par les composants de votre entité - plutôt que ceux qui représentent "agencements" physiques individuels.
la source
Peut-être ne contient pas d'autres composants, mais contrôle la durée de vie des sous-composants. Donc, dans un pseudo-code approximatif, votre code client ajouterait ce composant "bouclier".
la source
this
signifie votre réponse. Faitthis
référence au composant Bouclier ou vouliez-vous dire l'entité qui utilise le bouclier, son parent? La confusion pourrait être de ma faute. "Composant basé" est un peu vague. Dans ma version des entités basées sur des composants, une entité est simplement un conteneur de composants avec une fonctionnalité minimale qui lui est propre (nom d'objet, balises, messagerie, etc.).gameObject
quelque chose. Il s'agit d'une référence à l'objet / entité de jeu actuel / quel que soit le propriétaire des composants.Si votre système de composants autorise les scripts, le composant bouclier pourrait être presque un super composant qui appelle simplement un script pour son paramètre "effet". De cette façon, vous maintenez la simplicité d'un composant unique pour les boucliers et déchargez toute la logique de ce qu'il fait réellement sur les fichiers de script personnalisés qui sont alimentés aux boucliers par les définitions de votre entité.
Je fais quelque chose de similaire pour mon composant Moveable, il contient un champ qui est du script keyreaction (une sous-classe de script dans mon moteur) ce script définit une méthode qui suit mon message d'entrée. en tant que tel, je peux simplement faire quelque chose comme ça dans mon fichier de définition tempalte
puis dans mon composant mobile lors de l'enregistrement des messages j'enregistre la méthode Do des scripts (code en C #)
bien sûr, cela repose sur ma méthode Do suivant le modèle de fonctions que mon RegisterHandler prend. Dans ce cas, son (expéditeur IComponent, argument de type ref)
donc mon "script" (dans mon cas aussi C # juste runime compilé) définit
et ma classe de base KeyReactionScript
puis plus tard, lorsqu'un composant d'entrée envoie un message du type MessageTypes.InputUpdate avec le type en tant que tel
La méthode du script qui était liée à ce message et à ce type de données sera déclenchée et gérera toute la logique.
Le code est assez spécifique à mon moteur, mais la logique devrait être fonctionnelle dans tous les cas. Je le fais pour de nombreux types afin de garder la structure des composants simple et flexible.
la source