目前开发棋牌类游戏的公司和个人很多。但是对于很多开发者来说,开发一款具有可扩展、稳定的棋牌类游戏还是具有一定的难度。这次我就以我开发棋牌类游戏为例,讲述如何使用DELPHI来开发棋牌类游戏。希望我的经验可以对游戏开发爱好者起到抛砖引玉的作用。如果您对我基础篇中涉及到的内容非常熟悉,可以直接跳过进入设计篇。因为我的能力有限,所以文中难免有不足之处,欢迎大家指正。
首先来说说关于游戏开发中需要的一些基础知识。
第一个基础知识就是:链表的使用。
对于链表的使用,首先涉及到的就是结构的定义。以下是我定义的一个结构:
//用户信息结构
RuserInfo= record
UserID:String[20];
Sex:Boolean;
Face:Byte;
Score:Integer;
End;
PuserInfo = ^ RuserInfo;
在这个结构中大家需要注意UserID:String[20];的定义方法。我见过有人是这样定义的:UserID:String; 我觉得这样定义是不正确的。对于String[20]来说,这样定义说明了它是一个short String类型,而这种类型的长度是255。可是定义成string的话它的长度应该是2G。一个结构不能占用这么大的空间。所以我建议大家在定义结构对象的时候string类型尽量定义成string[]方式。
对于链表的时候其次就是向链表中加入指针和从链表中删除指针。
加入指针使用Add,删除指针使用Delete 例如:
//添加链表
New(p_User);
p_User.UserID:= UserID;
p_User.Sex:= Sex;
p_User.Face:= Face;
p_User.Score:= Score;
UserList.Add(p_User);
//删除链表
IF p_User.UserID = UserID then
Begin
UserList.Delete(I);
Dispose(p_User);
End;
在添加和删除链表的使用中一定要注意,在加入之前使用NEW函数在删除以后一定要使用dispose函数。我见的最多的错误就是在添加前使用了New但是在删除以后没有使用Dispose来释放自己申请的空间。这样会造成内存泄露。
2:链表的嵌套。
在我后面关于开发游戏的例子中会讲到在定义链表的时候使用嵌套的方式。
例如:对于一个游戏来说,我们可以给它定义一个GAMEID来作为这个游戏的编号。而一个游戏可以分成好几个房间(我们使用房间编号RoomID来标记)。对于房间来说,里面会包含很多的用户。那如何使用一个链表来保存这个信息,并且让我们以后查找起来非常方便呢?我是这样定义的:
//用户信息
RuserInfo = Record
UserID:String[20]; //用户编号 用来唯一确定一个用户
UserName:String[20]; //用户名称 用于显示使用
UserPaw:String[20]; //用户的密码
UserFace:Integer; //用户头像
UserSex:Boolean; //用户性别
… … //省略用户其它信息
End;
PuserInfo = ^ RuserInfo;
//房间信息
RroomInfo = record
RoomID:Integer; //房间编号
UserList:Tlist; //房间用户链表 用来保存PuserInfo
End;
ProomInfo = ^ RroomInfo;
//游戏信息
RgameInfo = record
GameID:String[2]; //游戏编号
RoomList:Tlist; //房间链表 用来保存ProomList
End;
PgameInfo = ^ RgameInfo;
这样定义出了一个使用嵌套的结构。
使用的时候和单一的链表结构使用没有区别。例如
在某房间加入一个用户(假设GameList为游戏链表)。
Procedure AddUserInfo(GameID:String;RoomID:Integer;UserInfo:RuserInfo);
Var
P_GameInfo:PgameInfo;
P_RoomInfo:ProomInfo;
P_UserInfo:PuserInfo;
I:Integer;
Begin
For I:=0 to GameList.Count-1 do
Begin
P_GameInfo:= GameList.Items[I];
If P_GameInfo.GameID = GameID then
Begin
For J:=0 to P_GameInfo. RoomList.Count-1 do
Begin
P_RoomInfo:= P_GameInfo. RoomList.Items[J];
If P_RoomInfo. RoomID = RoomID then
Begin
New(P_UserInfo);
P_UserInfo^:= UserInfo;
P_RoomInfo. UserList.Add(P_UserInfo);
Break;
End;
End;
End;
End;
End;
至于查询、删除都和上面的例子相差不大。
3:函数链表的使用。
对于棋牌类游戏中函数链表的使用主要表现于:服务端框架和具体游戏逻辑处理DLL中。由于服务端框架部分已经实现了一些函数(例如数据发送函数、用户状态改变函数、桌子状态改变函数等等),没有必要再让DLL实现这个功能(或者不易实现这个功能)。所以我们只要将这些函数的指针传入就可以直接使用它们。具体的传入方式可以查看我的BLOG文章《Delphi下使用指针的简单总结》中的3:函数指针的使用。为了保障阅读的连续性,我将当时的代码在这里也贴出来:
SendDataFun: procedure(Casetype: Byte; UserSocket: RUserSocket; Data: array of char; DataLen: Integer);
function ModuleSendData(FunPList: TList): Boolean; stdcall; export;
begin
SendDataFun := FunPList.Items[0];
end;
在EXE中的代码是:
Linstance:=LoadLibrary(Pchar(Temp));
if Linstance>0 then
begin
//将发送数据的指针传入DLL插件中
@GiveModuleFun:=GetProcAddress(Linstance,'ModuleSendData');
if @GiveModuleFun<>NIl then
begin
m_FunList:=TList.Create;
//发送数据
t_Pointer:=@DllSendData;
m_FunList.Add(t_Pointer);
GiveModuleFun(m_FunList);
End;
End;
是不是将链表使用的很熟练就可以开始开发游戏了呢?不是。对于网络棋牌类游戏来说。我的理解应该是两个部分非常重要:1:网络通信部分。2:界面实现部分。
下一篇我们来探讨使用DELPHI开发网络通信部分。