2D网络游戏开发(网络篇)(六)

时间:2022-06-01 18:29:47
2D网络游戏开发(网络篇)(六)   作者:akinggw   在前面的章节中,我们实现了一个简单的聊天室。今天,我们仍然要围绕这个主题,但采取别的方法,这个方法很有用,应该说是整个网络引擎的关键,它就是――RPC(Remote Procedure Calls),翻译成中文就可以理解成”远程功能调用”。 通常情况下,你发送一个信息,你必须实现下面的四个步骤:   1.       建一个数据包来存储你的数据; 2.       必须建立一个函数来实现数据包的编码和发送; 3.       建立一个数据包识别函数,用来识别你的数据包,以便于你调用哪个函数来处理它; 4.       最后建立一个函数来解码你的数据包并且处理它。    以上就是我们在编写网络程序要做的四个步骤。 但raknet已经为你做好了这一切,那就是RPC,有了它,你只用实现两个步骤,这样你就有更多的时间集中到游戏上。   1.       将你的数据编码; 2.       然后调用远程系统的一个相应函数来处理它.   RPC在你的游戏中实现的过程如下:   A.      告诉网络系统允许使用RPC调用函数 当然,你不需要RPC调用系统中的任何一个函数,这样势必为你带来很多的麻烦。你只需要几个用RPC参数定义的函数就行了,你可以照着下面的例子来定义你的RPC函数。 C函数
void MyFunction(RPCParameters *rpcParameters) {}
//
客户端指针
RakClient *rakClient;
//
注册成为RPC
REGISTER_AS_REMOTE_PROCEDURE_CALL(rakClient, MyFunction);

C++
静态函数
static void MyClass::MyFunction(RPCParameters *rpcParameters) {}
//
客户端指针
RakClient *rakClient;
//
注册成为RPC
REGISTER_AS_REMOTE_PROCEDURE_CALL(rakClient, MyClass::MyFunction);

C++
成员函数
class MyClass : public NetworkIDGenerator {
void __cdecl func1(RPCParameters *rpcParms);
};
//
客户端指针
RakClient *rakClient;
//
注册成为RPC
REGISTER_CLASS_MEMBER_RPC(rakClient, MyClass, func1)
服务器的注册同上一样。   B.给你的数据编码 你的RPC方法能够处理一个有长度的字符串或比特流,这就等同于将数据打包。   C.调用RPC函数进行处理   D.在远程系统上相应的函数将对你的数据进行处理   以上就是RPC的处理过程。 下面,我们来看一下RPC的参数和结构:   char * input; 来自于远程系统的数据; unsigned int numberOfBitsOfData; 我们接收的数据的大小; PlayerID sender; 哪一个系统调用这个RPC; RakPeerInterface * recipient; rakpeer中的哪一个实例将得到这次调用; Bool hasTimestamp; 如果为真,那么输入的开始4个字节表示时间; RakNet::BitStream * replyToSender 用相应的数据流回应发送者.   下面,我们来具体地看一下代码: char message1[300];   void PrintMessage(RPCParameters *rpcParameters) { printf("%sn",rpcParameters->input);     sprintf(message1,"%s",rpcParameters->input);                      if(rakServerInterface)         {       rakServerInterface->RPC("PrintMessage", message1, (strlen(message1)+1)*8, HIGH_PRIORITY, RELIABLE_ORDERED, 0,rpcParameters->sender, true, false, UNASSIGNED_NETWORK_ID,0);              } } 下面,我们来具体地讲解这个函数。 Message1用于存储得到的信息。首先,我们打印我们得到的信息,然后判断我们是否是服务器,如果是,那么就调用客户端的RPC. 这里这个RPC函数原型如下: bool RakServer::RPC ( char * uniqueID,   const char * data,   unsigned int bitLength,   PacketPriority priority,   PacketReliability reliability,   char orderingChannel,   PlayerID playerId,   bool broadcast,   bool shiftTimestamp,   ObjectID objectID,   RakNet::BitStream * replyFromTarget  ) [virtual, inherited] 第一个参数,我们注册的RPC函数名; 第二个参数,我们要发送的数据; 第三个参数,发送的数据的大小; 第四个参数,数据包的安全级别,和send函数一样; 第五个参数,数据包的可靠性,和send函数一样; 第六个参数,和send函数一样; 第七个参数,接收者ID; 第八个参数,是否广播; 第九个参数,与时间有关,以后讲解; 第十个参数,如果是静态函数,直接设置成UNASSIGNED_OBJECT_ID 第十一个参数,保留。   if (rakServerInterface) {         // 服务器运行在端口60000处        rakServerInterface->Start(32, 0, 0, 60000);        REGISTER_STATIC_RPC(rakServerInterface, PrintMessage);   } else {         // 运行客户端        printf("输入服务器IP地址:n");        gets(str);         // 127.0.0.1 designates the feedback loop so we can test on one computer         if (str[0]==0)                strcpy(str, "127.0.0.1");        rakClientInterface->Connect(str, 60000, 0, 0, 0);                 REGISTER_STATIC_RPC(rakClientInterface, PrintMessage);   }   在服务器或客户端注册RPC。 gets(message);                   if(rakServerInterface)           {            rakServerInterface->RPC("PrintMessage", message, (strlen(message)+1)*8, HIGH_PRIORITY, RELIABLE_ORDERED, 0,UNASSIGNED_PLAYER_ID , true, false, UNASSIGNED_NETWORK_ID,0);          }          else           {            rakClientInterface->RPC("PrintMessage", message, (strlen(message)+1)*8, HIGH_PRIORITY, RELIABLE_ORDERED, 0, false, UNASSIGNED_NETWORK_ID,0);           }   得到信息,然后调用RPC。   其它代码不用改动,程序运行的效果如下:

 

 
2D网络游戏开发(网络篇)(六)
图注1
2D网络游戏开发(网络篇)(六)
图注2
OK,今天的内容就到这里了。   关于更多内容请访问金桥科普网站(http://popul.jqcq.com)游戏开发栏目,如你需要游戏开发方面的书籍请参考金桥书城游戏频道(http://book.jqcq.com/category/1_70_740.html)。如果你在阅读本篇文章时有什么好的建议请来信给我,我的E_mail: akinggw@126.com. 如果你在使用SDL时有什么问题,请到金桥科普网站(http://popul.jqcq.com)游戏开发栏目,我将详细地为你解答。