728x90

1. 상태 패턴 정의

  • 객체의 내부 상태에 따라 스스로 행동을 변경할 수 있게 허가하는 패턴으로, 이렇게 하면 객체는 마치 자신의 클래스를 바꾸는 것처럼 보입니다.

 

2. 유한 상태 기계 ( FSM : Finite State Machine )

상태 기계 플로우 차트

  • 가질 수 있는 '상태'가 한정된다
  • 합 번에 '한 가지' 상태만 될 수 있다.
  • '입력'이나 '이벤트'가 기계에 전달된다.
  • 각 상태에는 입력에 따라 다음 상태로 바뀌는 '전이'가 있다.
  • 엄격하게 제한된 구조를 강제함으로써 복잡하게 얽힌 코드를 정리할 수 있게 한다.
  • 미리 정해놓은 여러 상태와 현재 상태 하나, 하드 코딩되어 있는 전이만 존재

 

3. 상태 인터페이스 구현

// 상태 인터페이스
class HeroineState
{
public:
	virtual ~HeroineState() {}
	virtual HeroineState* HandleInput( Heroine& InHeroine, INPUT InInput ) {}
	
	// 상태 입장.
	virtual void Enter( Heroine& InHeroine ) {}

	// 상태 퇴장
	virtual void Exit( Heroine& InHeroine ) {}
};

 

4. 상태별 클래스

// 상태별 클래스
class DuckingState : public HeroineState
{
public:
	virtual HeroineState* HandleInput( Heroine& InHeroine, INPUT InInput ) override
	{
		if ( InInput == INPUT::RELEASE_DOWN )
			return new StandingState();
	}

	virtual void Enter( Heroine& InHeroine ) override
	{
		// 상태 입장 시 실행될 함수들
		InHeroine.SetGraphics( STATE_IMAGE::IMAGE_DUNCKING );
	}

	virtual void Exit( Heroine& InHeroine ) override
	{
		// 상태 퇴장 시 실행될 함수들
	}
};

class StandingState : public HeroineState
{
public:
	virtual HeroineState* HandleInput( Heroine& InHeroine, INPUT InInput ) override
	{
		if ( InInput == INPUT::PRESS_DOWN )
			return new DuckingState();

		// 현재 상태 유지
		return nullptr;
	}

	virtual void Enter( Heroine& InHeroine ) override
	{
		// 상태 입장 시 실행될 함수들
		InHeroine.SetGraphics( STATE_IMAGE::IMAGE_STAND );
	}

	virtual void Exit( Heroine& InHeroine ) override
	{
		// 상태 퇴장 시 실행될 함수들
	}
};

 

5. 동작 상태 위임

class Heroine
{
private:
	HeroineState* State;

public:
	virtual void HandleInput( INPUT InInput )
	{
		HeroineState* state = State->HandleInput( *this, InInput );
		if ( state != nullptr )
		{
        	// 기존 상태 퇴장 함수 호출
			State->Exit( *this );

			delete State;
			State = state;

			// 새로운 상태의 입장 함수 호출
			State->Enter( *this );
		}		
	}

	void SetGraphics( STATE_IMAGE InStateImage );
};

 

6. 병행 상태 기계

// 병행 상태 기계
class Heroine
{
private:
	// 캐릭터 상태
	HeroineState* State;

	// 장비 상태
	HeroineState* Equipment;

public:
	virtual void HandleInput( INPUT InInput )
	{
		// 나누어진 상태 모두에게 전달
		HeroineState* state = State->HandleInput( *this, InInput );
		HeroineState* equipment = Equipment->HandleInput( *this, InInput );
		//....
	}
};
  • 유한 상태 기계 방식을 이용한 경우, 두 종류의 상태를 위해서는 N*M개의 상태가 필요하다.
  • 상태 기계 둘로 나누어 사용할 경우 N+M개의 상태만 있으면된다.

 

7. 계층형 상태 기계

// 상위 상태
class OnGroundState : public HeroineState
{
public:
	virtual HeroineState* HandleInput( Heroine& InHeroine, INPUT InInput ) override
	{
		if ( InInput == INPUT::RELEASE_DOWN )
		{
			return new StandingState();
		}
		else if ( InInput == INPUT::PRESS_DOWN )
		{
			//..
		}
	}
};

// 하위 상태
class DuckingState : public OnGroundState
{
public:
	virtual HeroineState* HandleInput( Heroine& InHeroine, INPUT InInput ) override
	{
		if ( InInput == INPUT::RELEASE_DOWN )
		{
			return new StandingState();
		}
		else
		{
			// 따로 입력을 처리하지 않고, 상위 상태로 보낸다.
			OnGroundState::HandleInput( InHeroine, InInput );
		}
	}
};
  • '땅 위에 있는' , '바다 안에 있는' 상태 등 특정 상태를 상위 클래스로 정의해 처리하는 것을 계층형 상태 기계라고 한다.
  • 어떤 상태는 상위 상태를 가질 수 있고, 그 경우 그 상태 자신은 하위 상태가 된다.
  • 이벤트가 들어올 때 하위 상태에서 처리하지 않으면, 상위 상태로 넘긴다.

 

반응형

+ Recent posts