从零开始编写网络游戏基础篇.docx
- 文档编号:29121860
- 上传时间:2023-07-20
- 格式:DOCX
- 页数:22
- 大小:23.42KB
从零开始编写网络游戏基础篇.docx
《从零开始编写网络游戏基础篇.docx》由会员分享,可在线阅读,更多相关《从零开始编写网络游戏基础篇.docx(22页珍藏版)》请在冰豆网上搜索。
从零开始编写网络游戏基础篇
从零开始编写网络游戏---基础篇
(1)
昌高杨.于星期四,07/11/2013-00:
01提交
最近2周比较忙,没有抽出时间来写Blog,不过在这段时间里面把整个思路理了一遍,梳理了一下大纲,以后会多抽时间来写Blog。
好了,言归正传,做任何事情都需要一定的基础,没有坚实的地基,是不可能建立雄伟的大厦的。
所以我在整个系列博文的最前面,把一些最基础的东西先整理出来,为后面的系统做铺垫。
本篇的内容,会介绍几个内容:
单例,dll动态加载以及一些跨平台的处理。
1、单例:
单例模式是一种使用广泛而又比较简单的设计模式,他的定义我就不多介绍了,大家上网一查就知道了,基本都能理解。
在游戏开发中,会有很多单件,所以封装一个单例类供后面的开发使用。
本单例使用模板实现,代码如下:
[cpp]viewplaincopyprint?
1.//singleton.h
2.#ifndef _SINGLETON_H
3.#define _SINGLETON_H
4.
5.namespace Blaze
6.{
7. template
8. class Singleton
9. {
10. public:
11. static T* instance()
12. {
13. if (!
_instance)
14. {
15. _instance = new T;
16. }
17. return _instance;
18. }
19.
20. protected:
21. /// 使用保护构造是为了用户不能在栈上声明一个实例
22. Singleton() {}
23.
24. private:
25. static T* _instance; /// 实例静态指针
26. };
27.
28. /// 静态实例指针初始化
29. template
:
_instance = NULL;
30.
31.} // namespace
32.
33.#endif //_SINGLETON_H
//singleton.h
#ifndef_SINGLETON_H
#define_SINGLETON_H
namespaceBlaze
{
template
classSingleton
{
public:
staticT*instance()
{
if(!
_instance)
{
_instance=newT;
}
return_instance;
}
protected:
///使用保护构造是为了用户不能在栈上声明一个实例
Singleton(){}
private:
staticT*_instance;///实例静态指针
};
///静态实例指针初始化
template
:
_instance=NULL;
}//namespace
#endif//_SINGLETON_H
[cpp]viewplaincopyprint?
1.//使用的时候只需要单件类继承此模板即可。
2.class Test :
public Singleton
//使用的时候只需要单件类继承此模板即可。
classTest:
publicSingleton
2、dll(so)动态加载
在开发网络游戏的过程中,现在已经不是能够单打独斗的年代了,一款游戏基本上不可能有一个人完成,因此分模块开发成为了必然,各自开发相关的模块,然后组合到一起。
dll就是分模块开发的产物之一,它的加载有动态和静态之分,各有优势,但是由于服务器程序是需要运行在多个平台,而他们又各自有各自的加载方法,为了方便使用,因此我们队加载dll进行了封装。
实现使用模板,非常简单,代码如下
[cpp]viewplaincopyprint?
1.// lib_def.h
2.#ifndef __LIB_DEF_H_
3.#define __LIB_DEF_H_
4.
5.namespace Blaze
6.{
7. // DLL对象创建辅助类
8. template
9. class DllApi
10. {
11. public:
12. static BOOL Load()
13. {
14. if(!
m_h) m_h = :
:
LoadLibrary(szFileName);
15. return m_h !
= NULL;
16. }
17. static void Unload()
18. {
19. if(m_h) :
:
FreeLibrary(m_h);
20. m_h = NULL;
21. }
22. protected:
23. static HMODULE m_h;
24. };
25. template
:
m_h;
26.
27. //库文件前后缀
28.#ifdef WIN32
29. #define __DLL_PREFIX _T("")
30. #define __DLL_SUFFIX _T(".dll")
31.#else
32. #define __DLL_PREFIX _T("lib")
33. #define __DLL_SUFFIX _T(".so")
34.#endif
35.
36. // 声明DLL文件名常量
37.#define DECLARE_DLL_FILE(module) extern "C" const TCHAR* module;
38.
39. // 定义DLL文件名常量
40.#if !
defined(_LIB) && !
defined(_USE_STATIC_LIB)
41. #define DEFINE_DLL_FILE(module) extern "C" const TCHAR* module = _T("./")""__DLL_PREFIX""_T(#module)""__DLL_SUFFIX;
42.#else
43. #define DEFINE_DLL_FILE(module)
44.#endif
45.}
46.
47.#endif
本例中使用了LoadLibrary,是windows的实现方法,在后面平台相关处理中,我会将linux的函数封装一下,和windows同名。
此模板使用方法很简单:
[cpp]viewplaincopyprint?
1.#if defined(_LIB) || defined(_USE_STATIC_LIB) // 静态库版本
2. #ifndef _LUA_ENGINE_API
3. #define _LUA_ENGINE_API IMPORT_API
4. #pragma comment(lib, MAKE_LIB_NAME(LuaEngine))
5. #endif
6.
7. _LUA_ENGINE_API ILuaEngine* GlobalLuaEngine();
8.#else
9. DECLARE_DLL_FILE(LuaEngine);
10. class GlobalLuaEngine :
public DllApi
11. {
12. typedef ILuaEngine* (*CREATE_PROC)();
13. ILuaEngine* m_p;
14. public:
15. GlobalLuaEngine() :
m_p(NULL)
16. {
17. Load();
18. static CREATE_PROC func;
19. if(func == NULL) func = (CREATE_PROC):
:
GetProcAddress(m_h, "GlobalLuaEngine");
20. if(func !
= NULL) m_p = func();
21. }
22. operator ILuaEngine* (){ return m_p; }
23. ILuaEngine* operator ->(){ return m_p; }
24. };
25.#endif
#ifdefined(_LIB)||defined(_USE_STATIC_LIB)//静态库版本
#ifndef_LUA_ENGINE_API
#define_LUA_ENGINE_APIIMPORT_API
#pragmacomment(lib,MAKE_LIB_NAME(LuaEngine))
#endif
_LUA_ENGINE_APIILuaEngine*GlobalLuaEngine();
#else
DECLARE_DLL_FILE(LuaEngine);
classGlobalLuaEngine:
publicDllApi
{
typedefILuaEngine*(*CREATE_PROC)();
ILuaEngine*m_p;
public:
GlobalLuaEngine():
m_p(NULL)
{
Load();
staticCREATE_PROCfunc;
if(func==NULL)func=(CREATE_PROC):
:
GetProcAddress(m_h,"GlobalLuaEngine");
if(func!
=NULL)m_p=func();
}
operatorILuaEngine*(){returnm_p;}
ILuaEngine*operator->(){returnm_p;}
};
#endif
如上面代码所示,LuaEngine是一个dll,我们在加载它的时候,使用了一个额外的类,在他的构造函数里面加载了共享库。
而且在应用级上也与平台无关。
3、跨平台的若干处理
windows的处理相当简单,只是定义一些简单的宏。
[cpp]viewplaincopyprint?
1.// gwindef.h :
windows开发定义文件
2.#ifndef __G_WIN_DEF_H_
3.#define __G_WIN_DEF_H_
4.
5.#include
6.#include
7.#include
8.#include
9.#include
10.#include
11.
12.#define SYS_API WINAPI
13.#define STD_CALL __stdcall
14.#if !
defined(_LIB)
15.#define EXPORT_API extern "C" _declspec(dllexport)
16.#else
17.#define EXPORT_API extern "C"
18.#endif
19.#if !
defined(_LIB) && !
defined(_USE_STATIC_LIB)
20.#define IMPORT_API extern "C" _declspec(dllimport)
21.#else
22.#define IMPORT_API extern "C"
23.#endif
24.
25.#endif // ndef __G_WIN_DEF_H_
而为了开发的时候去除平台无关性,在linux的开发中,我们需要做一些包装,使其在开发过程中和window代码一致。
[cpp]viewplaincopyprint?
1.// glindef.h :
linux开发定义文件
2.#ifndef __G_LIN_DEF_H_
3.#define __G_LIN_DEF_H_
4.//
5.#include
6.#include
7.#include
8.#include
9.#include
10.#include
11.#include
12.#include
13.#include
14.#include
15.#include
16.#include
17.#include
18.
19.inline _syscall0(pid_t, gettid) /* Using syscall
(2) may be preferable; see intro
(2) */
20.
21.#ifdef UNICODE
22.#define _T(str) L##str
23.#else
24.#define _T(str) str
25.#endif
26.
27.#define TRUE 1
28.#define FALSE 0
29.
30.#define MAX_PATH 256
31.
32.#define SYS_API
33.#define STD_CALL
34.#define EXPORT_API extern "C"
35.#define IMPORT_API extern "C"
36.
37./// HRESULT 常量定义
38.typedef long HRESULT;
39.enum HResult
40.{
41. S_OK = ((HRESULT)0x00000000), /**< 成功,值为0 */
42. S_FALSE = ((HRESULT)0x00000001), /**< 成功,但值为1 */
43. E_FAIL = _HRESULT_TYPEDEF_(0x80004005), /**< 未定义错误 */
44. E_NOTIMPL = _HRESULT_TYPEDEF_(0x80004001), /**< 接口未实现 */
45. E_OUTOFMEMORY = _HRESULT_TYPEDEF_(0x8007000E), /**< 内存不足 */
46. E_INVALIDARG = _HRESULT_TYPEDEF_(0x80070057), /**< 无效参数 */
47. E_NOINTERFACE = _HRESULT_TYPEDEF_(0x80004002), /**< 接口不存在 */
48. E_POINTER = _HRESULT_TYPEDEF_(0x80004003), /**< 无效指针 */
49. E_HANDLE = _HRESULT_TYPEDEF_(0x80070006), /**< 无效句柄 */
50. E_ABORT = _HRESULT_TYPEDEF_(0x80004004), /**< 操作被取消 */
51. E_ACCESSDENIED = _HRESULT_TYPEDEF_(0x80070005), /**< 访问拒绝 */
52. E_PENDING = _HRESULT_TYPEDEF_(0x8000000A), /**< 操作被挂起 */
53. E_UNEXPECTED = _HRESULT_TYPEDEF_(0x8000FFFF) /**< 未预料的错误 */
54.};
55.
56./// 判定 HRESULT 值是否为成功值
57.#define SUCCEEDED(Status) ((HRESULT)(Status) >= 0)
58./// 判定 HRESULT 值是否为失败值
59.#define FAILED(Status) ((HRESULT)(Status) < 0)
60.
61./// GUID 类型定义
62./**
63.要定义 GUID 常量请使用 GUID 专门的生成工具(比如 VS 携带的 guidgen.exe 程序)来生成,
64.以确保其唯一性。
65.接口 ID(IID), 类 ID(CLSID)均为 GUID 的别名*/
66.struct GUID
67.{
68. unsigned long Data1;
69. unsigned short Data2;
70. unsigned short Data3;
71. unsigned char Data4[8];
72.};
73.
74.typedef GUID IID;
75.typedef GUID CLSID;
76.#define REFGUID const GUID&
77.#define REFIID const IID&
78.#define REFCLSID const CLSID&
79.
80./// 判断两个 GUID 是否相等(内联版)
81.inline BOOL InlineIsEqualGUID(REFGUID rguid1, REFGUID rguid2)
82.{
83. return ((long*)&rguid1)[0] == ((long*)&rguid2)[0] &&
84. ((long*)&rguid1)[1] == ((long*)&rguid2)[1] &&
85. ((long*)&rguid1)[2] == ((long*)&rguid2)[2] &&
86. ((long*)&rguid1)[3] == ((long*)&rguid2)[3];
87.}
88.
89./// 判断两个 GUID 是否相等
90.inline BOOL IsEqualGUID(REFGUID rguid1, REFGUID rguid2)
91.{
92. return !
memcmp(&rguid1, &rguid2, sizeof(GUID));
93.}
94.
95.#define CopyMemory(dest, src, len) memcpy((dest), (src),(len))
96.#define ZeroMemory(dest, len) memset((dest), 0, (len))
97.#define FillMemory(dest, len, value) memset((dest), value, (len))
98.#define GetCurrentThreadId gettid
99.#define OutputDebugString(str) tprintf(_T("%s"), str)
100.#define LoadLibrary(file) dlopen(file, RTLD_NOW)
101.#define FreeLibrary dlclo
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 从零开始编写网络游戏 基础篇 从零开始 编写 网络游戏 基础