1. 게임제작론고급1및실습
DD3440 Mar. 2, 2010
Chapter 2
상태구동형 에이전트의 디자인
박창훈
호서대학교 게임공학과
2010년 3월 23일 화요일
2. 2. 상태구동형 에이전트의 디자인
DD3440 Mar. 2, 2010
A. 유한상태 기계란 정확하게 무엇일까?
2010년 3월 23일 화요일
3. 3
A. 유한상태 기계란 정확하게 무엇일까?
2. 상태구동형 에이전트의 디자인 Mar. 2, 2010
2010년 3월 23일 화요일
4. 2. 상태구동형 에이전트의 디자인
DD3440 Mar. 2, 2010
B. 유한상태기계 구현하기
B1. 상태 전환표
B2. 내장된 규칙들
2010년 3월 23일 화요일
5. 5
2. 상태구동형 에이전트의 디자인
Mar. 2, 2010
enum StateType
{
RunAway, Patrol, Attack
};
void Agent::UpdateState(StateType CurrentState)
{
switch (CurrentState)
{
case state_RunAway:
EvadeEnemy();
if (Safe())
{
ChangeState( state_Patrol);
}
break;
2010년 3월 23일 화요일
6. 6
2. 상태구동형 에이전트의 디자인
Mar. 2, 2010
case state_Patrol:
FollowPatrolPath();
if (Threatened())
{
if (StrongerThanEnemy())
{
ChangeState( state_Attack);
}
else
{
ChangeState( state_RunAway);
}
}
break;
2010년 3월 23일 화요일
7. 7
2. 상태구동형 에이전트의 디자인
Mar. 2, 2010
case state_Attack:
if (WeakerThanEnemy())
{
ChangeState( state_RunAway);
}
else
{
BashEnemyOverHead();
}
break;
}//end switch
}
2010년 3월 23일 화요일
8. 8
B1. 상태 전환표
2. 상태구동형 에이전트의 디자인 Mar. 2, 2010
2010년 3월 23일 화요일
9. 2. 상태구동형 에이전트의 디자인
DD3440 Mar. 2, 2010
B. 유한상태기계 구현하기
B1. 상태 전환표
B2. 내장된 규칙들
2010년 3월 23일 화요일
10. 10
B2. 내장된 규칙들
2. 상태구동형 에이전트의 디자인 Mar. 2, 2010
class State
{
public:
virtual void Execute(Troll* troll)=0;
};
2010년 3월 23일 화요일
11. 11
B2. 내장된 규칙들
2. 상태구동형 에이전트의 디자인 Mar. 2, 2010
class Troll
{
/* ATTRIBUTES OMITTED */
State* m_pCurrentState;
public:
/* INTERFACE TO ATTRIBUTES OMITTED */
void Update()
{
m_pCurrentState->Execute(this;)
}
void ChangeState(const State* pNewState)
{
delete m_pCurrentState;
m_pCurrentState = pNewState;
}
};
2010년 3월 23일 화요일
12. 12
B2. 내장된 규칙들
2. 상태구동형 에이전트의 디자인 Mar. 2, 2010
//------------------------------State RunAway
class State_Runway : public State
{
public:
void Execute(Troll* troll)
{
if(troll->isSafe())
{
troll->ChangeState(new State_Sleep());
}
else
{
troll->MoveAwayFromEnemy();
}
}
};
2010년 3월 23일 화요일
13. 13
B2. 내장된 규칙들
2. 상태구동형 에이전트의 디자인 Mar. 2, 2010
//-----------------------------State_Sleep
class State_Slepp : public State
{
void Execute(Troll* troll)
{
if(troll->isThreatened())
{
troll->ChangeState(new State_RunAway())
}
else
{
troll->Snore();
}
}
};
2010년 3월 23일 화요일
14. 2. 상태구동형 에이전트의 디자인
DD3440 Mar. 2, 2010
C. West World 프로젝트
C1. BaseGameEntity 클래스
C2. Minor 클래스
C3. Minor 상태들
C4. 상태 디자인 패턴에 대해 자세히 알아보기
2010년 3월 23일 화요일
15. 15
C1. BaseGameEntity 클래스
2. 상태구동형 에이전트의 디자인 Mar. 2, 2010
class BaseGameEntity
{
private:
int m_ID;
static int m_iNextValidID;
void SetID(int val);
public:
BaseGameEntity(int id)
{
SetID(id);
}
virtual ~BaseGameEntity(){}
virtual void Update()=0;
int ID()const{return m_ID;}
};
2010년 3월 23일 화요일
16. 2. 상태구동형 에이전트의 디자인
DD3440 Mar. 2, 2010
C. West World 프로젝트
C1. BaseGameEntity 클래스
C2. Minor 클래스
C3. Minor 상태들
C4. 상태 디자인 패턴에 대해 자세히 알아보기
2010년 3월 23일 화요일
17. 17
C2. Minor 클래스
2. 상태구동형 에이전트의 디자인 Mar. 2, 2010
class Miner : public BaseGameEntity
{
private:
State* m_pCurrentState;
location_type m_Location;
int m_iGoldCarried;
int m_iMoneyInBank;
int m_iThirst;
int m_iFatigue;
public:
Miner(int id);
void Update();
void ChangeState(State* new_state);
}
2010년 3월 23일 화요일
18. 18
C2. Minor 클래스
2. 상태구동형 에이전트의 디자인 Mar. 2, 2010
void Miner::Update()
{
m_iThirst += 1;
if (m_pCurrentState)
{
m_pCurrentState->Execute(this);
}
}
2010년 3월 23일 화요일
19. 2. 상태구동형 에이전트의 디자인
DD3440 Mar. 2, 2010
C. West World 프로젝트
C1. BaseGameEntity 클래스
C2. Minor 클래스
C3. Minor 상태들
C4. 상태 디자인 패턴에 대해 자세히 알아보기
2010년 3월 23일 화요일
20. 20
C3. Minor 상태들
2. 상태구동형 에이전트의 디자인 Mar. 2, 2010
2010년 3월 23일 화요일
21. 2. 상태구동형 에이전트의 디자인
DD3440 Mar. 2, 2010
C. West World 프로젝트
C1. BaseGameEntity 클래스
C2. Minor 클래스
C3. Minor 상태들
C4. 상태 디자인 패턴에 대해 자세히 알아보기
2010년 3월 23일 화요일
22. 22
C4. 상태 디자인 패턴에 대해 자세히 알아보기
2. 상태구동형 에이전트의 디자인 Mar. 2, 2010
class State
{
public:
virtual ~State(){}
//this will execute when the state is entered
virtual void Enter(Miner*)=0;
//this is the state's normal update function
virtual void Execute(Miner*)=0;
//this will execute when the state is exited. (My word, isn't
//life full of surprises... ;o))
virtual void Exit(Miner*)=0;
};
2010년 3월 23일 화요일
23. 23
C4. 상태 디자인 패턴에 대해 자세히 알아보기
2. 상태구동형 에이전트의 디자인 Mar. 2, 2010
void Miner::ChangeState(State* pNewState) {
//make sure both states are both valid before attempting to
//call their methods
assert(m_pCurrentState && pNewState);
//call the exit method of the existing state
m_pCurrentState->Exit(this);
//change state to the new state
m_pCurrentState = pNewState;
//call the entry method of the new state
m_pCurrentState->Enter(this);
}
2010년 3월 23일 화요일
24. 24
C4. 상태 디자인 패턴에 대해 자세히 알아보기
2. 상태구동형 에이전트의 디자인 Mar. 2, 2010
2010년 3월 23일 화요일
25. 25
C4. 상태 디자인 패턴에 대해 자세히 알아보기
2. 상태구동형 에이전트의 디자인 Mar. 2, 2010
/* ------------------ MyClass.h ------------------- */
#ifndef MY_SINGLETON
#define MY_SINGLETON
class MyClass
{
private:
int m_iNum;
MyClass(){}
MyClass(const MyClass &);
MyClass& operator=(const MyClass &);
public:
~MyClass();
int GetVal()const{return m_iNum;}
static MyClass* Instance();
2010년 3월 23일 화요일
26. 26
C4. 상태 디자인 패턴에 대해 자세히 알아보기
2. 상태구동형 에이전트의 디자인 Mar. 2, 2010
/* ------------------ MyClass.h ------------------- */
public:
~MyClass();
//methods
int GetVal()const{return m_iNum;}
static MyClass* Instance();
};
#endif
/* ------------------- MyClass.cpp ------------------ */
MyClass* MyClass::Instance()
{
static MyClass instance;
return &instance;
}
2010년 3월 23일 화요일
27. 27
C4. 상태 디자인 패턴에 대해 자세히 알아보기
2. 상태구동형 에이전트의 디자인 Mar. 2, 2010
int num = MyClass::Instance()->GetVal();
#define MyCls MyClass::Instance()
int num = MyCls->GetVal();
2010년 3월 23일 화요일
28. 28
C4. 상태 디자인 패턴에 대해 자세히 알아보기
2. 상태구동형 에이전트의 디자인 Mar. 2, 2010
๏ EnterMineAndDigForNugget
class EnterMineAndDigForNugget : public State
{
private:
EnterMineAndDigForNugget(){}
/* copy ctor and assignment op omitted */
public:
//this is a singleton
static EnterMineAndDigForNugget* Instance();
virtual void Enter(Miner* miner);
virtual void Execute(Miner* miner);
virtual void Exit(Miner* miner);
};
2010년 3월 23일 화요일
29. 29
C4. 상태 디자인 패턴에 대해 자세히 알아보기
2. 상태구동형 에이전트의 디자인 Mar. 2, 2010
๏ EnterMineAndDigForNugget
void EnterMineAndDigForNugget::Enter(Miner* pMiner)
{
//if the miner is not already located at the goldmine, he must
//change location to the gold mine
if (pMiner->Location() != goldmine)
{
SetTextColor(FOREGROUND_RED| FOREGROUND_INTENSITY);
cout << "n" << GetNameOfEntity(pMiner->ID()) << ": "
<< "Walkin' to the goldmine";
pMiner->ChangeLocation(goldmine);
}
}
2010년 3월 23일 화요일
30. 30
C4. 상태 디자인 패턴에 대해 자세히 알아보기
2. 상태구동형 에이전트의 디자인 Mar. 2, 2010
๏ EnterMineAndDigForNugget
void EnterMineAndDigForNugget::Execute(Miner* pMiner)
{
pMiner->AddToGoldCarried(1);
pMiner->IncreaseFatigue();
SetTextColor(FOREGROUND_RED| FOREGROUND_INTENSITY);
cout << "n" << GetNameOfEntity(pMiner->ID()) << ": "
<< "Pickin' up a nugget";
if (pMiner->PocketsFull()) {
pMiner->ChangeState(VisitBankAndDepositGold::Instance());
}
if (pMiner->Thirsty()) {
pMiner->ChangeState(QuenchThirst::Instance());
}
}
2010년 3월 23일 화요일
31. 31
C4. 상태 디자인 패턴에 대해 자세히 알아보기
2. 상태구동형 에이전트의 디자인 Mar. 2, 2010
๏ EnterMineAndDigForNugget
void EnterMineAndDigForNugget::Exit(Miner* pMiner)
{
SetTextColor(FOREGROUND_RED| FOREGROUND_INTENSITY);
cout << "n" << GetNameOfEntity(pMiner->ID()) << ": "
<< "Ah'm leavin' the goldmine with mah pockets full o' sweet gold";
}
2010년 3월 23일 화요일
32. 2. 상태구동형 에이전트의 디자인
DD3440 Mar. 2, 2010
D. 상태의 기본 클래스 재사용할 수 있게 만들기
2010년 3월 23일 화요일
33. 33
D. 상태의 기본 클래스 재사용할 수 있게 만들기
2. 상태구동형 에이전트의 디자인 Mar. 2, 2010
template <class entity_type>
class State
{
public:
virtual void Enter(entity_type*)=0;
virtual void Execute(entity_type*)=0;
virtual void Exit(entity_type*)=0;
virtual ~State(){}
};
2010년 3월 23일 화요일
34. 34
D. 상태의 기본 클래스 재사용할 수 있게 만들기
2. 상태구동형 에이전트의 디자인 Mar. 2, 2010
class EnterMineAndDigForNugget : public State<Miner>
{
public:
/* OMITTED */
};
2010년 3월 23일 화요일
35. 2. 상태구동형 에이전트의 디자인
DD3440 Mar. 2, 2010
F. 전역 상태 및 상태 블립
2010년 3월 23일 화요일
36. 36
F. 전역 상태 및 상태 블립
2. 상태구동형 에이전트의 디자인 Mar. 2, 2010
State<Miner>* m_pGlobalState;
class Miner : public BaseGameEntity
{
private:
State<Miner>* m_pCurrentState;
State<Miner>* m_pPreviousState;
State<Miner>* m_pGlobalState;
...
public:
void ChangeState(State<Miner>* pNewState);
void RevertToPreviousState();
...
};
2010년 3월 23일 화요일
37. 2. 상태구동형 에이전트의 디자인
DD3440 Mar. 2, 2010
G. 상태기계 클래스 생성하기
2010년 3월 23일 화요일
38. 38
G. 상태기계 클래스 생성하기
2. 상태구동형 에이전트의 디자인 Mar. 2, 2010
template <class entity_type>
class StateMachine
{
private:
entity_type* m_pOwner;
State<entity_type>* m_pCurrentState;
State<entity_type>* m_pPreviousState;
State<entity_type>* m_pGlobalState;
public:
StateMachine(entity_type* owner):m_pOwner(owner),
m_pCurrentState(NULL),
m_pPreviousState(NULL),
m_pGlobalState(NULL)
{}
2010년 3월 23일 화요일
39. 39
G. 상태기계 클래스 생성하기
2. 상태구동형 에이전트의 디자인 Mar. 2, 2010
virtual ~StateMachine(){}
void SetCurrentState(State<entity_type>* s){m_pCurrentState = s;}
void SetGlobalState(State<entity_type>* s) {m_pGlobalState = s;}
void SetPreviousState(State<entity_type>* s){m_pPreviousState = s;}
void Update()const
{
if(m_pGlobalState) m_pGlobalState->Execute(m_pOwner);
if (m_pCurrentState) m_pCurrentState->Execute(m_pOwner);
}
2010년 3월 23일 화요일
40. 40
G. 상태기계 클래스 생성하기
2. 상태구동형 에이전트의 디자인 Mar. 2, 2010
void ChangeState(State<entity_type>* pNewState)
{
assert(pNewState &&
"<StateMachine::ChangeState>: trying to change to NULL state");
m_pPreviousState = m_pCurrentState;
m_pCurrentState->Exit(m_pOwner);
m_pCurrentState = pNewState;
m_pCurrentState->Enter(m_pOwner);
}
void RevertToPreviousState()
{
ChangeState(m_pPreviousState);
}
2010년 3월 23일 화요일
41. 41
G. 상태기계 클래스 생성하기
2. 상태구동형 에이전트의 디자인 Mar. 2, 2010
bool isInState(const State<entity_type>& st)const
{
return typeid(*m_pCurrentState) == typeid(st);
}
State<entity_type>* CurrentState() const{return m_pCurrentState;}
State<entity_type>* GlobalState() const{return m_pGlobalState;}
State<entity_type>* PreviousState() const{return m_pPreviousState;}
};
2010년 3월 23일 화요일
42. 42
G. 상태기계 클래스 생성하기
2. 상태구동형 에이전트의 디자인 Mar. 2, 2010
class Miner : public BaseGameEntity
{
private:
StateMachine<Miner>* m_pStateMachine;
/* EXTRANEOUS DETAIL OMITTED */
public:
Miner(int id):m_Location(shack), m_iGoldCarried(0), m_iMoneyInBank(0),
m_iThirst(0), m_iFatigue(0), BaseGameEntity(id)
{
m_pStateMachine = new StateMachine<Miner>(this);
m_pStateMachine->SetCurrentState(GoHomeAndSleepTilRested::Instance());
m_pStateMachine->SetGlobalState(MinerGloalState::Instance());
}
2010년 3월 23일 화요일
43. 43
G. 상태기계 클래스 생성하기
2. 상태구동형 에이전트의 디자인 Mar. 2, 2010
~Miner(){delete m_pStateMachine;}
void Update()
{
++m_iThirst;
m_pStateMachine->Update();
}
StateMachine<Miner>* GetFSM()const{return m_pStateMachine;}
/* EXTRANEOUS DETAIL O<ITTED */
};
2010년 3월 23일 화요일
44. 44
G. 상태기계 클래스 생성하기
2. 상태구동형 에이전트의 디자인 Mar. 2, 2010
2010년 3월 23일 화요일
45. 45
G. 상태기계 클래스 생성하기
2. 상태구동형 에이전트의 디자인 Mar. 2, 2010
2010년 3월 23일 화요일
46. 2. 상태구동형 에이전트의 디자인
DD3440 Mar. 2, 2010
H. Elsa 소개하기
2010년 3월 23일 화요일
47. 47
H. Elsa 소개하기
2. 상태구동형 에이전트의 디자인 Mar. 2, 2010
2010년 3월 23일 화요일
48. 2. 상태구동형 에이전트의 디자인
DD3440 Mar. 2, 2010
I. FSM 메시지 처리기능 추가하기
I1. 전보구조
I2. 광부 Bob과 Elsa의 통신
I3. 메시지 급송 및 관리
I4. 메시지 처리하기
I5. Elsa는 저녁을 준비한다
2010년 3월 23일 화요일
49. 49
I1. 전보구조
2. 상태구동형 에이전트의 디자인 Mar. 2, 2010
struct Telegram
{
int Sender;
int Receiver;
int Msg;
double DispatchTime;
void* ExtraInfo;
/* CONSTRUCTORS OMITTED */
};
2010년 3월 23일 화요일
50. 2. 상태구동형 에이전트의 디자인
DD3440 Mar. 2, 2010
I. FSM 메시지 처리기능 추가하기
I1. 전보구조
I2. 광부 Bob과 Elsa의 통신
I3. 메시지 급송 및 관리
I4. 메시지 처리하기
I5. Elsa는 저녁을 준비한다
2010년 3월 23일 화요일
51. 51
I2. 광부 Bob과 Elsa의 통신
2. 상태구동형 에이전트의 디자인 Mar. 2, 2010
enum message_type
{
Msg_HiHoneyImHome,
Msg_StewReady
};
2010년 3월 23일 화요일
52. 2. 상태구동형 에이전트의 디자인
DD3440 Mar. 2, 2010
I. FSM 메시지 처리기능 추가하기
I1. 전보구조
I2. 광부 Bob과 Elsa의 통신
I3. 메시지 급송 및 관리
I4. 메시지 처리하기
I5. Elsa는 저녁을 준비한다
2010년 3월 23일 화요일
53. 53
I3. 메시지 급송 및 관리
2. 상태구동형 에이전트의 디자인 Mar. 2, 2010
class EntityManager
{
private:
typedef std::map<int, BaseGameEntity*> EntityMap;
private:
EntityMap m_EntityMap;
EntityManager(){}
EntityManager(const EntityManager&);
EntityManager& operator=(const EntityManager&);
2010년 3월 23일 화요일
54. 54
I3. 메시지 급송 및 관리
2. 상태구동형 에이전트의 디자인 Mar. 2, 2010
public:
static EntityManager* Instance();
void RegisterEntity(BaseGameEntity* NewEntity);
BaseGameEntity* GetEntityFromID(int id)const;
void RemoveEntity(BaseGameEntity* pEntity);
};
#define EntityMgr EntityManager::Instance()
Miner* Bob = new Miner(ent_Miner_Bob); //enumerated ID
EntityMgr->RegisterEntity(Bob);
Entity* pBob = EntityMgr->GetEntityFromID(ent_Miner_Bob);
2010년 3월 23일 화요일
55. 55
I3. 메시지 급송 및 관리
2. 상태구동형 에이전트의 디자인 Mar. 2, 2010
๏ MessageDispatcher 클래스
class MessageDispatcher
{
private:
std::set<Telegram> PriorityQ;
void Discharge(BaseGameEntity* pReceiver, const Telegram& msg);
MessageDispatcher(){}
public:
static MessageDispatcher* Instance();
void DispatchMessage(double delay, int sender, int receiver,
int msg, void* ExtraInfo);
void DispatchDelayedMessages();
};
#define Dispatch MessageDispatcher::Instance()
2010년 3월 23일 화요일
56. 56
I3. 메시지 급송 및 관리
2. 상태구동형 에이전트의 디자인 Mar. 2, 2010
๏ MessageDispatcher 클래스
void MessageDispatcher::DispatchMessage(double delay,
int sender, int receiver,
int msg, void* ExtraInfo)
{
Entity* pReceiver = EntityMgr->GetEntityFromID(receiver);
Telegram telegram(0, sender, receiver, msg, ExtraInfo);
if (delay <= 0.0f) {
Discharge(pReceiver, telegram);
}
else {
double CurrentTime = Clock->GetCurrentTime();
telegram.DispatchTime = CurrentTime + delay;
PriorityQ.insert(telegram);
}
}
2010년 3월 23일 화요일
57. 57
I3. 메시지 급송 및 관리
2. 상태구동형 에이전트의 디자인 Mar. 2, 2010
๏ MessageDispatcher 클래스
void MessageDispatcher::DispatchDelayedMessages()
{
double CurrentTime = Clock->GetCurrentTime();
while( (PriorityQ.begin()->DispatchTime < CurrentTime) &&
(PriorityQ.begin()->DispatchTime > 0) )
{
Telegram telegram = *PriorityQ.begin();
BaseGameEntity* pReceiver = EntityMgr->GetEntityFromID
(telegram.Receiver);
Discharge(pReceiver, telegram);
PriorityQ.erase(PriorityQ.begin());
}
}
2010년 3월 23일 화요일
58. 2. 상태구동형 에이전트의 디자인
DD3440 Mar. 2, 2010
I. FSM 메시지 처리기능 추가하기
I1. 전보구조
I2. 광부 Bob과 Elsa의 통신
I3. 메시지 급송 및 관리
I4. 메시지 처리하기
I5. Elsa는 저녁을 준비한다
2010년 3월 23일 화요일
59. 59
I4. 메시지 처리하기
2. 상태구동형 에이전트의 디자인 Mar. 2, 2010
class BaseGameEntity
{
private:
int m_ID;
/* EXTRANEOUS DETAIL REMOVED FOR CLARITY*/
public:
virtual bool HandleMessage(const Telegram& msg)=0;
/* EXTRANEOUS DETAIL REMOVED FOR CLARITY*/
};
2010년 3월 23일 화요일
60. 60
I4. 메시지 처리하기
2. 상태구동형 에이전트의 디자인 Mar. 2, 2010
template <class entity_type>
class State
{
public:
virtual bool OnMessage(entity_type*, const Telegram&)=0;
/* EXTRANEOUS DETAIL REMOVED FOR CLARITY*/
};
2010년 3월 23일 화요일
61. 61
I4. 메시지 처리하기
2. 상태구동형 에이전트의 디자인 Mar. 2, 2010
bool StateMachine::HandleMessage(const Telegram& msg)const
{
if (m_pCurrentState && m_pCurrentState->OnMessage(m_pOwner, msg))
{
return true;
}
if (m_pGlobalState && m_pGlobalState->OnMessage(m_pOwner, msg))
{
return true;
}
return false;
}
2010년 3월 23일 화요일
62. 62
I4. 메시지 처리하기
2. 상태구동형 에이전트의 디자인 Mar. 2, 2010
bool Miner::HandleMessage(const Telegram& msg)
{
return m_pStateMachine->HandleMessage(msg);
}
2010년 3월 23일 화요일
63. 63
I4. 메시지 처리하기
2. 상태구동형 에이전트의 디자인 Mar. 2, 2010
2010년 3월 23일 화요일
64. 64
I4. 메시지 처리하기
2. 상태구동형 에이전트의 디자인 Mar. 2, 2010
2010년 3월 23일 화요일
65. 65
I3. 메시지 급송 및 관리
2. 상태구동형 에이전트의 디자인 Mar. 2, 2010
public:
static EntityManager* Instance();
void RegisterEntity(BaseGameEntity* NewEntity);
BaseGameEntity* GetEntityFromID(int id)const;
void RemoveEntity(BaseGameEntity* pEntity);
};
#define EntityMgr EntityManager::Instance()
Miner* Bob = new Miner(ent_Miner_Bob); //enumerated ID
EntityMgr->RegisterEntity(Bob);
Entity* pBob = EntityMgr->GetEntityFromID(ent_Miner_Bob);
2010년 3월 23일 화요일
66. 66
I3. 메시지 급송 및 관리
2. 상태구동형 에이전트의 디자인 Mar. 2, 2010
๏ MessageDispatcher 클래스
class MessageDispatcher
{
private:
std::set<Telegram> PriorityQ;
void Discharge(BaseGameEntity* pReceiver, const Telegram& msg);
MessageDispatcher(){}
public:
static MessageDispatcher* Instance();
void DispatchMessage(double delay, int sender, int receiver,
int msg, void* ExtraInfo);
void DispatchDelayedMessages();
};
#define Dispatch MessageDispatcher::Instance()
2010년 3월 23일 화요일
67. 67
I3. 메시지 급송 및 관리
2. 상태구동형 에이전트의 디자인 Mar. 2, 2010
๏ MessageDispatcher 클래스
void MessageDispatcher::DispatchMessage(double delay,
int sender, int receiver,
int msg, void* ExtraInfo)
{
Entity* pReceiver = EntityMgr->GetEntityFromID(receiver);
Telegram telegram(0, sender, receiver, msg, ExtraInfo);
if (delay <= 0.0f) {
Discharge(pReceiver, telegram);
}
else {
double CurrentTime = Clock->GetCurrentTime();
telegram.DispatchTime = CurrentTime + delay;
PriorityQ.insert(telegram);
}
}
2010년 3월 23일 화요일
68. 68
I3. 메시지 급송 및 관리
2. 상태구동형 에이전트의 디자인 Mar. 2, 2010
๏ MessageDispatcher 클래스
void MessageDispatcher::DispatchDelayedMessages()
{
double CurrentTime = Clock->GetCurrentTime();
while( (PriorityQ.begin()->DispatchTime < CurrentTime) &&
(PriorityQ.begin()->DispatchTime > 0) )
{
Telegram telegram = *PriorityQ.begin();
BaseGameEntity* pReceiver = EntityMgr->GetEntityFromID
(telegram.Receiver);
Discharge(pReceiver, telegram);
PriorityQ.erase(PriorityQ.begin());
}
}
2010년 3월 23일 화요일
69. 2. 상태구동형 에이전트의 디자인
DD3440 Mar. 2, 2010
I. FSM 메시지 처리기능 추가하기
I1. 전보구조
I2. 광부 Bob과 Elsa의 통신
I3. 메시지 급송 및 관리
I4. 메시지 처리하기
I5. Elsa는 저녁을 준비한다
2010년 3월 23일 화요일
70. 70
I5. Elsa는 저녁을 준비한다
2. 상태구동형 에이전트의 디자인 Mar. 2, 2010
๏ 첫번째 단계
void GoHomeAndSleepTilRested::Enter(Miner* pMiner)
{
if (pMiner->Location() != shack)
{
cout << "n" << GetNameOfEntity(pMiner->ID()) << ": " <<
"Walkin' home";
pMiner->ChangeLocation(shack);
//let the wife know I'm home
Dispatch->DispatchMessage(SEND_MSG_IMMEDIATELY, //time delay
pMiner->ID(), //ID of sender
ent_Elsa, //ID of recipient
Msg_HiHoneyImHome, //the message
NO_ADDITIONAL_INFO);
}
}
2010년 3월 23일 화요일
71. 71
I5. Elsa는 저녁을 준비한다
2. 상태구동형 에이전트의 디자인 Mar. 2, 2010
๏ 두번째 단계
bool WifesGlobalState::OnMessage(MinersWife* wife, const Telegram& msg)
{
switch(msg.Msg)
{
case Msg_HiHoneyImHome:
{
cout << "nMessage handled by " << GetNameOfEntity(wife->ID()) <<
" at time: "
<< Clock->GetCurrentTime();
cout << "n" << GetNameOfEntity(wife->ID()) <<
": Hi honey. Let me make you some of mah fine country stew";
wife->GetFSM()->ChangeState(CookStew::Instance());
}
return true;
}//end switch
return false;
}
2010년 3월 23일 화요일
72. 72
I5. Elsa는 저녁을 준비한다
2. 상태구동형 에이전트의 디자인 Mar. 2, 2010
๏ 세번째 단계
void CookStew::Enter(MinersWife* wife)
{
//if not already cooking put the stew in the oven
if (!wife->Cooking())
{
cout << "n" << GetNameOfEntity(wife->ID()) <<
": Putting the stew in the oven";
Dispatch->DispatchMessage(1.5, //time delay
wife->ID(), //sender ID
wife->ID(), //receiver ID
Msg_StewReady, //msg
NO_ADDITIONAL_INFO);
wife->SetCooking(true);
}
}
2010년 3월 23일 화요일
73. 73
I5. Elsa는 저녁을 준비한다
2. 상태구동형 에이전트의 디자인 Mar. 2, 2010
๏ 네번째 단계
bool CookStew::OnMessage(MinersWife* wife, const Telegram& msg)
{
switch(msg.Msg) {
case Msg_StewReady: {
cout << "nMessage received by " << GetNameOfEntity(wife->ID()) << " at time: "
<< Clock->GetCurrentTime();
SetTextColor(FOREGROUND_GREEN|FOREGROUND_INTENSITY);
cout << "n" << GetNameOfEntity(wife->ID()) << ": StewReady! Lets eat";
Dispatch->DispatchMessage(SEND_MSG_IMMEDIATELY, wife->ID(), ent_Miner_Bob,
Msg_StewReady, NO_ADDITIONAL_INFO);
wife->SetCooking(false);
wife->GetFSM()->ChangeState(DoHouseWork::Instance());
}
return true;
}//end switch
return false;
}
2010년 3월 23일 화요일
74. 74
I5. Elsa는 저녁을 준비한다
2. 상태구동형 에이전트의 디자인 Mar. 2, 2010
๏ 다섯 번째 단계
bool GoHomeAndSleepTilRested::OnMessage(Miner* pMiner, const Telegram& msg)
{
switch(msg.Msg)
{
case Msg_StewReady:
cout << "nMessage handled by " << GetNameOfEntity(pMiner->ID())
<< " at time: " << Clock->GetCurrentTime();
cout << "n" << GetNameOfEntity(pMiner->ID())
<< ": Okay Hun, ahm a comin'!";
pMiner->GetFSM()->ChangeState(EatStew::Instance());
return true;
}//end switch
return false; //send message to global message handler
}
2010년 3월 23일 화요일