Contexte
Je fais du développement de jeux comme passe-temps et je cherche une meilleure façon de les concevoir. Actuellement, j'utilise une approche POO standard (je fais du développement d'entreprise depuis 8 ans donc ça vient de façon non-systématique). Prenons par exemple un "méchant"
public class Baddie:AnimatedSprite //(or StaticSprite if needed, which inherit Sprite)
{
//sprite base will have things like what texture to use,
//what the current position is, the base Update/Draw/GetInput methods, etc..
//an AnimatedSprite contains helpers to animated the player while
//a StaticSprite is just one that will draw whatever texture is there
}
Le problème
Disons que je fais un jeu de plateforme 2D et que j'ai besoin du méchant pour pouvoir sauter. Habituellement, ce que je fais est d'ajouter le code approprié dans les méthodes Update / GetInput. Ensuite, si j'ai besoin de faire ramper, canarder, grimper, etc ... le code y ira.
Si je ne fais pas attention, ces méthodes sont encombrées, donc je finis par créer des paires de méthodes comme celle-ci
CheckForJumpAction(Input input)
et DoJump()
CheckforDuckAction(Input input)
et DoDuck()
donc GetInput ressemble
public void DoInput(Input input)
{
CheckForJumpAction(input);
CheckForDuckAction(input);
}
et la mise à jour ressemble
public void Update()
{
DoJump();
DoDuck();
}
Si je vais créer un autre jeu où le joueur doit sauter et esquiver, je vais généralement dans un jeu qui a la fonctionnalité et je le copie. Messy, je sais. C'est pourquoi je recherche quelque chose de mieux.
Solution?
J'aime vraiment comment Blend a des comportements que je peux attacher à un élément. J'ai pensé à utiliser le même concept dans mes jeux. Regardons donc les mêmes exemples.
Je créerais un objet de comportement de base
public class Behavior
{
public void Update()
Public void GetInput()
}
Et je peux créer des comportements en utilisant ça. JumpBehavior:Behavior
etDuckBehavior:Behavior
Je peux ensuite ajouter une collection de comportements à la base Sprite et ajouter ce dont j'ai besoin à chaque entité.
public class Baddie:AnimatedSprite
{
public Baddie()
{
this.behaviors = new Behavior[2];
this.behaviors[0] = new JumpBehavior();
//etc...
}
public void Update()
{
//behaviors.update
}
public GetInput()
{
//behaviors.getinput
}
}
Alors maintenant, si je voulais utiliser Jump and Duck dans de nombreux jeux, je peux simplement apporter les comportements. Je pourrais même faire une bibliothèque pour les plus communes.
Est-ce que ça marche?
Ce que je ne peux pas comprendre, c'est comment partager l'état entre eux. En regardant Jump et Duck, les deux affectent non seulement la partie actuelle de la texture en cours de dessin, mais aussi l'état du joueur. (Le saut va appliquer une quantité décroissante de force ascendante au fil du temps, tandis que le canard va simplement arrêter le mouvement, changer la texture et la taille de la collision du méchant.
Comment puis-je lier cela ensemble pour que cela fonctionne? Dois-je créer des propriétés de dépendance entre les comportements? Dois-je faire connaître chaque comportement au parent et le modifier directement? Une chose que je pensais était de pouvoir passer un délégué dans chaque comportement pour être exécuté lorsqu'il est déclenché.
Je suis sûr qu'il y a plus de problèmes que je regarde, mais le but est que je puisse facilement réutiliser ces comportements entre les jeux et les entités dans le même jeu.
Je vous cède donc la parole. Voulez-vous expliquer comment / si cela peut être fait? As-tu une meilleure idée? Je suis tout ouïe.
Réponses:
Jetez un œil à cette présentation. Cela semble assez proche du type de motif que vous recherchez. Ce modèle prend en charge les comportements et les propriétés attachables. Je ne pense pas que la présentation le mentionne, mais vous pouvez également créer des événements attachables. Cette idée est similaire aux propriétés de dépendance utilisées dans WPF.
la source
Pour moi, cela ressemble à un cas presque manuel pour l'utilisation du modèle de stratégie . Dans ce modèle, vos comportements génériques peuvent être définis dans des interfaces qui vous permettront d'échanger différentes implémentations de comportements lors de l'exécution (pensez à la façon dont une mise sous tension peut affecter la capacité de saut ou de course de votre personnage).
Pour un exemple (artificiel):
Maintenant, vous pouvez implémenter différents types de sauts que votre personnage peut utiliser, sans nécessairement connaître les détails de chaque saut spécifique:
Tous les caractères que vous souhaitez avoir la capacité de sauter peuvent contenir une référence à un IJumpable et peuvent commencer à consommer vos différentes implémentations
Ensuite, votre code peut ressembler à quelque chose comme:
Maintenant, vous pouvez facilement réutiliser ces comportements, ou même les étendre plus tard si vous souhaitez ajouter plus de types de sauts, ou créer plus de jeux construits sur une seule plateforme à défilement horizontal.
la source
Jetez un œil à l' architecture DCI, une approche intéressante de la programmation OO qui peut vous aider.
L'implémentation d'une architecture de style DCI en C # nécessite l'utilisation de classes de domaine simples et l'utilisation d'objets de contexte (comportements) avec des méthodes d'extension et des interfaces pour permettre aux classes de domaine de collaborer sous différents rôles. Les interfaces sont utilisées pour marquer les rôles requis pour un scénario. Les classes de domaine implémentent les interfaces (rôles) qui s'appliquent à leur comportement prévu. La collaboration entre les rôles a lieu dans les objets de contexte (comportement).
Vous pouvez créer une bibliothèque de comportements et de rôles communs qui peuvent être partagés entre les objets de domaine à partir de projets distincts.
Voir DCI en C # pour des exemples de code en C #.
la source
Qu'en est-il de passer dans un objet de contexte dans un comportement qui fournit des méthodes pour changer l'état des sprites / objets affectés par un comportement? Maintenant, si un objet a plusieurs comportements, ils sont chacun appelés en boucle, ce qui leur donne la possibilité de changer le contexte. Si une certaine modification d'une propriété exclut / contraint la modification d'autres propriétés, l'objet contextuel peut fournir des méthodes pour définir une sorte d'indicateur pour indiquer ce fait, ou il peut simplement refuser des modifications indésirables.
la source