Saya tidak berpikir ada satu cara yang diterima untuk menerapkan konsep ini, tetapi saya benar-benar ingin berbagi bagaimana saya biasanya menangani ini dalam permainan saya. Ini sedikit kombinasi dari pola desain Perintah dan pola desain Komposit .
Saya memiliki kelas dasar abstrak untuk tindakan yang tidak lebih dari pembungkus di sekitar Update
metode yang dipanggil setiap frame, dan Finished
bendera untuk menunjukkan kapan tindakan selesai berjalan.
abstract class Action
{
abstract void Update(float elapsed);
bool Finished;
}
Saya juga menggunakan pola desain komposit untuk membuat jenis tindakan yang mampu menampung dan menjalankan tindakan lain. Ini juga kelas abstrak. Bermuara ke:
abstract class CompositeAction : Action
{
void Add(Action action) { Actions.Add(action); }
List<Action> Actions;
}
Kemudian saya memiliki dua implementasi tindakan gabungan, satu untuk eksekusi paralel dan satu untuk eksekusi berurutan . Tetapi keindahannya adalah karena paralel dan urutan adalah tindakan itu sendiri, mereka dapat digabungkan untuk menciptakan aliran eksekusi yang lebih kompleks.
class Parallel : CompositeAction
{
override void Update(float elapsed)
{
Actions.ForEach(a=> a.Update(elapsed));
Actions.RemoveAll(a => a.Finished);
Finished = Actions.Count == 0;
}
}
Dan yang mengatur tindakan berurutan.
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;
}
}
Dengan ini, itu hanya masalah menciptakan implementasi tindakan konkret, dan menggunakan Parallel
dan Sequence
tindakan untuk mengontrol aliran eksekusi. Saya akan mengakhiri dengan sebuah contoh:
// 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);
Saya telah berhasil menggunakan sistem ini untuk menggerakkan semua gameplay dalam petualangan grafis sebelumnya, tetapi mungkin bisa bekerja untuk apa saja. Itu juga cukup sederhana untuk menambahkan jenis tindakan komposit lainnya, yang digunakan untuk membuat loop eksekusi dan kondisional.