Je ne pense pas qu'il existe une façon acceptée de mettre en œuvre ce concept, mais j'aimerais vraiment partager la façon dont je gère généralement cela dans mes jeux. C'est un peu une combinaison du modèle de conception Command et du modèle de conception Composite .
J'ai une classe de base abstraite pour les actions qui n'est rien de plus qu'un wrapper autour d'une Update
méthode qui est appelée chaque trame, et un Finished
indicateur pour indiquer quand l'action a fini de s'exécuter.
abstract class Action
{
abstract void Update(float elapsed);
bool Finished;
}
J'utilise également le modèle de conception composite pour créer un type d'actions capable d'héberger et d'exécuter d'autres actions. C'est aussi une classe abstraite. Se résume à:
abstract class CompositeAction : Action
{
void Add(Action action) { Actions.Add(action); }
List<Action> Actions;
}
Ensuite, j'ai deux implémentations d'actions composites, une pour l' exécution parallèle et une pour l'exécution séquentielle . Mais la beauté est que le parallèle et la séquence étant eux-mêmes des actions, ils peuvent être combinés afin de créer des flux d'exécution plus complexes.
class Parallel : CompositeAction
{
override void Update(float elapsed)
{
Actions.ForEach(a=> a.Update(elapsed));
Actions.RemoveAll(a => a.Finished);
Finished = Actions.Count == 0;
}
}
Et celui qui régit les actions séquentielles.
class Sequence : CompositeAction
{
override void Update(float elapsed)
{
if (Actions.Count > 0)
{
Actions[0].Update(elapsed);
if (Actions[0].Finished)
Actions.RemoveAt(0);
}
Finished = Actions.Count == 0;
}
}
Avec cela en place, il s'agit simplement de créer des implémentations d'actions concrètes et d'utiliser les actions Parallel
et Sequence
pour contrôler le flux d'exécution. Je termine avec un exemple:
// Create a parallel action to work as an action manager
Parallel actionManager = new Parallel();
// Send character1 to destination
Sequence actionGroup1 = new Sequence();
actionGroup1.Add(new MoveAction(character1, destination));
actionGroup1.Add(new TalkAction(character1, "Arrived at destination!"));
actionManager.Add(actionGroup1);
// Make character2 use a potion on himself
Sequence actionGroup2 = new Sequence();
actionGroup2.Add(new RemoveItemAction(character2, ItemType.Potion));
actionGroup2.Add(new SetHealthAction(character2, character2.MaxHealth));
actionGroup2.Add(new TalkAction(character2, "I feel better now!"));
actionManager.Add(actionGroup2);
// Every frame update the action manager
actionManager.Update(elapsed);
J'ai utilisé avec succès ce système pour piloter tout le gameplay dans une aventure graphique auparavant, mais il devrait probablement fonctionner à peu près n'importe quoi. Il était également assez simple d'ajouter d'autres types d'actions composites, qui étaient utilisées pour créer des boucles d'exécution et des conditions.