最近在看老大的写的框架,觉得他有很多地方值我学习.尤其是他的那个消息机制,做得非常妙.
以前在做角色漫游那个模块时,注意到在那个模块的那个模块的manager的init中调用setRunning(this , priority) ,就可以把这个整个模块挂载到游戏循环中运行,调用setMessage(this , XX_MSG) ,就可以接受其他的游戏模块传过来的消息.这个消息可以是系统消息,服务器消息,还有自定义消息.一直都很好奇他是如何实现的.直到看了他的整个代码,才恍然大悟.
昨天晚上,根据自己的理解也写了一个简单的例子,用来模拟不同模块消息通信.代码如下:
1
/**//********************************************************************
2
created: 2008/12/28
3
created: 28:12:2008 13:51
4
filename: e:\MyProject\vs2005\MessageTransfer\MessageTransfer\Env.h
5
file path: e:\MyProject\vs2005\MessageTransfer\MessageTransfer
6
file base: Env
7
file ext: h
8
author: coast
9
10
purpose: 环境类,用来管理所有的实体和负责消息的转发
11
*********************************************************************/
12
#ifndef _ENV_H_
13
#define _ENV_H_
14
#include <map>
15
#include <vector>
16
#include <list>
17
#include "Entity.h"
18
#include "Msg.h"
19
using namespace MSG;
20
21
enum Run_PRI
22

{
23
//running 函数调用的优先级
24
PRI_1 ,
25
PRI_2 ,
26
};
27
28
29
class Env
30

{
31
//单件
32
public :
33
~Env()
34
{
35
ENT_LIST::iterator it ;
36
for (it = m_entRun.begin() ; it != m_entRun.end() ;)
37
{
38
if (*it != NULL)
39
{
40
it = m_entRun.erase(it) ;
41
delete *it ;
42
}
43
else
44
{
45
++it ;
46
}
47
48
}
49
50
for (int i = 0 ;i < MAX_MSG ; ++i)
51
{
52
m_entMsg[i].erase(m_entMsg[i].begin() , m_entMsg[i].end()) ;
53
}
54
55
if(m_sEnv != NULL)
56
{
57
delete m_sEnv ;
58
}
59
};
60
static Env *getSingletonPtr()
61
{
62
if (m_sEnv == NULL)
63
{
64
m_sEnv = new Env() ;
65
}
66
return m_sEnv ;
67
}
68
69
void rigesterMessage(unsigned int msgId , Entity *ent) ;
70
71
void procMessage() ;
72
73
void rigesterRunning(unsigned int priority , Entity *ent) ;
74
75
void procRunning() ;
76
77
void sendMessage(unsigned int msgId ,void *pData) ;
78
private:
79
//防止使用默认构造函数
80
Env()
81
{
82
//memset(ent_Msg ,0 ,sizeof(ENT_VEC) * MAX_MSG) ;
83
};
84
private:
85
struct Ent_PRI
86
{
87
unsigned int priority ;
88
Entity *ent ;
89
};
90
static Env *m_sEnv ;
91
typedef std::vector<Entity *> ENT_VEC;
92
ENT_VEC m_entMsg[MSG::MAX_MSG] ;
93
typedef std::list<Ent_PRI *> ENT_LIST ;
94
ENT_LIST m_entRun ;
95
};
96
#endif

/**//********************************************************************
created: 2008/12/28
created: 28:12:2008 14:09
filename: e:\MyProject\vs2005\MessageTransfer\MessageTransfer\Entity.h
file path: e:\MyProject\vs2005\MessageTransfer\MessageTransfer
file base: Entity
file ext: h
author: coast

purpose: 实体接口,一个模块就是一个实体.
*********************************************************************/

#ifndef _ENTITY_H_
#define _ENTITY_H_
class Entity


{
public:

virtual void init () = 0;

virtual void runing() = 0 ;

virtual void message(unsigned int msgId , void *pData) = 0 ;

};

#endif

/**//********************************************************************
created: 2008/12/28
created: 28:12:2008 14:15
filename: e:\MyProject\vs2005\MessageTransfer\MessageTransfer\Ent.h
file path: e:\MyProject\vs2005\MessageTransfer\MessageTransfer
file base: Ent
file ext: h
author: coast
purpose: 定义几个实体
*********************************************************************/

#ifndef _ENT_H_
#define _ENT_H_

#include "Entity.h"

class Ent1 : public Entity


{
public :
void init() ;
void runing() ;
void message(unsigned int msgId , void *pData) ;
private:
//member variable
};

class Ent2 : public Entity


