Ich glaube nicht, dass es einen akzeptierten Weg gibt, dieses Konzept umzusetzen, aber ich möchte wirklich gerne mitteilen, wie ich in meinen Spielen normalerweise damit umgehe. Es ist eine Art Kombination aus dem Command- Entwurfsmuster und dem zusammengesetzten Entwurfsmuster.
Ich habe eine abstrakte Basisklasse für Aktionen, die nichts anderes als ein Wrapper um eine Update
Methode ist, die für jeden Frame aufgerufen wird, und ein Finished
Flag, das angibt, wann die Aktion beendet wurde.
abstract class Action
{
abstract void Update(float elapsed);
bool Finished;
}
Ich verwende auch das zusammengesetzte Entwurfsmuster, um eine Art von Aktionen zu erstellen, die andere Aktionen hosten und ausführen können. Auch dies ist eine abstrakte Klasse. Läuft darauf hinaus:
abstract class CompositeAction : Action
{
void Add(Action action) { Actions.Add(action); }
List<Action> Actions;
}
Dann habe ich zwei Implementierungen von zusammengesetzten Aktionen, eine für die parallele Ausführung und eine für die sequentielle Ausführung . Das Schöne ist jedoch, dass Parallelität und Sequenz selbst Aktionen sind und kombiniert werden können, um komplexere Ausführungsabläufe zu erstellen.
class Parallel : CompositeAction
{
override void Update(float elapsed)
{
Actions.ForEach(a=> a.Update(elapsed));
Actions.RemoveAll(a => a.Finished);
Finished = Actions.Count == 0;
}
}
Und derjenige, der sequentielle Aktionen regelt.
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;
}
}
Wenn dies vorhanden ist, müssen lediglich konkrete Aktionsimplementierungen erstellt und die Aktionen Parallel
und verwendet werden Sequence
, um den Ausführungsfluss zu steuern. Ich werde mit einem Beispiel enden:
// 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);
Ich habe dieses System bereits erfolgreich verwendet, um das gesamte Gameplay in einem grafischen Abenteuer zu steuern, aber es sollte wahrscheinlich für so ziemlich alles funktionieren. Es war auch einfach genug, andere Arten von zusammengesetzten Aktionen hinzuzufügen, die zum Erstellen von Ausführungsschleifen und Bedingungen verwendet wurden.