2d网络游戏开发:2D网络游戏开发(网络篇)(十 9)



2D网络游戏开发(网络篇)(十 9)

作者:antking

前言

hi,伙计们是不是感觉前面内容点让你百般无聊不要着急今天我们就将给出个别人编例子这个例子很简单主要就是使用了我们上张所讲解内容本来都不愿意拿出来分享但我这个人心比较好分享就分享吧呵呵!
如果你觉得这个例子比较好请记得千万要给我来信邮箱是[email protected]
这个例子最开始是出现在Irrlicht这个3D游戏引擎官方主页上文章标题叫“APrimerForRakNetUsingIrrlicht”中文意思就是如何在Irrlicht引擎中使用Raknet文章比较简单内容主要就是Raknet中比特流和数据结构你如果将我前面写文章全部看懂了理解这篇文章就相当没问题
但在我这篇文章中我只会讲解有关RankNet部分如果你对Irrlicht游戏引擎有兴趣请参考原文:http://www.daveandrews.org/articles/irrlicht_raknet/
OK废话少说让我们开始吧!

先看张游戏执行界图你可以在http://www.daveandrews.org/articles/irrlicht_raknet/Chalkboard.zip下载文件源代码和可执行文件



客户端

如果你执行了游戏你就会发现这根本就不是游戏它只是显示如何在每个客户端同步画图
因此我们先讲解我们要用到些参数如果用个数据结构来表示可以表示如下:

数据包
{
数据包类型;
鼠标开始位置;
鼠标结束位置;
};

这就是我们要传输数据如果想象假如我要传输我自己游戏中角色信息那结构就会是下面这个样子:

数据包
{
数据包类型;//角色信息
角色类型;//比如人精灵妖怪等等
操作方式;//比如是重新建立更改删除
角色所处地图;//就是它在那张地图上
角色所处地图坐标;//就是它在地图什么位置
角色生命值;
.
.
.
};

好象又扯得太远了我们还是来说这里吧

#<irrlicht.h>
#<PacketEnumerations.h>
#<RakNetworkFactory.h>
#<NetworkTypes.h>
#<RakClientInterface.h>
#<BitStream.h>

#<windows.h>//forSleep
#<stdio.h>
#<conio.h>
#<.h>
#<stdlib.h>

头文件是不能不要作者说bitstream好象还存在些问题所以作者建议你在项目中包括bitstream.h和bitstream.cpp这两个文件
另外作者也讲解了为什么要包含windows.h文件包含windows.h文件作用就是使用它Sleep
通过使用Sleep就是为了让主线程在执行过程中能够给Raknet更多时间去执行在整个游戏客户端中我们都将在主循环中使用SleepSleep(1)并不能是暂停但可以让处理器放弃执行另

“客户端连接“类

作者使用了个客户端连接类来管理和服务器连接数据包处理和发送我们首先来看下这个类成员和功能:
1. 构造客户端连接类构造有两个参数:用于连接服务器IP地址(用串表示)和用于连接服务器端口号(也是用串表示)这个功能就是化Raknet网络连接并连接到服务器
2. 拆构拆构功能就是关闭构造建立连接并且释放Raknet建立网络结构
3. 添加线坐标这个作用就是将我们为了画线时产生坐标x,y添加到画线列表中
4. 发送线到服务器这个作用就是发送我们画线用坐标(或者点)到服务器
5. 画线这个和网络传输无关主要就是将画线列表中点连成条线
6. 侦听数据包这个作用就是检测从服务器传输过来数据包然后自动用下来处理它
7. 处理数据包它作用就是从数据包中读出数据然后显示到屏幕上

具体类描述如下:

ClientConnection
{
private:
list<line2d<s32>>lineList;
RakClientInterface*client;

public:
ClientConnection(char*serverIP,char*portString);
~ClientConnection;

voidAddLineLocal(s32x1,s32y1,s32x2,s32y2);
voidSendLineToServer(s32x1,s32y1,s32x2,s32y2);
voidDrawLines(IVideoDriver*irrVideo);
voidListenForPackets;
voidHandlePacket(Packet*p);
};

还有个类这个类来自于Irrlicht这个类主要就是处理游戏中些事件我在这里不讲解请大家自己看

另外在文件开始处要加入下面代码:

constunsignedcharPACKET_ID_LINE=100;

这个用于设置我们数据包类型有关这个方面我已经在前面进行了详细讲解

接下来我们具体地看实现
首先是构造:

ClientConnection(char*serverIP,char*portString)
:client(NULL)
{
client=RakNetworkFactory::GetRakClientInterface;



client->Connect(serverIP,atoi(portString),0,0,0);
}

比较简单我在这里就不进行讲解

~ClientConnection
{
client->Disconnect(300);
RakNetworkFactory::DestroyRakClientInterface(client);
}

拆构也比较简单

