ฉันไม่คิดว่าจะมีวิธีหนึ่งที่ได้รับการยอมรับในการนำแนวคิดนี้ไปใช้ แต่ฉันอยากจะแบ่งปันวิธีที่ฉันจัดการกับมันในเกมของฉัน มันเป็นการผสมผสานของรูปแบบการออกแบบคำสั่งและรูปแบบการออกแบบคอมโพสิต
ฉันมีคลาสฐานนามธรรมสำหรับการกระทำซึ่งไม่มีอะไรมากไปกว่าเสื้อคลุมรอบUpdate
วิธีที่เรียกว่าแต่ละเฟรมและFinished
แฟล็กเพื่อระบุเมื่อการกระทำเสร็จสิ้นลง
abstract class Action
{
abstract void Update(float elapsed);
bool Finished;
}
ฉันยังใช้รูปแบบการออกแบบคอมโพสิตเพื่อสร้างประเภทของการกระทำที่สามารถโฮสต์และดำเนินการการกระทำอื่น ๆ ได้ นี่ก็เป็นคลาสนามธรรม เดือดลงไปที่:
abstract class CompositeAction : Action
{
void Add(Action action) { Actions.Add(action); }
List<Action> Actions;
}
แล้วฉันมีสองการใช้งานของการกระทำของคอมโพสิตหนึ่งสำหรับการดำเนินการคู่ขนานและหนึ่งสำหรับการดำเนินการตามลำดับ แต่ความงามก็คือตั้งแต่ขนานและลำดับเป็นการกระทำของตัวเองพวกเขาสามารถรวมกันเพื่อสร้างกระแสการดำเนินการที่ซับซ้อนมากขึ้น
class Parallel : CompositeAction
{
override void Update(float elapsed)
{
Actions.ForEach(a=> a.Update(elapsed));
Actions.RemoveAll(a => a.Finished);
Finished = Actions.Count == 0;
}
}
และหนึ่งที่ควบคุมการกระทำตามลำดับ
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;
}
}
ด้วยสิ่งนี้มันเป็นเพียงเรื่องของการสร้างการดำเนินการที่เป็นรูปธรรมและการใช้Parallel
และSequence
การกระทำเพื่อควบคุมการไหลของการดำเนิน ฉันจะจบด้วยตัวอย่าง:
// 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);
ฉันใช้ระบบนี้ในการขับเคลื่อนการเล่นเกมทั้งหมดในการผจญภัยกราฟิกก่อนหน้านี้ได้สำเร็จ แต่มันก็น่าจะใช้ได้กับทุกอย่าง นอกจากนี้ยังง่ายพอที่จะเพิ่มการกระทำคอมโพสิตประเภทอื่นซึ่งใช้สำหรับการสร้างลูปการดำเนินการและเงื่อนไข
- ดูเพิ่มเติม: คำตอบที่เกี่ยวข้องกันที่นี่