Reputation: 22123
I'm writing an RTS game, and I want to encapsulate user actions into "commands". Commands would allow:
Also they must add minimal overhead. I want to avoid using reflection because of this. So far, the best I came up with is bad because I inevitably end up with a huge switch statement.
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;
}
}
}
}
The language is C#. My question is : what would be a way to implement this system in a way that satisfies the requirements and avoid relying on a huge switch statement to branch on each different type of command?
Thank you.
Upvotes: 0
Views: 1041
Reputation: 42497
I have a couple of ideas. First, you could expose On<Event>
methods for each type of command. Then add an abstract method to Command
, like Execute
with the parameter Game
. Each command implementation can then call the appropriate method on Game
(including any other logic relevant to the command). You would no longer need the enum.
The other idea is somewhat similar, but uses delegates. Define a delegate for each command type, and for each Command implementation, expose an event which uses this delegate. Then in your Command
abstract, you can have the method Execute
, which when implemented, raises the appropriate event. When you create each event, you simply delegate the event on Game
to a member that will handle that command.
Upvotes: 0
Reputation: 3011
I did a very similar thing for a game engine a while ago. I actually went through a few different version, and the one I came up with was something like this.
Then to send a command over the wire you ask the CommandRegistry to serialize it for you. It will serialize the command and tack on its Id. The CommandRegistry on the receiving end will read the Id, create a Command of the appropriate type and then ask it to deserialize itself from the rest of the data.
I've done this basic setup both in C++ and in Go, so I think it should work fine in C#.
Upvotes: 0