资源描述
让虚拟世界和现实世界成为相互的起点和终点
蜗牛游戏程序编码规范 (版本 0.1)
规范说明: 1
一、 命名规则 1
二、 程序的版式 3
三、 注释 5
四、 服务端平台无关 7
五、 服务端表格操作 7
六、 客户端文件读写 8
七、 客户端内存操作 8
八、 脚本内的注释 9
规范说明:
制定该规范的目的是让程序清晰易懂、易维护、易管理。该规范为强制规范,必须执行,如果有没涉及的地方请参考《高质量C++-C编程指南》。当所在编程环境(如MFC、Linux)与本规范有差异时,可以使用所在编程环境的规范,但是同一个项目必须是统一的规范。
最后希望大家都能养成一个良好的程序习惯,一个好的习惯受益终身!
一、 命名规则
1.所有命名应当直观且可拼读,并具有实际意义;
2.类名和函数名用大写字母开头的单词组合而成,接口类名以I开头;
3.常量全用大写的字母,用下划线分割单词,尽量不要使用宏;
4.类的数据成员加前缀m_,全局变量加前缀g_,静态变量加前缀s_;
5.变量名第一个字母小写,使用“名词”或“形容词+名词”的词义表示法;
示例:
·局部变量
char *pStringBuffer;
int &stringFindResult;
bool isEngineStartup;
·函数命名
unsigned int GetVoyageCoreState();
static bool GetVoyageServiceCount(int &count);
·结构类型
struct NodeValue
{
int width;
int height;
}
·枚举类型(枚举值必须大写且有前缀)
enum VoyageSupportType
{
VOYAGE_OS_SUPPORT_INVALID = 1,
VOYAGE_OS_SUPPORT_WINDOWS = 2
}
·联合类型
union Color
{
unsigned char arrColor[3];
struct ColorRGB
{
unsigned char r;
unsigned char g;
unsigned char b;
};
};
·类类型
class Object
{
int m_width; // 宽度
int m_height; // 高度
void SetValue(int width, int height); // 成员函数
virtual int GetArea(); // 虚函数
inline int GetWidth(); // 内联函数
};
·抽象类
class ISpriteManager
{
public:
virtual int GetSpriteID() = 0;
virtual bool IsSpriteExist() = 0;
};
·自定义类型
typedef unsigned int Number;
·全局变量(我们不主张使用全局变量)
int g_howManyPeople;
·静态变量
static char *s_pStringBuffer;
·常量
const float SPRINT_RADIUS = 100.0f;
·回调函数
typedef int (*CALLBACK_SYSTEMINIT_FUNC)(IKernel * pKernel);
二、 程序的版式
1. 一行代码只做一件事情,只写一条语句, 语句排版整齐;
2. 关键字之后要留空格,赋值操作符、比较操作符、算术操作符、逻辑操作符、位域操作符,如“=”、“+=” “>=”、“<=”、“+”、“*”、“%”、“&&”、“||”、“<<”,“^”等二元操作符的前后应当加空格,一元操作符如“!”、“~”、“++”、“--”、“&”(地址运算符)等前后不加空格,象“[]”、“.”、“->”这类操作符前后不加空格;
3. 程序的分界符‘{’和‘}’应独占一行并且位于同一列,同时与引用它们的语句左对齐。{ }之内的代码块在‘{’右边4格处左对齐,这里的4格也可以是Visual Studio里的一个TAB;
4. 代码行最大长度宜控制在80个字符以内;
5. 代码应按功能分块,代码块之间必须有空行,而且每个代码块不要超过10行。
示例:
·语句分行和空格(▲表示空格)
for▲(int i▲=▲0,▲j▲=▲0;
(i▲<▲backBufferWidth)▲&&▲(j▲<▲backBufferHeight);
i++,▲j++)
{
... // program code
}
if▲(n▲>▲5)
{
…
}
else if▲(n▲<▲0)
{
…
}
else
{
…
}
while▲(a▲>▲b)
{
…
}
do
{
…
}while▲(a▲>▲b);
switch▲(n)
{
case▲1:
▲▲▲▲{
▲▲▲▲w▲=▲w▲+▲2;
}
break;
}
·代码块
………
// 获得字符串长度。
int length = (int)strlen(pString);
// 如果长度为空,直接将当前String类对象置空。
if (0 == length)
{
m_pString = NULL;
m_length = 0;
}
………
三、 注释
1. 对外暴露的模块接口全部要求使用“doxygen” 注释对文件、类、函数、变量进行注释;
2. 所有文件和函数必须有功能说明注释,这里不要使用“doxygen” 注释(便于生成程序文档);
3. 代码块的起始处必须有该代码块的功能说明注释;
4. 通信的消息和命令必须有功能和参数注释。
“doxygen” 注释示例:
·接口文件首部
/**
@file varithmetic.h
@brief IString模块是voyage引擎开发以及游戏开发所使用的
算法集合模块。
@author Armterla X
@date 2007.12.1
*/
·接口函数注释
注意:这些接口注释都是写在头文件里的。
注意:接口参数要写[IN]或者是[OUT]以表明参数是输入参数还是输出参数。
函数接口注释
/**
@brief 对任意类型元素的数组进行快速排序。
@param pHead
[IN]元素数组首地址。
@param ppDstHead
[OUT]输出一组经过排序的指针。
*/
void QuickSort(void *pHead, void **ppDstHead);
·类接口注释
/**
@brief IString类是用于在Voyage引擎内部进行字符串处理的类。
IString类可以完成快速的字符串连接、分割、字串查找、
字串修改等功能。
*/
class IString
{
public:
/**
@brief IString默认构造函数。
@remarks 使用默认构造函数构造IString对象不会
申请任何堆内存。
*/
IString();
/**
@brief 使用标准字符串构造IString类对象。
@param pString
[IN]指定源字符串。也就是使用哪个字符串构造当前IString对象。
@remarks 这个构造办法会申请堆内存,构造时调用一次堆分配。
分配空间大小与参数指定的字符串长度加1相等。
*/
IString(const char* pString);
/**
@brief 析构函数,如果当前IString类对象已经申请了堆内存,
该函数会释放这个堆内存。
*/
~IString();
………
};
·通信的消息和命令
/**
\brief 聊天内容信息
\param 聊天类型,类型int
\param 聊天内容,类型wstring
*/
MSG_SERVER_SPEECH = 1001
模块内部注释示例:
·文件首部
/*
file $FILE$
brief 文件说明
author %USERNAME%
date $DATE$
*/
·函数注释
//做地形的可视检测
int TerrainSubObject::IsVisible(int x,int z)
·变量注释
int ValCol; //修改表格的第几列数据
四、 服务端平台无关
1. 服务端程序不要使用依赖于操作系统的API和数据类型,以及和操作系统相关的规则,以便于未来Windows和Linux平台切换。
五、 服务端表格操作
1. 服务端表格“Record”的名称定义也要符合命名规范;
2. 在操作时不能直接用数字表示列号;
示例:
// 表格列号的定义
enum
{
CCR_CLONE_SERIAL = 0,
CCR_CYCLE_TIME,
CCR_INTO_COUNT,
CCR_COL_COUNT
};
…………………
// 表格定义和访问
pKernel->AddRecord(index, "CloneCountRec", CCR_COL_COUNT, 128);
pKernel->SetRecordColType(index , "CloneCountRec",
CCR_CLONE_SERIAL, VARTYPE_INT); // 副本号
pKernel->SetRecordColType( index , "CloneCountRec",
CCR_CYCLE_TIME, VARTYPE_INT); // 进入时间
pKernel->SetRecordColType(index, "CloneCountRec",
CCR_INTO_COUNT, VARTYPE_INT); // 进入次数
六、 客户端文件读写
1. 客户端必须使用引擎提供的API进行文件的打开、读写、关闭等操作。
示例:
HANDLE hFile = _CORE_API->fio->_CreateFile(filename, GENERIC_READ, 0, OPEN_EXISTING);
if (hFile == INVALID_HANDLE_VALUE)
return false;
DWORD Length = _CORE_API->fio->_GetFileSize(hFile, NULL);
if (Length > 0)
{
char *pBuffer = new char[Length + 1];
_CORE_API->fio->_ReadFile(hFile,
(void *)pBuffer, Length, NULL);
}
_CORE_API->fio->_CloseHandle(hFile);
七、 客户端内存操作
1. 分配内存并调用默认构造函数:
char *p = Voy_New(char, 23); 等价于 char *p = new char[23];
CUnit *p = Voy_New(CUnit, 2); 等价于 CUnit *p = new CUnit[2];
CUnit *p = Voy_New(CUnit, 1); 等价于 CUnit *p = new CUnit;
2. 释放内存并调用析构函数:
Voy_Delete(p);
如果p是某个类的指针,如:
CUnit *pUnit = Voy_New(CUnit, 2);
char *p = (char *)pUnit;
Voy_Delete(p);
这个时候不会调用CUnit的析构函数,因为传给Voy_Delete的指针是一个char*的指针,Voy_Delete认为char*指针没有析构函数。
因此,这种情况下,必须把p转换为Voy_Delete可接受的格式:(对指针的引用)
Voy_Delete((CUnit *&)p); // 这样就能正确地调用析构函数
Voy_Delete和Voy_Free会检查传入的指针是否为空,也会在删除后自动把传入的指针设为空。
3. 如果只想分配内存,而不想调用构造函数,可以调用:
char *p = Voy_Malloc(char, 1024);
4. 如果只想释放内存,而不想调用析构函数,可以调用:
Voy_Free(p);
或者:
Voy_Delete((char *&)p);
5. 如果某个类的构造函数需要参数,例如:
申请:CShow *pShow = new CShow(“this is a show”, 0);
释放:delete pShow;
应该改写为:
申请:CShow *pShow = (CShow*)(Voy_Malloc(CShow, 1));
new(pShow) CShow(“this is a show”, 0);
释放:Voy_Delete(pShow);
八、 脚本内的注释
1.以上规范适合于脚本的必须执行;
-9-
工具开发支持管理
展开阅读全文