Command
Page dedicated to knowledge related to Command design pattern from gaming programming pattern by Robert Nystrom..
In my own words
Command design pattern is a design pattern for encapsulating command function. The most interesting case is when storing a state for allowing undo and redo actions.
Basic idea
From the Gang of Four: Commands are an object-oriented replacement for callbacks.
// ===== an interface command defining command methods ========================
class Command
{
public:
virtual ~Command() {}
// pass the actor on which the command must be executed
virtual void execute(GameActor& actor) = 0;
};
// ===== a function returning command according to input ======================
Command* InputHandler::handleInput()
{
if (isPressed(BUTTON_X)) return buttonX_;
if (isPressed(BUTTON_Y)) return buttonY_;
if (isPressed(BUTTON_A)) return buttonA_;
if (isPressed(BUTTON_B)) return buttonB_;
// nothing pressed, so do nothing.
return NULL;
}
// ===== retrieve command and execute it on specific actor ====================
Command* command = inputHandler.handleInput();
if (command)
{
command->execute(actor);
}
We can let the player control any actor in the game now by changing the actor we execute the commands on.
Undo and Redo
// ===== add undo method ======================================================
class Command
{
public:
virtual ~Command() {}
virtual void execute() = 0;
virtual void undo() = 0;
};
// ===== now the command stores previous and next state =======================
class MoveUnitCommand : public Command
{
public:
MoveUnitCommand(Unit* unit, int x, int y)
: unit_(unit),
xBefore_(0),
yBefore_(0),
x_(x),
y_(y)
{}
virtual void execute()
{
// retrieve current position
xBefore_ = unit_->x();
yBefore_ = unit_->y();
// move to next position
unit_->moveTo(x_, y_);
}
virtual void undo()
{
unit_->moveTo(xBefore_, yBefore_);
}
private:
// unit of which the command was run
Unit* unit_;
// previous state
int xBefore_, yBefore_;
// next state
int x_, y_;
};