{
public :
void init() ;
void runing() ;
void message(unsigned int msgId , void *pData) ;
private:
//member variable
};

class Ent3 : public Entity


{
public :
void init() ;
void runing() ;
void message(unsigned int msgId , void *pData) ;
private:
//member variable
};

#endif

/**//********************************************************************
created: 2008/12/28
created: 28:12:2008 14:20
filename: e:\MyProject\vs2005\MessageTransfer\MessageTransfer\Msg.h
file path: e:\MyProject\vs2005\MessageTransfer\MessageTransfer
file base: Msg
file ext: h
author: coast
purpose: 定义消息和消息数据
*********************************************************************/
#ifndef _MSG_H_
#define _MSG_H_
#include <string>
using namespace std;
namespace MSG


{
enum MSG_ID

{
ID_MSG_1 = 0 ,
ID_MSG_2 ,
ID_MSG_3 ,
MAX_MSG ,
};

struct MSG_0

{
string strSender ;//sender name
};

const unsigned int MSG_1 = ID_MSG_1 ;
struct MSG_1_Data :public MSG_0

{
//data
};


const unsigned int MSG_2 = ID_MSG_2 ;
struct MSG_2_Data :public MSG_0

{
//data
};

const unsigned int MSG_3 = ID_MSG_3 ;
struct MSG_3_Data :public MSG_0

{
//data
};

}
#endif

/**//********************************************************************
created: 2008/12/28
created: 28:12:2008 14:34
filename: e:\MyProject\vs2005\MessageTransfer\MessageTransfer\Env.cpp
file path: e:\MyProject\vs2005\MessageTransfer\MessageTransfer
file base: Env
file ext: cpp
author: coast
purpose:
*********************************************************************/
#include "Env.h"
#include <iostream>
using namespace std ;
Env *Env::m_sEnv = NULL ;

void Env::procMessage()


{

/**//*for (int i = 0 ; i < MAX_MSG ; ++i)
{

}*/
}

void Env::sendMessage(unsigned int msgId, void *pData)


{
if (m_entMsg[msgId].empty())

{
cout<<"error"<<endl ;
}
else

{
ENT_VEC::iterator it ;
for (it = m_entMsg[msgId].begin() ; it != m_entMsg[msgId].end() ; ++it)

{
(*it)->message(msgId ,pData) ;
}
}
}

void Env::rigesterMessage(unsigned int msgId , Entity *ent)


{
ENT_VEC::iterator it ;
for (it = m_entMsg[msgId].begin() ; it != m_entMsg[msgId].end() ; ++it)

{
if ((*it) == ent)

{
return ;
}
}

m_entMsg[msgId].push_back(ent) ;
}

void Env::rigesterRunning(unsigned int priority, Entity *ent)


{
Ent_PRI *pEntPRI = new Ent_PRI();
pEntPRI->ent = ent ;
pEntPRI->priority = priority ;
if (m_entRun.empty())

{
m_entRun.push_back(pEntPRI) ;
}
else

{
ENT_LIST::iterator it ;
for (it = m_entRun.begin() ; it != m_entRun.end() ; ++it)

{
if ( priority > (*it)->priority)

{
m_entRun.insert(it,pEntPRI) ;
return ;
}
}
m_entRun.push_back(pEntPRI) ;
}
}

void Env::procRunning()


{
ENT_LIST::iterator it ;
for (it = m_entRun.begin() ; it != m_entRun.end() ; ++it)

{
(*it)->ent->runing() ;
}
}

/**//********************************************************************
created: 2008/12/28
created: 28:12:2008 14:32
filename: e:\MyProject\vs2005\MessageTransfer\MessageTransfer\Ent.cpp
file path: e:\MyProject\vs2005\MessageTransfer\MessageTransfer
file base: Ent
file ext: cpp
author: coast
purpose:
*********************************************************************/

#include "Ent.h"
#include "Env.h"
#include <iostream>
#include <assert.h>
using namespace std;
using namespace MSG ;

void Ent1::init()


{
//注册消息,表明ent1有接收MSG1和MSG2的权限
Env::getSingletonPtr()->rigesterMessage(MSG_1 , this ) ;
Env::getSingletonPtr()->rigesterMessage(MSG_2 , this ) ;

//注册running函数,表明ent1有执行running函数的权限,优先级为2
Env::getSingletonPtr()->rigesterRunning(PRI_2 ,this ) ; //
}

void Ent1::message(unsigned int msgId, void *pData)


