游戏服务器引擎开发笔记之三——游戏服务器引擎和逻辑的功能的相互调用(二)
来源:互联网 发布:云计算 中国科学院 编辑:程序博客网 时间:2024/04/29 03:36
其实很早就想将代码贴出来,一直都在想服务器的讲解可能比较枯燥。
有时间的话,也可以先看看设计模式之类的,比如一些通用的Factory模式,Adapter模式,了解了解。
其他的也不多说。先贴代码,做做简单的说明。
上一章讲述了IModule和IModuleFactory的实现,这里就不多讲。现在有一个关键的地方,就是我们在实现相应逻辑功能的时候,不可能只写一个逻辑功能模块。这时候我们就需要使用相应的ModuleFactory来创建对象实例。
IModuleFactory重写一遍:
class IModuleFactory{public:IModuleFactory(IModuleFactory * next){m_pNext = next;m_pModule = 0;};virtual ~IModuleFactory(){if (m_pModule != 0){m_pModule->Shutdown();delete m_pModule;}};virtual const char * Name() = 0;virtual IModule * Create() = 0;IModuleFactory * Next() { return m_pNext; }IModule * GetModule() { return m_pModule; }bool Created() { return m_pModule != 0; }protected:IModuleFactory *m_pNext;IModule *m_pModule;};
通过链表的形式,只需要得到第一个ModuleFactory,我们就能得到所有的ModuleFactory,然后创建出所有Module的实例了。
下面使用宏来替换相应的ModuleFactory:
// 这里需要关注一下##和#的用法#define CREATE_MODULE(a) \class a##ModuleFactory: public IModuleFactory \{\public: \a##ModuleFactory(IModuleFactory * & p): IModuleFactory(p) { p = this; } \virtual ~##a##ModuleFactory() {} \virtual IModule * Create() { if (m_pModule == 0) {m_pModule = new a;} return m_pModule; } \virtual const char * Name() { return #a; } \}; \a##ModuleFactory a##ModuleFactory(g_pModuleFactory);
在此说明一下,#把宏参数变为一个字符串,用##把两个宏参数贴合在一起。具体的用法各位可以上百度或者写个小程序测试一下。
为了好看和代码编写简单,我们将DLL的函数导出也用宏定义一下:#define BEGIN_MODULES \extern "C" __declspec(dllexport)\IModuleFactory * g_pModuleFactory = 0;\extern "C" __declspec(dllexport)\IModuleFactory * __cdecl GetModuleFactory()\{\return g_pModuleFactory;\}
首先我们需要一个class来管理游戏引擎的操作,我们将它命名为GameWorld:
class CGameWorld{public:CGameWorld(const char *path);virtual ~CGameWorld();public:CKernel* GetKernel(){return m_pKernel;}CModuleSet* GetModuleSet(){return m_pModuleSet;}public:bool Begin();bool Shutdown();private:CKernel* m_pKernel;CModuleSet* m_pModuleSet;private:char m_path[MAX_PATH];};它里面有两个成员,Kernel就是我所定义的引擎指针,ModuleSet是负责管理逻辑模块的功能。
我们先看ModuleSet:
class CModuleSet{public:CModuleSet();CModuleSet(const CModuleSet &other);virtual ~CModuleSet();public://初始化bool Initialize(CKernel * pKernel);//查找模块IModule * FindModule(const char * module);//释放模块bool Shutdown();//////////////////////////////////////////////////////////////////////////public://加载模块bool Create(const char * module);protected:typedef map<string, IModule*> MapModule;private:MapModule m_mapModule;typedef IModuleFactory * (*GetModuleFactory)(); //宏定义函数指针类型 };看到后面有一个typedef了吗,GetModuleFactory是不是很熟悉,在哪见过呢?
IModuleFactory * __cdecl GetModuleFactory()\{\return g_pModuleFactory;\}就是它了,我们能通过它,得到函数地址,然后就能够得到ModuleFactory的指针,再然后就能创建Module的实例。
一切就是这么简单,但是没办法,还是需要一步步的讲解,首先是ModuleSet的构造和析构函数:
CModuleSet::CModuleSet(){}CModuleSet::CModuleSet(const CModuleSet &other){ m_mapModule = other.m_mapModule;}CModuleSet::~CModuleSet(){}这个有点浪费篇幅了,我也觉得,下面就是过去指针创建实例的地方了:
//加载模块bool CModuleSet::Create(const char * module){HINSTANCE hDll = NULL; //DLL句柄 hDll = LoadLibrary(module); if (hDll == NULL) {return false;}GetModuleFactory modulefactory; //函数指针 modulefactory = (GetModuleFactory)GetProcAddress(hDll, "GetModuleFactory"); IModuleFactory * pCreator = (*modulefactory)();if (pCreator == NULL) { FreeLibrary(hDll);} //保存Moduledo {IModule * p = pCreator->Create();string name = pCreator->Name();m_mapModule.insert(make_pair(name, p));pCreator = pCreator->Next();} while (pCreator != NULL);return true;}关于应用程序调用DLL的地方,有不熟悉的,可以去找找相关资料。
主要是3个函数LoadLibrary、FreeLibrary、GetProcAddress。
Module的初始化和释放:
//初始化bool CModuleSet::Initialize(CKernel * pKernel){for (MapModule::iterator it = m_mapModule.begin();it != m_mapModule.end();++it){if (!it->second->Initialize((IKernel*)pKernel)){return false;}}return true;}//释放模块bool CModuleSet::Shutdown(){for (MapModule::iterator it = m_mapModule.begin();it != m_mapModule.end();++it){if (!it->second->Shutdown()){return false;}}return true;}查找模块:
//查找模块IModule * CModuleSet::FindModule(const char * module){MapModule::iterator it = m_mapModule.find(module);if (it != m_mapModule.end()){return it->second;}return NULL;}下面我们讲讲提供给逻辑层调用的引擎接口:
class CKernel : IKernel{public:CKernel();virtual ~CKernel();public:// 显示virtual void Print(const char * info);// 获取其他逻辑模块地址virtual IModule *GetModule(const char * name);};这里面我只写了2个接口,其中一个Print是为了抛砖引玉,能实现它,自然也就能实现其他的接口。
另外一个是获得其他逻辑模块的地址,这样的话我们就能够实现引擎和逻辑、逻辑和逻辑之间的相会调用了。
下面的是实现代码:
extern CGameWorld *g_pGameWorld;CKernel::CKernel() {}CKernel::~CKernel(){}// void CKernel::Print(const char * info){printf("%s", info);}// IModule *CKernel::GetModule(const char * name){return g_pGameWorld->GetModuleSet()->FindModule(name);}到此,GameWorld的两个成员就都实现完了,我们再来看看GameWorld的实现。
先是构造和析构:
CGameWorld::CGameWorld(const char *path){m_pKernel= NULL;m_pModuleSet= NULL;strcpy(m_path, path);}CGameWorld::~CGameWorld(){delete m_pKernel;delete m_pModuleSet;}Begin和Shutdown的实现:
bool CGameWorld::Begin(){m_pKernel = new CKernel();m_pModuleSet = new CModuleSet();// 加载dll,这里只加载了一个,抛砖引玉只用// 主要讲解并不在这里,有兴趣的可以加载多个dllchar dll[MAX_PATH] = {0};if (!m_path || strlen(m_path) == 0){return false;}size_t index = strlen(m_path) - 1;while (index >= 0){if (m_path[index] == '\\'){break;}index--;}strncpy(dll, m_path, index + 1);strcat(dll, "Logic.dll");m_pModuleSet->Create(dll);// 断点跟进就能看到如何相互调用,包括引擎和逻辑间调用,逻辑和逻辑间调用m_pModuleSet->Initialize(m_pKernel);return true;}bool CGameWorld::Shutdown(){m_pModuleSet->Shutdown();return true;}
我们再来看看main函数:
CGameWorld * g_pGameWorld = 0;int main(int argc, char* argv[]){g_pGameWorld = new CGameWorld(argv[0]);g_pGameWorld->Begin();// 这里可以使用scanf或其他通过读字符串的操作,通过输入命令来break,随意发挥while (true){Sleep(1000);}g_pGameWorld->Shutdown();delete g_pGameWorld;return 0;}引擎的代码就到这里了,逻辑DLL的代码可以通过下面的链接下载之后看一下。只是实现了Print和GetModule的调用。
在vs2005下编译并且调试通过。
说完这一章,其实应该明白了逻辑功能个引擎之间的调用,后面的只要讲解都会是关于引擎的实现,有可能讲解的篇幅太长,一个功能分为几个篇章讲解。代码并不太会频繁提供源码下载,主要是一些想法的东西和文章中将代码贴出。不过在一个完整的功能讲完之后都会有编译通过的的源码提供。
本章源码下载地址:
http://download.csdn.net/detail/abc2258/5455659
- 游戏服务器引擎开发笔记之三——游戏服务器引擎和逻辑的功能的相互调用(二)
- 游戏服务器引擎开发笔记之二——游戏服务器引擎和逻辑的功能的相互调用(一)
- 游戏服务器引擎开发笔记之一——游戏服务器引擎的功能简介
- 一款免费开源的游戏服务器引擎—Scut
- 一款免费开源的游戏服务器引擎—Scut
- 游戏服务器需要什么样的引擎?
- 游戏引擎的开发
- 游戏服务器引擎设计
- 游戏服务器引擎设计
- 游戏服务器引擎实现
- 游戏服务器引擎~
- Scut游戏服务器引擎之Unity3d接入
- Scut游戏服务器引擎之新手入门
- Scut游戏服务器引擎之Unity3d接入
- j2me游戏引擎——游戏引擎的基本构
- Unity3D 游戏引擎之详解游戏开发音频的播放
- Android开发_libgdx游戏引擎教程 性能优良的游戏引擎—libgdx (五)
- MMO 游戏服务器引擎设计
- 按层次/广度遍历二叉树
- ubuntu13.04-gnome体验及相关配置
- 【学习笔记】《卓有成效的管理者》 第四章 如何发挥人的长处
- leetcode Subsets II problem
- javascript各进制数据与十进制之间的转换
- 游戏服务器引擎开发笔记之三——游戏服务器引擎和逻辑的功能的相互调用(二)
- 基本文件IO的实现
- 第十三周项目四——Date类,Time类,多继承的DateTime类
- svn在windows下的搭建
- poj-3159,SPFA+堆栈
- WP8调用WebService或WCF时遇到的问题及解决方案
- metasploit针对性钓鱼攻击向量(BT5R1失败)
- Windows Phone(WP)从此开始!
- GWT 实现文件上传和下载