FSM1

복잡한 상태 기계가 아니라 간단하게 사용 할 수 있는 유한 상태 기계를 알아본다.

Steve Rabin님의 AI Wisdom 1권의 6.5 상태 기계 언어의 구현이다.
가장 간단하게 상태 기계를 만들게 되면 switch 문과 if 문으로 만들어 진다.

#define 문을 이용한 여섯 개의 매크로 키워드로 코드를 나타 낼 수 있다.

BeginStateMachine   
EndStateMachine     
State(a)            
OnEvent(a)          
OnEnter             
OnUpdate            
OnExit              

상태 기계를 사용한 코드 구조는 다음과 같다.

//StateMachine을 상속한 OnStates()에서 상태 처리 구조

BeginStateMachine

 

    ............

 

    State( STATE_WANDER )

        OnEnter

            //상태 시작시 코드 추가

 

        OnUpdate

            //업데이트시 코드 추가, 조건에 따라 상태를 바꾼다.

            SetState( STATE_DEAD );

 

        OnExit

            //상태 종료시 코드 추가

 

    State( STATE_DEAD )

        OnEnter

            //상태 시작시 코드 추가

    ............

 

EndStateMachine

상태 머신의 관리는 StateMachine 클래스에서 이뤄진다.
StateMachine을 상속한 OnStates( ) 메쏘드에 필요한 코드를 추가 한다.

매크로로 만들어진 상태 기계를 이용하는 방법에 대해  알아 보자.

1. StateMachine 클래스를 상속해서 OnStates( ) 메쏘드를 선언 한다..

여기서는 StateMachine 클래스를 상속한 Npc 클래스이다.

class  Npc : public  StateMachine

{

    .........

private:

    virtual  bool  OnStates( float  fTime, StateMachineEvent event, int  state );

    .........

};

2. 상속 받은 클래스의 OnStates( ) 메소드를 구현 한다.

Npc는 STATE_INIT, STATE_WANDER, STATE_DEAD 세 개의 상태를 갖는 NCP_STATE를 선언한다.
StateMachineEvent는 OnEnter, OnUpdate, OnExit 이벤트의 매개 변수이다.

BeginStateMachine, EndStateMachine 사이에 NCP_STATE에 관련된 처리 코드를 추가 한다.

//Add new states here

enum  NPC_STATE

{

    STATE_INIT,

    STATE_WANDER,

    STATE_DEAD

};

 

bool  Npc::OnStates( float  fTime, StateMachineEvent event, int  state )

{

BeginStateMachine

 

    /////////////////////////////////////////////////////////////////

    State( STATE_INIT )

        OnEnter

            m_fTimer = fTime;

            OutputDebugPrintf( "STATE_INIT : OnEnter %.2f \n", fTime );

 

        OnUpdate

            if( fTime - m_fTimer > 3 )

                SetState( STATE_WANDER );

 

 

    /////////////////////////////////////////////////////////////////

    State( STATE_WANDER )

        OnEnter

            m_fTimer = fTime;

            OutputDebugPrintf( "STATE_WANDER : OnEnter %.2f \n", fTime );

 

        OnUpdate

            if( fTime - m_fTimer > 3 )

                SetState( STATE_DEAD );

        OnExit

            OutputDebugPrintf( "STATE_WANDER : OnExit %.2f \n", fTime );

 

    /////////////////////////////////////////////////////////////////

    State( STATE_DEAD )

        OnEnter

            m_bDead = true;

 

EndStateMachine

}

3. 상태 머신을 업데이트 한다.

상속 받은 Npc의 객체를 Initialize( ) 한 후, Update( ) 한다.
 Initialize( )을 실행 하지 않으면 STATE_INIT 상태의 OnEnter 실행 없이 OnUpdate가 최초로 샐행 된다.

    Npc npc;

    npc.Initialize( GetTickCount() / 1000.0f );

 

    while( npc.IsDead() == false )

    {

        float  fTime = GetTickCount() / 1000.0f;

        npc.Update( fTime );

    }

프로젝트 : def_fsm.zip