我正在编写RTS游戏,我想将用户操作封装到“命令”中。命令允许:
此外,他们必须增加最小的开销。因此,我想避免使用反射。 到目前为止,我提出的最好的是糟糕的,因为我不可避免地得到了一个巨大的转换声明。
enum CommandType {
MoveCamera,
ChangeTerrain
}
// Base class for all commands (public fields used for brevity)
abstract class Command {
protected Command(CommandType type) {
Type = type;
}
public CommandType Type;
}
class CommandMoveCamera : Command {
public CommandMoveCamera() : base(CommandType.MoveCamera) {}
public int DeltaX;
public int DeltaY;
}
class CommandChangeTerrain : Command {
public CommandChangeTerrain() : base(CommandType.ChangeTerrain) {}
public int NewTerrainType;
public int X;
public int Y;
}
class Game {
Queue<Command> m_commands;
void Update() {
// Example of adding a command
m_commands.Enqueue(new CommandMoveCamera { DeltaX = -10, DeltaY = 0 });
// Processing commands
while (m_commands.Count > 0) {
var c = m_commands.Dequeue();
switch(c.Type) {
case CommandType.MoveCamera:
var command = (CommandMoveCamera)c;
MoveCamera(c.DeltaX, c.DeltaY);
break;
case CommandType.ChangeTerrain:
var command = (CommandChangeTerrain)c;
ChangeTerrain(c.X, c.Y, c.NewTerrainType);
break;
}
}
}
}
语言是C#。我的问题是:以满足要求的方式实现该系统的方法是什么,并避免依赖于巨大的switch语句来分支每种不同类型的命令?
谢谢。
答案 0 :(得分:0)
我刚才为游戏引擎做了类似的事情。我实际上经历了一些不同的版本,而我提出的版本是这样的。
然后通过线路发送命令,请求CommandRegistry为您序列化它。它将序列化命令并修正其Id。接收端的CommandRegistry将读取Id,创建适当类型的Command,然后让它从其余数据中反序列化。
我已经在C ++和Go中完成了这个基本设置,所以我认为它应该可以在C#中正常工作。
答案 1 :(得分:0)
我有几点想法。首先,您可以为每种类型的命令公开On<Event>
方法。然后将一个抽象方法添加到Command
,例如Execute
,其参数为Game
。然后,每个命令实现都可以在Game
上调用适当的方法(包括与该命令相关的任何其他逻辑)。你将不再需要枚举。
另一个想法有点相似,但使用代表。为每个命令类型定义委托,并为每个Command实现公开使用此委托的事件。然后在Command
摘要中,您可以使用方法Execute
,该方法在实施时会引发相应的事件。创建每个事件时,只需将Game
上的事件委托给将处理该命令的成员。