最近在看老大的写的框架,觉得他有很多地方值我学习.尤其是他的那个消息机制,做得非常妙.
以前在做角色漫游那个模块时,注意到在那个模块的那个模块的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"
19using namespace MSG;
20
21enum Run_PRI
22{
23 //running 函数调用的优先级
24 PRI_1 ,
25 PRI_2 ,
26};
27
28
29class Env
30{
31 //单件
32public :
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) ;
78private:
79 //防止使用默认构造函数
80 Env()
81 {
82 //memset(ent_Msg ,0 ,sizeof(ENT_VEC) * MAX_MSG) ;
83 };
84private:
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
隙中驹 阅读(405)
评论(0) 编辑 收藏 引用