Tôi không nghĩ có một cách được chấp nhận để thực hiện khái niệm này, nhưng tôi thực sự muốn chia sẻ cách tôi thường xử lý vấn đề này trong các trò chơi của mình. Đó là một chút kết hợp của mẫu thiết kế Command và mẫu thiết kế Composite .
Tôi có một lớp cơ sở trừu tượng cho các hành động không gì khác hơn là một trình bao bọc xung quanh một Update
phương thức được gọi là mỗi khung và một Finished
cờ để cho biết khi nào hành động đã chạy xong.
abstract class Action
{
abstract void Update(float elapsed);
bool Finished;
}
Tôi cũng sử dụng mẫu thiết kế tổng hợp để tạo ra một loại hành động có khả năng lưu trữ và thực hiện các hành động khác. Đây cũng là một lớp trừu tượng. Luộc xuống:
abstract class CompositeAction : Action
{
void Add(Action action) { Actions.Add(action); }
List<Action> Actions;
}
Sau đó, tôi có hai triển khai các hành động tổng hợp, một cho thực thi song song và một cho thực hiện tuần tự . Nhưng điều tuyệt vời là vì song song và trình tự là hành động, chúng có thể được kết hợp để tạo ra các luồng thực thi phức tạp hơn.
class Parallel : CompositeAction
{
override void Update(float elapsed)
{
Actions.ForEach(a=> a.Update(elapsed));
Actions.RemoveAll(a => a.Finished);
Finished = Actions.Count == 0;
}
}
Và một trong những chi phối hành động liên tiếp.
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;
}
}
Với điều này, đó đơn giản chỉ là vấn đề tạo ra các triển khai hành động cụ thể, và sử dụng Parallel
và Sequence
các hành động để kiểm soát luồng thực thi. Tôi sẽ kết thúc bằng một ví dụ:
// 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);
Tôi đã sử dụng thành công hệ thống này để điều khiển tất cả các trò chơi trong một cuộc phiêu lưu đồ họa trước đây, nhưng nó có thể hoạt động cho hầu hết mọi thứ. Nó cũng đủ đơn giản để thêm các loại hành động tổng hợp khác, được sử dụng để tạo các vòng lặp thực thi và các điều kiện.