[게임 개발 : 히어로 체스] 2. 명령 패턴 적용

WIGWAG·2023년 1월 16일
0

히어로 체스

목록 보기
3/5

명령 패턴이란?

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

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


코드 설명

명령 패턴을 적용하기 위해 Command클래스를 추상 클래스로 두고
하위 명령 클래스는 Command클래스를 상속한다.

InputHandler클래스에서는 게임에 필요한 각 키들을 필요한 명령클래스와 바인드하고
키를 눌렀을 경우 바인드된 명령클래스의 실행함수가 실행된다.

이동 명령을 조잡하게 만들긴 했다. 마우스 클릭으로 이동 위치를 설정하는 것은 후에 생각하기로 하자. 그래도 이정도면 명령 패턴을 잘 적용한 것 같다.


<C_Command.h>

#pragma once
#include "C_Hero.h"

class C_Command
{
public:
    virtual ~C_Command() {}
    virtual void execute(C_Hero* unit) = 0;
    virtual void undo() = 0;
};

class MoveUnitCommand : public C_Command
{
public:
	virtual void execute(C_Hero* unit) override;
	virtual void undo() override;
private:
	C_Hero* unit_;
	int x_, y_;
	int before_x = -1, before_y = -1;
};

<C_Command.cpp>

#include "stdafx.h"
#include "C_Command.h"

void MoveUnitCommand ::execute(C_Hero* unit)
{
	unit_ = unit;
	if (before_x == -1)
		before_x = unit_->get_x();
	if (before_y == -1)
		before_y = unit_->get_y();
	unit_->Move_Per_Frame(0, 0);
}

void MoveUnitCommand::undo()
{
	if (unit_)
		unit_->Move_Per_Frame(before_x, before_y);
}

<C_InputHandler.h>

#pragma once
#include "C_Command.h"
#include "C_Hero.h"

class C_InputHandler
{
public:
	void Handle_Input(C_Hero* hero);
	void Bind_Command();
	void Set_Pressed(char ch);
private:
	std::shared_ptr<C_Command> buttonAZ;

	bool A_is_pressed = false;
	bool Z_is_pressed = false;
};

<C_InputHandler.cpp>

#include "stdafx.h"
#include "C_InputHandler.h"

void C_InputHandler::Handle_Input(C_Hero* hero)
{
	if (A_is_pressed)
		buttonAZ->execute(hero);
	else if (Z_is_pressed)
		buttonAZ->undo();
}

void C_InputHandler::Bind_Command()
{
	buttonAZ = std::make_shared<MoveUnitCommand>();
}

void C_InputHandler::Set_Pressed(char ch)
{
	switch (ch)
	{
	case 'A': 
	{
		A_is_pressed = true;
		Z_is_pressed = false;
		break;
	}
	case 'S': 
	{
		A_is_pressed = false; 
		Z_is_pressed = false;
		break;
	}
	case 'Z': {
		A_is_pressed = false;
		Z_is_pressed = true; 
		break;
	}
	}
}

<마법사 클래스의 설정한 목적지까지 이동하는 함수>

void C_Magician::Move_Per_Frame(int dest_x, int dest_y)
{
    int dist_x = dest_x - x;
    int dist_y = dest_y - y;

    if (dist_x >= -5 and dist_x <= 5)
        x = dest_x;
    else
    {
        int move_x = 10 * dist_x / (int)sqrt(dist_x * dist_x + dist_y * dist_y);
        x += move_x;
    }

    if (dist_y >= -5 and dist_y <= 5)
        y = dest_y;
    else
    {
        int move_y = 10 * dist_y / (int)sqrt(dist_x * dist_x + dist_y * dist_y);
        y += move_y;
    }
}

실행 결과

<초기 화면>



<A키를 누르면 0,0위치로 이동한다.>



<Z키를 누르면 이전 위치로 이동한다.>



<S키를 누르면 이동 중에 정지한다.>

profile
윅왁의 프로그래밍 개발노트

0개의 댓글