Part 1. 1) Commander Pattern (C#, Unity)
Commander Pattern
•
Capsulate the command itself. Through this, make different users who have different inputs parameter, wait or logging the users’ requests and supporting the restore operation.
◦
= Command Patterns reify calling functions.
▪
“reifing” means changing the concept into object.
▪
“reifing calling functions” means that wrapping calling functions with objects
▪
it is equal to express callbacks (or function pointer) with OOP (Object-Oriented Programming)
Example
•
Changing the Input keys
X → JUMP()
Y → FURE_GUN()
Z → LURCH()
X → SWAP_WEAPON()
•
Before
Class InputHandler() {
public void handleInput(){
if (isPressed(ButtonX) jump();
else if (isPressed(ButtonY) fireGun();
}
void jump() {...}
void fireGun() {...} //implicitly call the actors
public void isPressed(UserInput ButtonX) //UserInput is peusdo class
C#
복사
•
After
class Command() {
public virtual Command() {}
public virtual void execute {}
}
class JumpCommand() : Command {
public virtual void execute() { jump(); }
}
class FireCommand() : Command {
public virtual void execute() { fireGun(); }
}
class InputHandler {
private Command buttonX;
private Command buttonY;
...
public void handleInput(){
if(isPressed(ButtonX)) buttonX.execute();
...
}
}
C#
복사
•
Constraints : the code has coupling; each function (jump & fire_gun()) finds character objects implicitly.
•
Solve: Pass the character object as a parameter
class JumpCommand: Command {
public virtual void execute(GameActor actor) {
actor.jump();
}
}
C#
복사
•
Key idea: one abstract class between actor and command
◦
From now on, we can handle all the actors cause we used Command Pattern by passing the actors as a parameter !
Other Use Case
•
Command Stream
◦
AI (Input Handler, Producer) → Command Stream → Actor (Dispatcher, Subscriber)
•
Undo Command
◦
define virtual method undo()
class Command() {
public virtual Command() {};
public virtual execute() {};
public virtual undo() {};
}
Python
복사
◦
store previous status into variables
public class MoveUnitCommand : Command {
private Unit unit;
private int x, y;
private int xBefore, yBefore;
public MoveUnitCommand(Unit unit, int x, int y) {
this.unit = unit;
this.x = x;
this.y = y;
this.xBefore = 0; // Assuming default initialization
this.yBefore = 0;
}
public override void Execute() {
// Store previous status into variables
xBefore = unit.X; // Assuming X and Y are properties of Unit
yBefore = unit.Y;
unit.MoveTo(x, y); // Assuming MoveTo is a method of Unit
}
public override void Undo() {
unit.MoveTo(xBefore, yBefore);
}
}
C#
복사
Summary
•
Chain of Responsibility
◦
if objects can react to the command and can assign processing command to sub-objects, it could be the Chain of Responsiblity Pattern.
1.
I would say Commander Pattern is making abstract class for the command to do decoupling user’s input and actors
2.
Commander Pattern can be utilized to implement the undo function
Reference
•
There are some commands only have actions without status. If so, making many instances of the command classes are memory-wasting job. It can be solved by the Lightweight Patterns
This contents are originated from “Game Programming Patterns”, Robert, Hanbit Media Inc. (Korean Version)
This contents are originated from “Game Programming Patterns”, Robert, Hanbit Media Inc. (Korean Version)