2D网络游戏开发(网络篇)(八)1

2D 网络游戏开发(网络篇)(八)
 
作者: akinggw
 
前言
 
已经写到 raknet 编程的第八篇了,在前面的内容当中,我们讲解了 raknet 如何传输普通的信息,可光是这些是不够的。因为一个游戏不可能就只传输这些信息,它们可能会传输数据结构。
而我们今天的内容就和数据结构有关。
 
建立一个数据包
 
建立什么样的数据包,或是在数据包中要包含什么样的信息完全由你想发送什么样的数据决定。而我们在游戏当中到底要发送什么样的信息呢?比如,我们要发送一个游戏玩家 Mine 在游戏世界中某一时间的坐标,那么我们就需要下面的数据:
l        玩家 Mine 在游戏世界中的坐标,包含 3 个浮点值: x,y,z 。你可以用一个矢量值来表示。
l        用一些方法来确定所有玩家都知道玩家 Mine 的存在。关于这个问题,可以直接采用 Network ID Generator 类来完成。我们假设类 Mine NetworkObject 继承而来,那么其它所有玩家就不得不得到并存储 Mine ObjectID.
l        谁是玩家 Mine, 关于这个问题请参考 players,PlayerID 。如果你是在服务器上玩游戏,我们可以将你的 playerID 值设置成一些傀儡值,比如 255 。而如果在客户端,你可以用 GetPlayerID 得到它。
l        当一个玩家 Mine 在某个地方 , 但可能 10 秒以后,它就到达另一个地方,因此最重要的是我们得到那相同的时间,这样做的好处就是避免玩家 Mine 在不同的计算机上拥有不同的时间。幸运的是, Raknet 可以使用 Timestamping 来处理这个问题。
 
使用结构或比特流
 
最终,你发送数据将发送用户的角色的流。有两种方法可以编码你要发送的数据。一种方法是建立一个结构,另一个方法是内建一个比特流类。
 
建立一个结构的优点就是能够非常容易地改变结构并且看到你实际发送了什么数据。这样,发送者和接收者就能够共享结构中相同的源文件,这样做就避免了不必要的错误。建立结构的缺点就是你将不得不经常改变和重新编译许多文件。也将失去在比特流中传输时压缩的机会。
 
使用比特流的优点就是你不用改变任何其它的外部文件。简单地建立一个比特流,把你想发送的数据写入比特流,然后发送。你也可以通过压缩来读写数据,然后通过 bool 值来判断数据是否被压缩。比特流的缺点是你现在一旦范了一个错误,那就不容易那么改变。
 
用结构建立一个包
 
打开 NetworkStructures.h
在文件中间将有一个大的部分,像下面这样:
// -----------------------------------------
// 你的结构在下面
//------------------------------------------
 
// ------------------------------------
// 你的结构在这里
// ---------------------------------
 
// -----------------------------------------------
// 你的结构在上面
// --------------------------------------
 
有两个通用的形式用于结构中,一个是带有 timestamping ,一个是没有。
 
不带 Timestamping 的形式
 
#pragma pack(1)
struct structName
{
 unsigned char typeId;   // 把你的结构类型放在这里
 // 你的数据放在这里
}
 
Timestamping 的形式
 
#pragma pack(1)
struct structName
{
 unsigned char useTimeStamp;   // 分配它到 ID_TIMESTAMP
 unsigned long timeStamp;      // 把通过 timeGetTime() 返回的系统时间放在这里
 unsigned char typeId;         // 结构类型放在这里
 // 你的数据放在这里
}
对于前面我们的角色,我们在这里想使用 timestamping ,因此,结构填充的结果如下:
pragma pack(1)
struct structName
{
 unsigned char useTimeStamp; // 分配这个到 ID_TIMESTAMP
 unsigned long timestamp;   // 把由 getTime() 得到的系统时间放在这里
 unsigned char typeId;      // 这将分配一个类型 id PacketEnumerations.h 中,这里,我们可以说是 ID_SET_TIMED_MINE
 float x,y,z;              // 角色 Mine 的坐标
 ObjectID objected;       // 角色 Mine 的目标 ID ,用于在不同计算机上参考 Mine 的通用方法
 PlayerID playerId;       // 角色 Mine 拥有的玩家的 PlayerId
};
正如上面我们写的结构,我们添加 typeId 的目的就是当我们得到一个数据流到达时,我们将知道我们看见了什么。因此最后一步就是在 PacketEnumerations.h 中添加 ID_SET_TIMED_MINE.
注意你不能在结构中直接或间接地包含指针。
 
你将注意到我在结构中调用了 ObjectID objected PlayerID playerId 。为什么不使用一些更具有描述性的名字,比如 mineId mineOwerId? 我以我的实际经练告诉你,在实际运用中使用描述性的名字是不明智的。因为虽然你知道这些数据包中的参数意味着什么,但它们自己却并不知道。使用通用名字的优点是你可以通过粘贴,复制来处理你的数据包,而不用重新给这些数据包装填数据。当你有许多的数据包的时候,你将在一个很大的游戏中,这种方法保存了许多分歧。
 
巢结构 
 
关于巢结构并没有多少问题,值得注意的是第一个字节总是决定了数据包的类型。
 
#pragma pack(1)
struct A
{
 unsigned char typeId; // ID_A
};
#pragma pack(1)
struct B
{
 unsigned char typeId; //ID_A
};
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
游戏 引 擎 是一个处理游戏底层技术的平台,使用游戏引擎,游戏开发人员可以不用 花过多精力去处理系统架构、图形处理等一些底层的技术,可以直接使用引擎提供的 API来进行游戏开发,从而大大缩短游戏开发时间。 本文 通 过 对网络通信和图形处理方面的研究,设计并实现了一个具备消息处理和客 户端动作交互功能的引擎。 本文 设 计 的引擎主要包括三个部分:消息处理系统、自动更新系统、图形处理与动 作交互系统。 消 息 处 理系统包含两部分:网络通信底层模块和服务器端消息处理模块。网络通信 底层模块通过对Socket的API函数进行封装和功能扩展,使得开发人员在构建通信模 型时更加方便。服务器端消息处理模块实现了对客户端发往服务器端的消息进行识别和 处理的功能。 自动 更 新 系统模块由三个子模块组成:文件版本管理模块、文件传输服务器模块和 接受文件模块。这是一个独立的引擎模块,实现了游戏客户端更新版本的整个过程。 图形 处 理 与动作交互系统。设计了游戏中从位图调入、场景显示、角色行走、地图 处理等一系列的API函数,并利用这些函数实现了一个简单的动作交互系统模型。 本 文 研 究的课题初步探讨了2D网络游戏引擎的基本技术架构,对于国内基于2D网络游戏系统开发具有一定的借鉴和参考价值。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值