{
assert(pData) ;

//接收消息,并作相应的处理
switch (msgId)

{
case MSG_1 :

{
MSG_1_Data *pD1 = (MSG_1_Data *) pData ;
cout<<"Ent1 received message MSG_1 , " ;
cout<<"this message from "<<pD1->strSender<<endl ;
break ;
}
case MSG_2 :

{
MSG_2_Data *pD2 = (MSG_2_Data *) pData ;
cout<<"Ent1 received message MSG_2 ," ;
cout<<"this message from "<<pD2->strSender<<endl ;
break ;
}
}
}

void Ent1::runing()


{
int n ;
cout<<"it's turned ent1 :"<<endl ;
cin >> n ;
if (n == 3)

{
MSG_3_Data data ;
data.strSender = "ent1" ;
Env::getSingletonPtr()->sendMessage(MSG_3 ,(void *)&data) ;//发送消息MSG_3.
}
}


void Ent2::init()


{
//注册running函数,表明ent2有执行running函数的权限,优先级为1
Env::getSingletonPtr()->rigesterRunning(PRI_1 ,this) ;
//注册消息,表明ent2有接收MSG3的权限
Env::getSingletonPtr()->rigesterMessage(MSG_3 ,this) ;
}

void Ent2::message(unsigned int msgId, void *pData)


{
assert(pData) ;
//接收消息,并作相应的处理
switch (msgId)

{
case MSG_3 :
MSG_3_Data *pD = (MSG_3_Data *) pData ;
cout<<"Ent2 received message MSG_3 , " ;
cout<<"this message from "<<pD->strSender<<endl ;
break ;
}
}

void Ent2::runing()


{
int n ;
cout<<"it's turned ent2 :"<<endl ;
cin >> n ;
if (n == 1)

{
MSG_1_Data data ;
data.strSender = "ent2" ;
Env::getSingletonPtr()->sendMessage(MSG_1 ,(void *)&data) ;//发送消息MSG_1.
}
else if (n == 2)

{
MSG_2_Data data ;
data.strSender = "ent2" ;
Env::getSingletonPtr()->sendMessage(MSG_2, (void *)&data) ;//发送消息MSG2.
}
else if (n == 3)

{
//ent2可以接收MSG_3,向自己发送消息没意义
}
}


void Ent3::init()


{
//注册消息,表明ent3有接收MSG_1,MSG_2,MSG3的权限
Env::getSingletonPtr()->rigesterMessage(MSG_1 ,this) ;
//Env::getSingletonPtr()->rigesterMessage(MSG_3 ,this) ;//取消ent3接收MSG的权限
Env::getSingletonPtr()->rigesterMessage(MSG_2 ,this) ;
}

void Ent3::message(unsigned int msgId, void *pData)


{
//接收消息,并作相应的处理
switch (msgId)

{
case MSG_1 :

{
MSG_1_Data *pD1 = (MSG_1_Data *) pData ;
cout<<"Ent3 received message MSG_1 , " ;
cout<<"this message from "<<pD1->strSender<<endl ;
break ;
}
case MSG_2 :

{
MSG_2_Data *pD2 = (MSG_2_Data *) pData ;
cout<<"Ent3 received message MSG_2 ," ;
cout<<"this message from "<<pD2->strSender<<endl ;
break ;
}
case MSG_3 :

{
MSG_3_Data *pD3 = (MSG_3_Data *) pData ;
cout<<"Ent3 received message MSG_3 , " ;
cout<<"this message from "<<pD3->strSender<<endl ;
break ;
}
}
}

void Ent3::runing()


{
//ent3 没有注册running函数,所以running函数不会运行.
cout<<"it's turned ent3 ?"<<endl;
}

/**//********************************************************************
created: 2008/12/30
created: 30:12:2008 22:49
filename: e:\MyProject\vs2005\MessageTransfer\MessageTransfer\test.cpp
file path: e:\MyProject\vs2005\MessageTransfer\MessageTransfer
file base: test
file ext: cpp
author: coast
purpose:
*********************************************************************/
#include "Env.h"
#include "Ent.h"
#include <iostream>
using namespace std;


int main()


{
Ent1 *ent1 = new Ent1() ;
ent1->init() ;
Ent2 *ent2 = new Ent2() ;
ent2->init() ;
Ent3 *ent3 = new Ent3() ;
ent3->init() ;

bool done = true ;
int c ;
while(done)

{
Env::getSingletonPtr()->procRunning() ;
cout<<"quit?"<<endl;
cin>>c ;
if ( c == 0)

{
done = false ;
}
}

delete ent1 ;
delete ent2 ;
delete ent3 ;
return 0 ;
}
posted on 2008-12-30 22:55
隙中驹 阅读(410)
评论(0) 编辑 收藏 引用