2D
网络游戏开发(网络篇)(十)
作者:
akinggw
前言
其实,我也很想将游戏开发简单化,可不管我怎么努力,游戏开发还是那么难,还是涉及那么多知识。同样,在这里,我也希望我的翻译和讲解能够让你明白,为了使你和我更容易地理解游戏开发的内容,因此你的反馈对我很重要,
我的邮箱是akinggw@126.com
。欢迎你提出你宝贵的意见。最近天气比较热,因此,我也改编程为翻译,希望没有译错。
发送数据包
决定你的数据
关于这个东西,已经在建立数据包那一篇讲解了,你最好翻看前面的内容。
决定使用那种方式来进行
你通常是想发送一个触发动作的标志,而不是发送动作的结果。通常来说,一个数据包的来源主要集中在下面三个方面:
来自于一个函数来触发动作
来自于一个标志驱使函数去触发动作
来自于一个数据管理器
它们每种方法都有自己的优点和缺点。
来自于一个函数来触发动作
例子:
假如我们有一个函数叫
ShootBullet
,带有大量的参数,包括射击的方式,在哪里射击和向哪个方向射击。每次
ShootBullet
函数一旦调用,那么我就将发送一个数据包去告诉网络,已经有事情发生了。
这种方法的优点
很容易维护。
ShootBullet
函数可能在许多不同的地方被调用(比如,鼠标输出,键盘输出,
AI
等),因此,我们就不得不保证在每一个接收到的地方的一致性。这种方法在现在的单玩家游戏中很容易实现。
这种方法的缺点
编程实现很难。如果我用
ShootBullet
去初始那个包,那么当网络想实现这个函数时,它将调用什么?如果
ShootBullet
初始那数据包,并且网络调用
ShootBullet
函数,那么另一个数据包将寄出,建立一个反馈循环。因此,我能写另一个函数,比如
DoShootBullet,
或者传输一个参数到
ShootBullet
,告诉它是否发送一个数据包。我们也不得不考虑授权,客户端是直接发出子弹,还是在发出子弹之前,要经过服务器授权?如果需要授权,那么
ShootBullet
将发送一个数据包并且马上返回,只有一种情况不会返回,那就是它被网络调用并且它不能发送数据包。那网络也许还需要一些
ShootBullet
函数没有的附加信息,比如子弹存在的数量。有时这些可以从上下文中得到,但是有时也不能。
来自于一个标志驱使函数去触发动作
我们还是使用上面的例子,但这次有一点不同,我们这次是在
ShootBullet
函数内部发送数据包,而何时发送数据包是通过一个标志来确定。例如,当用户点击鼠标,
AI
决定射击或空格键被按下。
优点
我可以在网络中调用
ShootBullet
函数,而不用担心返回循环。并且我将得到更多函数以外的信息可以利用。因此,利用网络,可以很容易地发送数据。
缺点
难于维护。如果我稍后添加另一种方法射击子弹,可能我会忘记发送数据包。
来自于一个数据管理器
例子
每次,一个玩家的生命值到达
0
,发送一个数据包。不管怎样,我不会这样做。我会把它添加到一些运行每一帧的一些函数里,也许在代码中实现玩家的更新。当代码发现玩家的生命值是
0
时,它马上发送一个数据包。然后注册这个已经发送的数据包以避免又一次重新被发送。
优点
从网络来看,非常的清楚。我不得不担心反馈和在实际动作中改变那函数。不用维护,除非一些人改变了它。还有就是非常的高效。
缺点
但是从设计的角度讲,非常的不整洁并且只能用于数据的一定类型。另外就是不得不反复设置。
决定可靠性的类型和你需要什么样的顺序流
PcaketPriority.h
包含了可靠性的类型。你需要从三中级别中作出选择:
HIGH_PRIORITY, MEDIUM_PRIORITY, LOW_PRIORITY
。
高可靠性的数据包比中可靠性的数据包先寄出,而中可靠性的数据包比低可靠性的数据包先寄出。在游戏中,你将用
RELIABLE_ORDERED
来设置数据包。
调用客户端的服务器的发送函数
发送函数并不会改变你的数据,但是会做一次拷贝。
顺序流
对于顺序数据包,有
32
种顺序流,而对于连续的数据包,同样有
32
种顺序流。你能把流想象成一种相关的顺序流,它们所有的数据包拥有相同的顺序类型。我们可以举一个例子来描述这个东西。假设你想排序所有的聊天信息,排序所有的玩家移动数据包,排序所有的玩家开火包,连续所有的弹药数据包。你想使聊天信息按顺序到达,又不想聊天信息被挂起,因为你不能很容易的得到玩家移动的数据包。玩家移动数据包并不和聊天信息关联,因此,你不用担心他们是按照什么顺序到达。这样,你就可以为他们使用不同的顺序流,也许,
0
表示聊天信息,
1
表示玩家的移动数据包。值得一提的是玩家的开火数据包的顺序应该和玩家移动的数据包相关,因为你不想在错误的位置进行开火。因此,你应该将玩家开火的数据包放在和玩家移动数据包相同的数据流里。这样做的好处就是如果开火数据包比移动数据包后到达,开火数据包不会给你任何东西,它会一直等待移动数据包的到达。
序列将不停地剔除老的数据包,因此,如果你得到包的顺序为
2
,
1
,
3
,那么你将开始收到
2
,
1
,然后这些包被剔除,最后你将得到数据包
3
。这对于弹药来说非常的有用,因为弹药就只是不断地下降。如果你得到一个很老的包,那你就将得到很多的弹药,这明显是个错误。值得注意的是序列数据包不同于顺序数据包,因为顺序数据包是用一组流来表示的。
关于更多内容请访问金桥科普网站(
http://popul.jqcq.com
)游戏开发栏目,如你需要游戏开发方面的书籍请参考金桥书城游戏频道(
http://book.jqcq.com/category/1_70_740.html
)。
如果你在阅读本篇文章时有什么好的建议请来信给我,我的
E_mail: akinggw@126.com.
如果你在使用
SDL
时有什么问题,请到金桥科普网站(
http://popul.jqcq.com
)游戏开发栏目,我将详细地为你解答。