voidSendLineToServer(s32x1,s32y1,s32x2,s32y2)
{
RakNet::BitStreamdataStream;

dataStream.Write(PACKET_ID_LINE);
dataStream.Write(x1);
dataStream.Write(y1);
dataStream.Write(x2);
dataStream.Write(y2);

client->Send(&dataStream,HIGH_PRIORITY,RELIABLE_ORDERED,0);
}

发送数据到服务器端这个完全按照我们我们前面所讲内容进行先往数据流中写数据包类型然后才是数据最后发送有关Send我们前面已经讲解了
我们再来看下侦听:

voidListenForPackets
{
Packet*p=client->Receive;

(p!=NULL){
HandlePacket(p);

client->DeallocatePacket(p);
}
}

这个成员作用就是接收数据包如果数据包不为空就处理这个数据包然后释放它

voidHandlePacket(Packet*p)
{
RakNet::BitStreamdataStream((constchar*)p->data,p->length,false);
unsignedcharpacketID;

dataStream.Read(packetID);

switch(packetID){
PACKET_ID_LINE:
x1,y1,x2,y2;

dataStream.Read(x1);
dataStream.Read(y1);
dataStream.Read(x2);
dataStream.Read(y2);

AddLineLocal(x1,y1,x2,y2);
;
}
}

我们再来看下处理数据包我们数据是经过数据流处理后传输因此我们接收时候必须先将数据包中数据重新写入数据流然后读取这个数据流类型
如果这个数据包满足我们条件我们就将数据读出然后画线最后退出

这就是客户端处理下面我们来看下服务器处理过程

服务器可以用个控制台来写下面我们来看下这个应该怎样来写

#<PacketEnumerations.h>
#<RakNetworkFactory.h>
#<NetworkTypes.h>
#<RakServerInterface.h>

#<windows.h>//forSleep

开始和客户端首先包含Raknet头文件

constunsignedcharPACKET_ID_LINE=100;

定义数据包类型

服务器端不是使用直接使用了 3个:

1. SendLineToClients这个就是将接收信息广播给所有在线客户端
2. HandlePacket这个就是处理数据包中数据
3. Main这个就是建立服务器然后在游戏循环中接收数据处理数据

下面我们来具体看下这些处理过程

voidSendLineToClients(RakServerInterface*server,PlayerIDclientToExclude,x1,y1,x2,y2)


{
RakNet::BitStreamdataStream;

dataStream.Write(PACKET_ID_LINE);
dataStream.Write(x1);
dataStream.Write(y1);
dataStream.Write(x2);
dataStream.Write(y2);

server->Send(&dataStream,HIGH_PRIORITY,RELIABLE_ORDERED,0,clientToExclude,true);
}

这个就是将接受到数据写入数据流然后广播给在线所有客户端

voidHandlePacket(RakServerInterface*server,Packet*p)
{
unsignedcharpacketID;

RakNet::BitStreamdataStream((constchar*)p->data,p->length,false);

dataStream.Read(packetID);

switch(packetID){
PACKET_ID_LINE:
x1,y1,x2,y2;

dataStream.Read(x1);
dataStream.Read(y1);
dataStream.Read(x2);
dataStream.Read(y2);

SendLineToClients(server,p->playerId,x1,y1,x2,y2);
;
default:
prf("Unhandledpacket(notaproblem):%i\\n",(packetID));
}
}

这个作用就是从网络上得到数据然后判断这个数据是不是我们所需要如果是就将它从数据流中读出然后用SenLineToClients进行处理

最后我们来看


{
RakServerInterface*server=RakNetworkFactory::GetRakServerInterface;
Packet*packet=NULL;

port=10000;

(server->Start(32,0,0,port)){
prf("Serverstartedsuccessfully.\\n");
prf("Serverisnowlisteningonport%i.\\n\\n",port);
prf("Pressakeytocloseserver.\\n");
}
{
prf("Therewasanerrorstartingtheserver.");
system("pause");

0;
}

while(kbhitfalse){
Sleep(1);
packet=server->Receive;

(packet!=NULL){
HandlePacket(server,packet);

server->DeallocatePacket(packet);
}
}

server->Disconnect(300);

RakNetworkFactory::DestroyRakServerInterface(server);

prf("Serverclosedsuccessfully.\\n");

system("pause");
}

这个作用很简单我简单地说先建立服务器然后进入游戏循环接收数据如果数据不为空就进行处理如果你按动任何按键就退出关闭服务器

这就是个游戏例程很简单

有关更多内容请访问金桥科普网站WebSite(http://popul.jqcq.com)游戏开发栏目如果你需要游戏开发方面书籍请参考金桥书城游戏频道(http://book.jqcq.com/category/1_70_740.html)如果你在阅读本篇文章时有什么好建议请来信给我E_mail:[email protected].如果你在使用SDL时有什么问题请到金桥科普网站WebSite(http://popul.jqcq.com)游戏开发栏目我将详细地为你解答

border=0>

border=0> border=0>

Tags:  最新2d网络游戏 2d网络游戏 2d网络游戏开发

延伸阅读

最新评论

发表评论