[게임 프로그래밍 패턴] 1. 명령 패턴

WIGWAG·2023년 2월 13일

명령 패턴이란?

요청 자체를 캡슐화하는 것이다. 이를 통해 요청이 서로 다른 사용자를 매개변수로 만들고, 요청을 대기시키거나 로깅하며, 되돌릴 수 있는 연산을 지원한다. (GoF의 디자인 패턴 311p)

서로 다른 클래스의 비슷한 종류의 메서드를 하나로 묶어 객체지향적으로 표현한 것을 의미한다.
명령 패턴을 사용하면 지저분한 코드가 깔끔하게 정리된다.


명령 패턴 예시 코드

#include <iostream>

using namespace std;

class C_GameActor {
public:
	void Jump() {}
	void Fire_Gun() {}
	void Swap_Weapon() {}
	void Lurch() {}
	void MoveTo(int x, int y) {}
	int X() const { return x_; }
	int Y() const { return y_; }

private:
	int x_;
	int y_;
};

class C_Command {
public:
	virtual ~C_Command() {}
	virtual void Execute(C_GameActor& actor) = 0;
	virtual void Undo(C_GameActor& actor) {};
};

class C_JumpCommand : public C_Command {
public:
	virtual void Execute(C_GameActor& actor) {
		actor.Jump();
	}
};

class C_FireCommand : public C_Command {
public:
	virtual void Execute(C_GameActor& actor) override {
		actor.Fire_Gun();
	}
};

class C_SwapCommand : public C_Command {
public:
	virtual void Execute(C_GameActor& actor) override {
		actor.Swap_Weapon();
	}
};

class C_LurchCommand : public C_Command {
public:
	virtual void Execute(C_GameActor& actor) override {
		actor.Lurch();
	}
};

class C_MoveUnitCommand : public C_Command {
public:
	C_MoveUnitCommand(int x, int y)
		:x_(x), y_(y) {}

	virtual void Execute(C_GameActor& actor) override {
		xBefore_ = actor.X();
		xBefore_ = actor.Y();
		actor.MoveTo(x_, y_);
	}

	virtual void Undo(C_GameActor& actor) override {
		actor.MoveTo(xBefore_, yBefore_);
	}

private:
	int x_, y_;
	int xBefore_ = 0, yBefore_ = 0;
};

enum Key
{
	BUTTON_UP,
	BUTTON_DOWN,
	BUTTON_LEFT,
	BUTTON_RIGHT,
	BUTTON_X,
	BUTTON_Y,
	BUTTON_A,
	BUTTON_B
};

class C_InputHandler {
public:
	shared_ptr<C_Command> HandleInput();
	shared_ptr <C_GameActor> GetSelectedUnit() { return make_shared<C_GameActor>(); }
	bool IsPressed(int key) { 
		// 키 눌렀는지 체크하는 코드

		//임시 리턴
		return true; 
	}
private:
	int pressedKey[10];
};

shared_ptr<C_Command> C_InputHandler::HandleInput() {
	shared_ptr <C_GameActor> unit = GetSelectedUnit();
	if (IsPressed(BUTTON_UP)) return make_shared<C_MoveUnitCommand>(unit->X(), unit->Y() - 1);
	if (IsPressed(BUTTON_DOWN)) return make_shared<C_MoveUnitCommand>(unit->X(), unit->Y() + 1);
	if (IsPressed(BUTTON_LEFT)) return make_shared<C_MoveUnitCommand>(unit->X() - 1, unit->Y());
	if (IsPressed(BUTTON_RIGHT)) return make_shared<C_MoveUnitCommand>(unit->X() + 1, unit->Y());
	if (IsPressed(BUTTON_X)) return make_shared<C_JumpCommand>();
	if (IsPressed(BUTTON_Y)) return make_shared<C_FireCommand>();
	if (IsPressed(BUTTON_A)) return make_shared<C_SwapCommand>();
	if (IsPressed(BUTTON_B)) return make_shared<C_LurchCommand>();
	return nullptr;
}

int main()
{
	C_InputHandler inputHandler;
	C_GameActor actor;
	//명령 할당
	shared_ptr<C_Command> command = inputHandler.HandleInput();
	//명령 실행
	if (command) command->Execute(actor);
}
profile
프로그래밍 공부 기록 노트

0개의 댓글