畅游+绑定角色服务器的三种角色和所玩的服务器的三种角色不一致?

为了提升整体服务质量给大家創造更好的游戏环境20141707:00开始公测区沧海龙吟、笑问苍天、龙行天下、江山如画、梦回大清、步步惊心、蛟龙出海、苍狼啸月、龙脈传说、大清宝藏服务器的三种角色将进行“合服”操作。本次合服由于服务器的三种角色数据量较大预计操作时间为6小时。如果在预萣时间内无法完成操作内容开机时间也将继续顺延。服务器的三种角色合服后原登录界面上的服务器的三种角色名称都将保留,大家鈳以继续按以往的方式进入游戏

合服后的第一周(17-114日),还将开启登录领奖和全服1.2倍经验活动(全服好礼回馈助您光速升级,乐享游戏

合服期间给您带来的不便,敬请谅解祝您游戏愉快!

(源服务器的三种角色:所有数据将被目标服务器的三种角色接受的垺务器的三种角色)

(目标服务器的三种角色:接受所有源服务器的三种角色移民数据的服务器的三种角色)

全国电信龙掘世界三十四龙脈传说

全国电信龙掘世界三十四大清宝藏

为了保证数据安全,我们将于以下时间点关闭源服务器的三种角色和目标服务器的三种角色的部汾功能所有功能将在合服操作当天服务器的三种角色开机后恢复正常。

龙掘之境城战、黑市功能、外包任务及师徒任务

住宅养育及种植、帮会比赛、龙掘之境建城、荣光战场、家族种植、帮会拍卖行、畅易阁上架功能

建家族、建帮、申请属地、开设玩家商店、伙伴繁殖及煋座之语

元宝寄售系统、组队交友平台

合服相关规则如下请大家查看:

请各位玩家及时领取补偿仓库内的物品和伙伴,以及上次合服时嘚住宅补偿和商店补偿

1.  同账号角色超上限处理方法

1)   鹿鼎记每个账号可建角色上限为3,如果源服务器的三种角色该账号的角色和目标服该賬号的角色数量之和小于等于3,那么合服时会直接将源服务器的三种角色的角色转移到目标服务器的三种角色上。

2)   如果两个服务器的彡种角色角色之和大于3将所有角色(含待删除)按等级排列,合服时将等级最高的三个保留,其他的删除如等级相同,系统则随机選择一个保留请玩家注意转移该账号下等级无法被保留的低级账号的物品财产

1)  当两个服务器的三种角色有重名的角色时目标服务器嘚三种角色的角色名全部保留,源服务器的三种角色的重名角色会在角色名后面加符号“*”并提供玩家一次自由修改角色名的机会。

2)  当角色名因重名被修改后源服务器的三种角色的玩家可以在扬州NPC“姚盖明”(195,181处直接改名。

1.  通用公共功能处理规则

1)  目标服务器的三种角銫明湖新村保留所有源服务器的三种角色的明湖新村改为明湖别苑,明湖外村没有社区的全面性公共功能玩家可通过京师传送NPC孙惜佳(234,44)处传送至“明湖别苑”。

2)  明湖别苑社区场景的成长NPC全部删除只保留目标服的成长NPC。合服后会将源服务器的三种角色剩余的果树都删掉目标服务器的三种角色的保留。——成长型NPC是在服务器的三种角色内可持续生长变化的比如社区的花、果树、池塘放养的鱼、牧场裏的牛羊。

3)  明湖别苑保留的功能包括:飞行、码头、样板间、社区管理、社区向导、集体住宅印鉴相关(传送)其他功能及玩法仅可在奣湖新村使用。

2.  基本住宅信息处理规则

1)  合服之后源服务器的三种角色和目标服务器的三种角色的住宅都会被删掉。

2)  合服前请玩家及时取絀住宅仓库、伴侣仓库里的物品和住宅里的家具;住宅中的家具将无法保留请大家提前将家具收起,避免给您带来不必要的损失

3)  合服後,住宅向导NPC李奇薇(342245)处可以领取重建令,凭借令牌可以去换取土地归属同时获得房契获得之后可以去得到的土地处使用房契,建慥住宅

4)  住宅仓库、伴侣仓库内的物品,如果合服前没有取出那么可以在合服之后在住宅向导NPC李奇薇(342245)处取回住宅仓库中的金钱會直接存入玩家普通仓库中。

1)  将提前十天关闭住宅建造功能

合服时,源服务器的三种角色和目标服务器的三种角色的全部别墅和土地将會被清除玩家可以在合服之后,到社区向导NPC李奇薇(342245)处领取重建令牌,令牌将会记录玩家合服前住宅的部分信息包括住宅等级、庭院等级、住宅修炼等级、风水值等重要信息。如玩家未领取重建令牌在登录游戏的时候会收到邮件通知。

合服之后源服务器的三种角色和目标服务器的三种角色的明湖新村和明湖别苑都会被清空,已售出的土地和已建的别墅都会清除住宅的归属也清除,这些土地将會无法拍卖后续给已有别墅的玩家来重建合服之前未售出的土地,合服之后可以继续拍卖不能用来重建。三种重建令(别墅重建令、汢地回收令和集体住宅重建令)都为拾取绑定物品获得以后无法交易。只能用来换取土地归属和房契或者换取合服补偿

4)  合服之后,别墅被清空的玩家可以去明湖新村的住宅向导处领取一个道具:别墅重建令合服前有别墅的玩家可以领取重建令,合服后可以用重建令到住宅向导李奇薇(342245)处获取土地归属并获得相应的房契。

5)  别墅重建令换取的房契会包含该玩家之前住宅的房间等级、庭院等级、修炼等級、风水值、住宅积分等信息玩家可以通过专属房契重新建造别墅,别墅的信息会同别墅重建令里记录的一致新建别墅走建造的流程。如果玩家土地已经被抢光了可以用这个道具换取合服补偿。

1)  如果合服之前玩家买了土地但是没有建造别墅,那么合服之后该玩家可鉯到住宅向导处领取一个道具:土地回收令

2)  合服时有土地的玩家可以领取土地回收令,合服后可以使用回收令到住宅向导李奇薇(342245)處换取一块土地的归属。

3)  如果还没有领取土地回收令那么就会在上线时收到邮件通知去领取。

1)  合服之后源服务器的三种角色和目标服務器的三种角色的集体住宅都会被删掉,归属也删掉

合服之后有集体住宅的玩家可以去明湖新村的住宅向导处领取一个道具:集体住宅偅建令。合服时有别墅的玩家可以领取重建令合服后可以到住宅向导李奇薇(342245)处使用重建令来获取相应的房契。如果不想换取房契那么可以去住宅向导李奇薇(342245)处兑换合服补偿

3)  如果还没有领取集体住宅重建令,那么就会在上线时收到邮件通知去领取

4)  集体住宅重建令会包含该玩家之前住宅的房间等级、修炼等级等信息。玩家可以通过集体住宅重建令换取一个专属房契使用专属房契可以在噺村或外村任意一个空闲的房间新建一个集体住宅,住宅的信息会同集体住宅重建令里记录的一致新建住宅走建造的流程。

5)  当前服务器嘚三种角色如果仍有可建造集体住宅的位置则不可领取补偿金;仅当前服务器的三种角色所有集体住宅都已经出售完毕后才可以领取补償金。

6.  住宅仓库、家具和无限仓库处理规则

1)  玩家新建的别墅将不会保留原住宅的家具

2)  住宅仓库内、无限仓库的全部将转移至无限仓库,玩家可以到明湖新村住宅向导NPC李奇薇(342245)处领取。

3)  住宅仓库内的金钱会直接转入玩家普通仓库

4)  合服前给系统会给玩家的伴侣发邮件,提示其去取出他在伴侣仓库里存放的物品由于服务器的三种角色要进行合服,住宅仓库将无法保留请尽快到您伴侣的住宅中,取出您倉库中的物品以免造成不必要的损失。

5)  无限仓库的物品将会被转移到补偿仓库中可以到明湖新村住宅向导NPC李奇薇(342245)处选择“打开補偿仓库”取出物品补偿仓库中的物品会保存至下一次合服,请在此之前尽快取出

6)  明湖新村住宅向导NPC李奇薇(342245)处可以选择取回住宅仓库内道具在此之前请先领取住宅重建令,然后再领取住宅仓库的物品道具如果住宅仓库的物品道具数量非常多,可以分批多领取幾次

1)  明湖新村社区向导李奇薇(342245)处可以选择“领取住宅合服补偿”。

n  判断该玩家是否可以领取住宅合服补偿需要进行判断身上昰否有以下三种物品之一:集体住宅重建令、别墅重建令、土地回收令

n  如果拥有以上三种物品且服务器的三种角色(包括新村和别苑)中沒有剩余对应无归属的集体住宅、别墅或土地(合服之前就无归属的除外),就可以选择将道具扣除以换取合服补偿

2)  别墅补偿的规则如丅:

n  土地赔偿:玩家购入土地时所花的金额的100%

n  房间等级赔偿:根据房间等级分为四个档次

n  庭院等级赔偿:根据庭院等级,分为四个档佽

n  外观等级赔偿:根据外观等级分为四个档次

n  最终的赔偿金额为:土地赔偿+(房间赔偿+庭院赔偿+外观赔偿)×积分系数

3)  集体住宅补偿的规则洳下:

n  住宅赔偿,根据房间等级分为四个档次

n  最终的赔偿金额为:房间赔偿×积分系数

4)  土地补偿的规则如下:

n  土地赔偿:购入土地金额嘚100%花费。

1)  合服时目标服家族数据保持不变,源服务器的三种角色数据并入目标服务器的三种角色其他数据均保留。目标服务器的三种角色家族资助商户的信息保留源服务器的三种角色的信息将被清除。多次合服根据以下规则进行家族合并。

2)  如果目标服务器的三种角銫和源服务器的三种角色的家族数量相加没有超过上限,那么直接将源服务器的三种角色的家族合并到目标服务器的三种角色ID顺延。

3)  洳果两个服的家族数量和超过上限了那么先将两个服务器的三种角色家族放在一起排序,规则如下:

n  家族等级等级越高排名越高;

家族等级相同,依照家族繁荣度排名繁荣度越高,排名越高

家族繁荣度相同依照家族资金排名,资金越多排名越高

n  排名之后保留在总排名中前5000的家族,其余家族将被删除在以上5000个家族中,属于源服务器的三种角色的家族将会合并到目标服家族ID依顺序补充。

n  被删除的镓族族长和组员都可以获得赔偿,赔偿金额根据家族等级和人物等级而定赔偿规则如下:

4)  合服时,出现重名的家族处理规则同角色┅样,源服务器的三种角色的重名家族会被强制改名在原名字后面加符号“*”。

1) 合服时目标服务器的三种角色帮会数据保持不变,源服务器的三种角色数据并入目标服其他数据均保留。

2) 多次合服根据以下规则进行帮会合并:

3) 如果目标服务器的三种角色和源服務器的三种角色的帮会数量相加,没有超过上限那么直接将源服务器的三种角色的帮会合并到目标服务器的三种角色,ID顺延

4) 如果两個服的帮会数量和超过上限了,那么先将两个服务器的三种角色帮会放在一起排序规则如下:

n  有属地的帮会优先保留;

帮会等级,等级樾高的排名越高;

帮会等级相同依照帮会繁荣度排名,繁荣度越高则排名越高;

帮会繁荣度相同依照帮会资金排名,资金越多排名越高

n  排名之后,前540的帮会保留帮会和属地

排名541~640的帮会只保留帮会,并删除帮会属地

5) 在以上640个帮会中,属于目标服务器的三种角色的幫会属地位置不变;属于源服务器的三种角色的帮会则将其合并到目标服帮会ID依顺序补充,属地位置将进行特殊处理规则如下:

n  同一個属地位置,最多只能放6个属地;

n  如果某个位置目标服被保留下来的属地不足6个,那么源服务器的三种角色同位置被保留下来的属地则按顺序被保留在该位置按剩下空位数目进行保留,排名高的帮会则被优先保留

n  如果剩余空位不足以供源服的属地全部迁移,那么这些源服属地将被随机分配到其他有空位的属地位置上该步骤会在上一步完成之后再进行,直至所有目标服的属地也被分配完毕

6) 排名在640鉯后的帮会都将被解散。

7) 合服时出现重名的帮会、帮会属地,处理规则同角色一样源服务器的三种角色的重名帮会、帮会属地会被強制改名,在原名字后面加符号“*”并提供一次自由改名的机会。

8) 源服务器的三种角色的帮会商业路线会直接随帮会本身合并到目标垺务器的三种角色商业专利也是如此。

9) 源服务器的三种角色的帮会比赛在互联后将被清空源服务器的三种角色处于比赛阶段的帮会將获得一定的补偿,规则如下:

n  参加海选赛的帮会补偿5000帮会珠宝;

n  参加战盟赛的帮会,补偿20000帮会珠宝;

n  参加无双赛的帮会补偿50000帮会珠寶。

10) 如果单个位置的属地合并之后超过六个,那么目标服的属地位置不变源服的根据帮会ID顺序补充,没有位置的会随机被分配到其怹有空余位置的属地同时这些被挪动属地位置的帮会,会被标记有该标记的帮会可以领取属地位置变更补偿,详见下则说明

11) 被挪動帮会属地位置的帮会,该帮的帮主和副帮主会在上线时收到一封邮件,通知他去领取补偿在帮会管理NPC明珠处,选择“领取属地位置變更补偿”可获得补偿5000珠宝。

12) 被清除帮会的玩家可以到帮会管理NPC处,选择“领取清除帮会补偿”获得相应的补偿

1.  多次合服时,根據以下规则进行玩家商店合并:

2.  如果两个服务器的三种角色的玩家商店数量和超过上限了那么会将源服务器的三种角色玩家商店删除并給予补偿。补偿规则如下:

n  商店被删除的玩家将获得开店许可证一张。

n  补偿金额=店铺本金+盈利资金+柜台数×固定柜台单价

n  玩家可以前往NPC處选择“领取玩家商店合服补偿”获得以上补偿

1.  目标服务器的三种角色在龙掘之境的所有城市都保留且位置不变,源服务器的三种角色茬龙掘之境的城市需要被移动过来并可由城主选择调整城市位置。

2.  多次合服时根据以下规则进行大世界城市合并:

3.  如果目标大世界和源大世界的城市数量相加,没有超过上限那么直接将源大世界的城市合并到目标大世界,并由工作人员对城市位置进行调整多次合服還将提供一个城市迁移令牌。

4.  如果两个服务器的三种角色的城市数量和超过上限了那么先将两个服务器的三种角色的城市进行排序,规則如下:

n  城市等级等级越高排名越高(包括0级城市,0级城市排名最后);

城市成员城市成员数量越多排名越高;

等级相同,城市建造時间越早排名越高

n  排名在前230的城市将会被保留,其余城市将被删除

5.  被删除的城市,城主和城员会获得相应的补偿补偿规则如下:

n  其怹成员获得补偿:100+城市等级×500珠宝

6.  奇迹、飞行点等争夺性据点,将仅保留目标服务器的三种角色的归属状态

7.  合服时,出现重名的城市洺称处理规则同角色一样,源服务器的三种角色龙掘之境的重名城市会被强制改名在原名字后面加符号“*“,并提供一次自由改名机會

8.  每个被强制改名的城市都有一次修改城市名字的机会,城主可在自己的城市旗帜处选择“城市名称修改”来修改自己的城市名称每個城市只能改一次。

9.  被删除城市的玩家可以到平安城奖励使者NPC处,选择“领取城市合服补偿”来领取相应的补偿

1.  合服后,结拜称号需偠重新领取结拜玩家可组队在结拜功能NPC处重新领取结拜称号,所有组队玩家名字内不可包含*领取称号需由队长操作。

合服后结婚称號需要重新领取。玩家夫妻需组队在京师月老处重新领取结婚称号领取称号需由队长进行操作领取。需要玩家名字内不包含*源服务器嘚三种角色的全服第N对情侣这一记录将保留,合服后不会修改也不计入目标服务器的三种角色的排名,合服之后如果再有结婚的玩家,这一数字需要按照目标服务器的三种角色原先的数量继续排

3.  合服后,源服务器的三种角色的所有邮件清空删除目标服务器的三种角銫的所有邮件保留。

4.  好友列表和聊天群保持不变 源服务器的三种角色的组队交友平台将提前一天关闭,目标服务器的三种角色保持不变

1.  合服时,元宝寄售系统处理目标服的寄售数据保留,源服务器的三种角色的数据清空合服前请大家提前取回寄售的金币或元宝。

2.  目標服务器的三种角色伙伴繁殖的所有功能不变源服务器的三种角色的伙伴繁殖和星座之语功能将提前三天关闭。

3.  成长NPC主要包括亲信、大卋界的头目怪等合服时,目标服的相关数据保持不变源服务器的三种角色的清空。

4.  合服时目标服务器的三种角色的相关数据保留,源服务器的三种角色的清空合服前一天将关闭源服务器的三种角色的聊天交友功能。

5.  成就系统相关处理目标服数据不改,源服数据清涳玩家自身成就不变,全服唯一成就的玩家保留

6.  合服后将删除源服务器的三种角色的所有师徒任务和外包任务,请发布外包任务或师徒任务的玩家撤销已发布任务将任务奖励收回

合服时VIP等级和获益角色不变化。

1) 畅易阁将提前7天强制下架源服务器的三种角色和目標服务器的三种角色玩家未下单的商品、金币直接退回到玩家身上的畅易阁暂存列表。

2) 已经下单并支付的商品仍按正常交易过程完荿,不受影响

3) 已经下单但未完成支付的商品,会有30分钟的等待时间等待时间结束后,如已经付款则将按正常交易过程完成;如未付款则关闭交易商品退回玩家身上的畅易阁暂存列表。

1.  鹿鼎黑市将在合服前10天关闭待合服结束后重新开放使用。

2.  合服时已经上架但未絀售的物品将被删除,如需保留请玩家及时将其取出。已经竞拍成功的物品系统仍将保留8天,8天内可领取

1.  合服时,大明地宫排行榜榜单将会清空,玩家需在合服后重新进行挑战登录排行

2.  玩家个人与组队最高层数记录直接保留不受影响。

1.  合服时若参与大区赛的榜单已經产生,合服后仍保留源服务器的三种角色和目标服务器的三种角色战队的参赛资格

2.  如合服时正处于常规赛赛季,合服后源服务器的三種角色的积分将和目标服务器的三种角色融合产生新的排行榜。

3.  合服后如源服务器的三种角色中战队名称与目标服务器的三种角色战隊名称重复,处理方式同角色名处理规则战队可在天空之城NPC炮炮糖(1236)处修改战队名称

搜狐畅游《鹿鼎记》运营团队

}

没有专用服务器的三种角色的动莋类游戏的实现

本章主要介绍 P2PMO 游戏的开发详细内容如下。

  • P2P MO 游戏的特点和开发策略

  • 客户端 / 服务器的三种角色软件 + 中间件、基本原则

前面章節介绍的 C/S MMO 游戏开发中使用了专用服务器的三种角色所以从最初的概要设计、流程设计到物理设计就需要考虑服务器的三种角色的相关问題。

但是对于 P2P MO 游戏来说因为参与游戏的玩家少、不需要为(游戏使用的)专用服务器的三种角色付费,所以在概要设计、流程设计、物悝设计中需要考虑的情况就大为减少这样可以加快开发游戏的速度。

本章针对 P2P MO 游戏和 C/S MMO 游戏在设计上的不同以及那些不需要花费很多精仂解决的问题,通过实际的开发流程来向读者进行说明

5.1 P2P MO 游戏的特点和开发策略

第 3 章已经介绍了 P2P MO 游戏的概要。本章主要整理开发中需要嘚知识点

5.1.1 P2P MO 和动作类游戏——游戏的状态频繁发生改变

P2P MO 这种典型的多人游戏的设计主要有以下几种分类。

  • 例:暴雪娱乐公司的《暗黑破壞神》、卡普空的《怪物猎人》系列

  • 例:微软的《帝国时代》、暴雪娱乐公司的《星际争霸》系列

  • 例:任天堂的《马里奥赛车》系列

  • 例:任天堂的《全明星大乱斗》系列

这类游戏都具有动作游戏的特点动作类游戏的游戏状态频繁发生变化,会产生大量数据交互如果使用 C/S 方式实现,对服务器的三种角色、带宽等成本要求过高所以从商业角度考虑是不可行的。

因此即便有使用游戏外挂作弊的风险,P2P 的实現方式从经济角度来说也是合理的但是,目前服务器的三种角色硬件以及带宽成本不断降低这种经济角度的考虑已经变得不那么重要叻。所以游戏的数据通信全部通过服务器的三种角色来传输的方式也在逐渐流行起来 1

15.6 节会介绍这种实现方式。

上述动作游戏都可以使用“同步共享内存”(数据对象同步和事件通信)的方式来开发这种方式与 C/S 类型的 MMO 游戏中经常使用的 RPC 方式相比,通信量会增加但是程序開发相对简单,而且可以在游戏的单机部分开发完成后再扩展其网络功能

共享内存这种方式是 P2P MO 游戏开发中经常使用的特有方法,本章会詳细说明

在 C/S MMO 游戏中,服务器的三种角色通过 RPC 方式同步客户端数据进行游戏P2P MO 类型的游戏使用共享内存方式,它们的区别请参考表 5.1

表 5.1 RPC 開发方式和共享内存开发方式的比较

数据量大(对象数百万以上) 数据量小(对象数几百到几千)

通过表 5.1 可以看到,RPC 开发方式面向的是 MMO 游戲而共享内存的实现方式更适合 MO 游戏。共享内存其实在 C/S 和 P2P 游戏中都可以使用相对于通信方式来说,我们更应该根据游戏的内容来选择開发技术

例如,如果要求单服务器的三种角色同时连接数在数千级别带宽负荷和 CPU 负荷都应该尽量减少,就只能选择 RPC 开发方式对于不使用服务器的三种角色的 P2P MO 游戏,即使单个玩家需要的带宽多一点也可以使用共享内存的方式来开发。

笔者认为应该尽量采用共享内存嘚方式开发游戏。这是因为共享内存相对于 RPC不需要针对每个操作分别定义函数,开发起来比较容易但是对于大型 MMO 游戏来说,由于它们使用了大量数据对象而且 CPU 负荷和服务器的三种角色的带宽要求都很高,只能选择 RPC 开发方式随着云计算的使用费逐渐降低,未来也许可鉯都采用共享内存的方式来开发但目前趋势还不明显。

RPC 开发方式的相关内容在介绍 C/S MMO 的章节已经详细描述过了,本章主要对共享内存开發方式进行详细说明

P2P MO 游戏的需求和 C/S MMO 游戏正好相反,这里列举一下它们的不同特点

  • 游戏的相关资源,除了贴图和动画之外一般在几百兆鉯内可以全部安装在普通玩家的 PC 中 2。因为不需要联网也可以进行游戏所以需要安装全部的数据和资源。

  • 配置信息对玩家是可见的

    因为遊戏的配置信息是安装在玩家的电脑中所以可以在本地文件中看到配置内容,游戏运行时也可以跟踪内存信息而且还可以通过逆向工程破解全部的游戏内容,这些都是无法预防的

  • 不能严格保证游戏数据变更的安全性(可以作弊)

    正如前文所述,玩家可以通过修改内存數据来作弊要保护游戏数据的安全性是很困难的。这样造成的结果就是:原本需要玩家花费数百小时长时间培养游戏角色的游戏方式,以及具有精心创造的宏大游戏世界能让玩家在不知不觉中消耗大量时间和精力的游戏方式就难以实现了。对玩家来说这种经过长时間游戏积累的数据一旦损坏或者丢失将是难以承受的损失,游戏体验的品质也就不能得到保证导致的结果就是 P2P MO 游戏的游戏时长较短并且鉯游戏内容为中心。

  • 不能进行 P2P 连接的 NAT 网络环境有很多

    玩家之间不能通过端对端方式进行网络连接(TCP 或者 UDP 的连接方式)的情况有很多比如茬公司局域网游戏时,或者使用公寓楼、大学、当地的有线电视网络等通过路由器构建的 NAT 公共网络在日本,这种情况大概占到 10%~30%另外還有因为 P2P 通信量的异常增大而禁止直接发送数据的情况。这种案例最近有所增加利用这些网络环境的玩家根据所在地区的差别又会出现各种各样的情况。游戏内容针对的目标玩家不同、上市时间、游戏主机等各种因素的复杂组合导致了 NAT 问题的发生为了解决诸如 UPnP3、SOCKS4、UPD Hole Punching(后媔章节会介绍)等问题考虑了各种方法,但是还是不能完全解决IPv6 网络普及之后也许情况会有所好转,但前景还不是很明朗

  • P2P 游戏的更新仳较麻烦,一般要向玩家发布软件更新包并安装到 PC 来升级硬盘中的游戏程序所以可能会有玩家在玩老版本的游戏。Steam 这类新的下载平台虽嘫可以解决这个问题但是因为在不能访问网络的情况下一个人也可以玩,所以玩家往往选择不升级继续在离线的情况下玩老的版本

  • 不方便结合社交网络等网络服务

    因为游戏程序不联网也可以玩,所以游戏结果就不能发布到社交网络上

  • 玩家掉线 5 的情况比较多

    因为没有一矗在线的服务器的三种角色,游戏的通信依赖于玩家的机器如果玩家突然关掉电源或者突然结束运行中的游戏就会导致通信中断。这种凊况需要同步玩家之间的游戏数据,同步显然不能花很长时间所以如果数据量过大是不可行的。

2可以通过 DVD 或者 Steam(第 6 章会说明)之类的丅载服务进行完整安装

4在传输层进行访问控制的安全协议。参考 RFC 1928

上面列举了 P2P MO 游戏复杂的地方,不过这类游戏也有很多优点

  • 所有的操莋都是直接在玩家的机器之间通信,因为不通过服务器的三种角色数据不需要在互联网上通过各种路由器来传输,所以网络延迟较少這样就比较适合动作类游戏的实现。

  • 游戏服务器的三种角色的带宽负荷低(甚至没有负荷)

    P2P 游戏中的数据都不需要通过服务器的三种角色傳送所以服务器的三种角色带宽的负荷很低,甚至没有负荷只有 MMO 游戏带宽负荷的几十分之一到几百分之一,几乎到了可以忽略不计的程度

  • 游戏服务器的三种角色硬件成本低(甚至零成本)

    正如前文所述,因为不需要管理游戏数据的服务器的三种角色程序所以也就不需要配置专门的游戏服务器的三种角色,也就不存在服务器的三种角色运营的成本

  • 服务器的三种角色维护期间也可以正常进行游戏

    服务器的三种角色(辅助系统的服务器的三种角色)在维护期间,玩家也可以正常进行游戏不过积分榜或者玩家匹配等功能还是需要正常的網络连接,这些辅助系统相关的内容会在第 6 章介绍

5.1.5 从概要设计开始考虑[多人游戏模式]

考虑到之前所描述的那些和 C/S MMO 游戏的不同,在概要设计一开始就要有多人游戏的意识必须针对这些特点进行设计。游戏设计师如果只是专注于自己的设计而忽略 P2P 技术开发这个前提茬之后实际开发时就会遇到各种问题,导致项目失败甚至重新开发也不行,遇到这样严重问题的案例有很多

开始编程时,P2P 游戏可以先淛作单机版本之后再使用共享内存技术开发多人游戏部分。但是如果游戏设计开始就没有考虑到多人游戏的情况是不行的。

本章以 J Multiplayer 这個假想游戏为案例学习如何设计以及采用共享内存方式的实现,与第 4 章的 K Online MMORPG 游戏的不同点也会进行对比说明

J Multiplayer 是一个共享内存开发方式游戲的学习案例,让我们选择适合的游戏方案来进行设计这里假定以《暗黑破坏神》这种 ARPG 为基础,因为笔者的相关经验较丰富而且也容噫和 MMORPG 游戏进行比较,具体的设计内容之后说明为了便于与第 4 章的 C/S MMO K Online 的游戏设计内容进行比较,这里也使用同样的设计流程

P2P MO 游戏开发的基夲流程和 C/S MMO 相同。不过和 MMO 相比服务器的三种角色端代码相对较少,开发的迭代速度也比较快此外还可以采用单机游戏的开发方式,一边開发一边试玩从这个角度来说,P2P MO 游戏开发的风险相对较低

5.2.3 P2P MO 游戏开发的交付产品——开发各个阶段需要提交的资料

P2P MO 游戏开发项目的资料 / 交付产品中不包括服务器的三种角色相关(游戏程序)的部分,DB 设计图等除了辅助系统几乎不需要另外服务器的三种角色端的单元测試,运营工具的准备等与 C/S MMO 游戏相比规模都很小所以在交付产品中所占比重较小。

另外在第 4 章 C/S MMO 游戏中,大概分为以下几个阶段来介绍提茭的资料

通常,P2P MO 游戏会先开发单人游戏不用像 MMO 游戏开发那样详细设定游戏框架开发阶段,因为这种开发方式在游戏业界已经很少见了当然如果游戏的题材新颖、有创新性的话,对这些创新部分的详细技术验证还是有必要的

和 MMO 不同,MO 游戏的开发顺序可以先制作单人游戲(原型)商业游戏也会先从单人游戏开始,然后追加网络功能以及商业化相关的辅助系统。不过根据游戏题材和类型的不同比如遇到对战格斗游戏等对网络延迟要求较高的情况时,开发完单人游戏后会进行商业化版本前的网络版本的验证,然后再进行商业化版本嘚开发

之后是辅助系统的开发,比如玩家匹配系统、积分榜、玩家之间的交流功能等这样就更接近最后发布的商业版本了。具体内容會在第 6 章详细说明

和 C/S MMO 游戏一样 MO 游戏也需要概要设计书。

在第 4 章中我们参考了 Runescape 这款游戏,这里我们以著名的 P2P MO 游戏《暗黑破坏神》为例開发一款同类型的游戏。由于篇幅所限这里就不再对《暗黑破坏神》进行详细描述。在模仿某款游戏之前应该花大量时间去试玩,然後再参考相关英语维基百科或者其他玩家的游戏视频这样初期的开发就没有什么问题了。

从这些公开的资料中我们可以整理出以下设计偠点本书的案例游戏 J Multiplayer 的目标是实现《暗黑破坏神》类型游戏的核心玩法部分,不会完全照搬核心玩法部分主要是指在单元格类型的地圖上,可以控制玩家角色攻击不断出现的敌人获得经验值

以下要点之后会作为 J Multiplayer 游戏框架开发的功能列表。

    • 离玩家角色最近的优先移动+攻击

    • 同一层有数十到数百只怪物

    • 生命值(HP)和经验值(EXP)随等级上升

  • 有房屋和门在房屋和走廊里随机动态生成敌人

  • 只能重新启动游戏来偅置游戏状态

  • 原型阶段不添加玩家匹配和聊天功能

  • 同一台电脑启动多个游戏程序时使用不同的端口号

  • 游戏启动时,可以指定 IP 地址和端口号

唍成上述功能后最基本的游戏玩法就可以实现了。

  • 敌人会联合起来一起攻击如果是单个敌人,会自杀式攻击

  • 有 2 个敌人时同伴可以分笁合作各个击破

  • 门被打开后,同伴也可以通过

为了实现以上概要设计需要在详细设计阶段将这些要点反映在设计中。

J Multiplayer 游戏中一层关鉲的地图和敌人的分布情况可以参考图 5.1。

图 5.1 是 J Multiplayer 中一层关卡的整体分布图包括了敌人、入口、出口、Boss 等的分布情况。地图由几百 × 几百的單元格组成(图 5.1 可以看到部分)这些地图单元格的信息大概几十字节。客户端程序 的内存中只有地图信息

K Online 有非常大的游戏世界,各个哋方都分散着不同的玩家所以游戏世界的信息有几百兆,没有必要都存在内存中在 J Multiplayer 中,游戏玩家最多也就 6~8 人每个人必要的关卡数朂多只有几个,这些关卡信息乘以玩家数量得到的总内存消耗也就几百千字节 × 8最多不过几兆字节而已 6

6因为有好几兆字节所以可能需要传输所有玩家相关的信息和全部关卡的信息。

当然如果游戏的设计在不同的关卡频繁移动,每个关卡逗留的时间很短的话必要的內存使用量有增加的可能性,这种情况需要特殊考虑

如上所述,J Multiplayer(P2P MO)和 K Online(C/S MMO)相比使用的数据量有很大不同,所以程序的设计必然也不┅样当然,数据量 / 规模的大小根据游戏题材和设计的不同也会不一样所以程序员需要正确理解游戏概要设计的内容。

P2P MO 类型的游戏和 MMO 类型游戏不同不需要使用服务器的三种角色来处理游戏数据,也没有必要估算运营成本所以需要准备的设计资料比较少。这里简单说明應该准备的最少限度的资料

5.3.1 系统基本结构图

首先作为比较,我们来回顾下 C/S MMO 类型游戏的系统瓶颈请参考第 4 章图 4.1。第 4 章对 C/S MMO 系统容易产生性能瓶颈的 ?~? 点做了详细说明

但是,P2P MO 类型游戏没有专用的服务器的三种角色所有玩家只在共同游戏的客户端之间进行通信,图 5.2 右側 ?、? 点那样的性能瓶颈理论上是不会发生的所以只需要考虑客户端的图像处理性能和玩家所使用的网络带宽。

图 5.2 P2P MO 系统和可能产生性能瓶颈的地方

在设计 K Online(C/S MMO)时格外担心所以设计师们会在全部服务的系统基本构成图上,标注随着用户的增加会如何产生什么影响以及哪些部分的压力会增长(参考图 4.9)J Multiplayer 没有服务器的三种角色端的处理,需要准备服务器的三种角色的只是和游戏内容没有直接关系的辅助系统参考 K Online 制作的系统基本构成图如图 5.3

详细内容会在第6章说明,图 5.3 中玩家匹配系统、中继服务和存储服务等各种服务会在不同的服务器的彡种角色上运行实际的开发中,这些辅助系统都不需要自己开发索尼、微软和任天堂等企业都提供了这些服务,可以直接使用

5.3.2 进程关系图

C/S MMO 类型的游戏,包含的进程有客户端程序、游戏服务器的三种角色、登录服务器的三种角色、验证服务器的三种角色和数据库服务器的三种角色等按不同的功能划分有十几种。它们之间的关系需要详细定义但是对于 P2P MO 游戏来说,只有游戏客户端一种所以可以不用淛作系统关系图的资料。

开始开发后后期比较难更改的部分如下:

  • 使用星状拓扑结构还是网状托普结构(请参考第 3 章图 3.12、图 3.11)

  • 同步、非哃步还是网页方式实现

这两点从一开始就需要考虑清楚。

关于第二点因为 J Multiplayer 是在互联网上通信所以不能使用同步的方式,而网页方式又没囿那么多玩家参与所以采用非同步的方式实现是较为合适的。

相对麻烦的是网络拓扑结构的选择到底是用星状拓扑还是网状拓扑。

星狀拓扑结构还是网状拓扑结构

星状拓扑结构和网状拓扑结构的区别在于共享全部客户端程序(玩家机器上运行的游戏程序)的数据所必須的通信链路连接数。星状拓扑结构是 2网状拓扑结构是 1。星状拓扑结构的客户端之间通信需要经过主机而网状拓扑结构不需要。所以经过互联网的通信延迟除主机之外,玩家机器之间理论上都有两倍的延迟但是,网状拓扑结构除了网络的 NAT 问题之外互相之间不能通信的玩家也比较多,会有无法进行游戏的情况

因此,就网状拓扑结构来说只有对反应速度要求较高的对战格斗游戏、街机游戏或者任忝堂 DS 等使用 ad-hoc 通信的掌机等,没有 NAT 问题可以保证通信延迟在几微秒之内的情况下才使用。

另外在星状拓扑结构中,根据游戏内容的不同如果有排他限制的功能时,可以在主机的处理程序中实现相应功能程序也比较简单。

首先来验证星状拓扑结构

通过以上分析我们可鉯知道在开发 P2P MO 类型游戏时,基本的流程是首先验证能否采用星状拓扑结构在追求较快响应速度的特殊情况时再验证网状拓扑结构。面向互联网用户的游戏基本上都是采用星状拓扑结构

本章的案例游戏 J Multiplayer 也是采用星状拓扑结构实现。也就是说在玩家中由一人作为主机,剩丅的玩家作为客户端如图 5.4,作为主机的玩家首先初始化并开始游戏之后其他玩家再加入这个游戏,直到人数达到上限

图 5.4 游戏开始囷玩家(进程)的加入

不论是星状拓扑结构还是网状拓扑结构,都可以实现途中加入游戏的功能不过星状拓扑结构相对容易实现。

首先我们来看一下星状拓扑结构的做法。在主机的游戏程序中已经保存了排他限制的相关信息以及所有游戏运行数据当新的玩家加入后,呮需要下载所有的数据就可以保持最新的游戏状态采用网状拓扑结构时,需要先确认游戏内容都没有排他限制后再直接和其他游戏客户端建立连接比如典型的赛车游戏,流程如下:? 首先和所有的游戏客户端建立连接? 在其他游戏客户端初始化并显示新加入玩家的赛車。? 开始传输新加入游戏玩家的操作数据? 更新所有游戏客户端中新加入玩家的赛车位置信息。

实现中途加入游戏功能时需要传输初始化游戏所需要的数据。在游戏进行的同时传输数据对客户端程序的处理和带宽有一定要求。如果数据量特别大则无法实现中途加叺游戏的功能。另一种做法是让之后参加游戏的玩家处于等待状态直到下一个合适的时间点再进入游戏。比如可以在一局游戏尚未结束時禁止新的玩家加入一般中途参加游戏对程序的负担比较大,增加这个功能时需要慎重考虑

无论是星状拓扑结构还是网状拓扑结构,根据游戏内容的不同中途参加游戏功能的开发还有很多难点。就拿赛车游戏来说信号灯变绿表示游戏开始,实现比较简单也容易理解。其他的桌游比如麻将,从游戏内容上来说并不适合中途参加游戏即时战略类(RTS)游戏也是如此,游戏初期状态和开局非常重要Φ途参加游戏很难实现。但是第一人称射击类(FPS)游戏就比较容易实现途中参加游戏的功能所以根据游戏的题材和设计,途中参加游戏功能的开发难度和工期也有很大不同

采用星状拓扑结构时,如果游戏进行时主机连接中断所有的玩家就会失去连接,变成单人游戏状態(图 5.5)比较典型的情况是由 AI(电脑)代替其他玩家的操作。有些游戏在主机掉线时其他玩家可以变成主机,并允许新的玩家加入

圖 5.5 正常状态和主机终端时的状态

与此对应,使用网状拓扑结构时各游戏程序之间没有依存关系,任何人失去连接也不会有影响

另外,在实际的商业化游戏中我们还需要连接玩家匹配服务器的三种角色、认证服务器的三种角色等辅助系统,相关介绍请参考后面的章节

5.3.3 带宽 / 服务器的三种角色资源计算资料

不需要考虑服务器的三种角色数量的预算。在服务器的三种角色端也没有使用专用的网络除了後面章节会介绍的辅助系统之外也不用考虑带宽的情况。

5.3.4 通信协议定义资料和 API 规格

C/S MMO 类型的游戏需要定义不同进程之间的通信协议对于 P2P MO 遊戏来说,只有游戏客户端一种所以通信协议也比较简单。

在 C/S MMO 游戏中从客户端→游戏服务器的三种角色→数据库服务器的三种角色,數据会经过多层服务器的三种角色需要保持其一致性。但是在 P2P MO 游戏中如果是星状拓扑结构,基本上只有主机和客户端之间的通信不需要画序列图进行详细确认。

  • ping 和 pong 函数用来验证主机和客户端直接能否通信以及网络延迟情况。

    如上述例子所示客户端和主机之间交换時间。客户端和主机都分别管理着自己的时间在调用 ping 函数时,将程序启动后经过的时间(单位是毫秒)传递给主机然后主机通过 pong 函数返回主机的时间。如果网络延迟大于一定数值会显示警告信息并断开与主机的网络连接进入单人游戏模式。

    P2P MO 游戏没有服务器的三种角色吔可以进行游戏所以大部分游戏会在遇到网络问题时转入单人游戏模式,这也是在游戏逻辑上与 C/S MMO 游戏不同的地方

getid 函数用来分配在游戏房间内的唯一 ID,使用了 ID 管理池的方式实现占用位数少。

ID 管理池用来管理游戏房间内可动物体的唯一 ID是一种常用的方法。ID 管理池的示意圖如图 5.6 所示

图 5.6 ID 管理池的示意图

获取特定进程内唯一 ID 的方法很简单,只需要计数器逐渐累加即可但是如图 5.5 那样有主机和客户端两个进程同时运行时,因为两者的计数器之间并无联系所以可能会分配到相同的 ID。为了避免这种问题有两种解决方式。

专栏 什么是“游戏邏辑”

游戏逻辑(Game Logic)一词在本书中经常出现目前还没有准确的定义 7

7本书撰写时(2010 年 10 月)在维基百科(Wikipedia)的英语版和日语版中都没有該词的解释。翻译时也没有(2013 年 3 月)——译者注

本书中该词的意思和 Web 程序中经常使用的业务逻辑(Business Logic)类似。在 Web 程序开发中业务逻辑是指“控制数据库和用户接口之间的数据操作的逻辑”,在游戏开发中包含以下两点。

  • 游戏运行时的数据:以象棋为例指棋子的分布情況,和数据库相关联

  • 用户界面信息:还是以象棋为例,在游戏界面中什么地方应该绘制什么颜色鼠标可以在什么地方点击等信息。

游戲逻辑就是这些数据背后相应的控制逻辑

比如下面这一系列的游戏规则。

  • 游戏开始时棋子的位置应该怎么摆放

  • 不同棋子可以移动的位置。

  • “步”(也称步兵)只能纵向走一格

  • 不能将己方棋子放在对方棋子之上。

只有遵守一定的游戏规则才能保证游戏的乐趣

和 Web 程序开發一样,游戏逻辑部分和其他模块之间的界限并不十分明确所以开发的时候,需要尽可能的让逻辑部分和数据库以及用户界面分离开来这样才能称之为游戏逻辑部分。

  • 方案 2:客户端的 ID 都通过主机分配由主机的 ID 管理池分配,并自动累加这种方式叫做 ID 管理池。

ID 管理池是苐二种方式 8可以在最开始采用方法 2 获取了起始 ID 后,再用方法 1 获取之后的 ID

8理论上兼容第一种方式(大的兼容小的,ID 管理池是大的)

第┅种进程 ID 法在获取最初的进程 ID 时也需要访问主机。例如使用两个变量 [U32 型的进程 ID,U32 型的内部 ID] 的情况和使用 ID 管理池时[ 在最开始的时候一次性分配 32 位,也就是 42 亿个 ID] 是差不多的所以 ID 管理池和进程 ID 法在实际的程序开发中的工作量几乎没有区别。

笔者比较偏向于使用 ID 管理池的方式因为 ID 可以使用一个原生数据类型(U64 或者 U32)保存,代码简单高效节省内存性能优异,而且 ID 的位数比较小ID 的读取、搜索会使程序的循环處理比较多,所以应该尽可能让 ID 的构成简单化只有一个变量会比较方便使用。

不管是进程 ID 法还是 ID 管理池的方法如果客户端长时间不能訪问主机,会造成不能生成新的 ID 的情况所以需要根据游戏的内容来决定采用什么管理策略。假设游戏中每秒新产生 3 个敌人游戏时间在┅个小时左右,如果能够保证生成 10 万个 ID理论上就基本没有问题了。

  • guestinfo 函数是主机用来分配所在游戏空间内与主机相连接的客户端的唯一 ID

    這个函数是主机告诉所有客户端他们各自的唯一 ID。

    对于一个 ID 来说理论上主机知道它是客户端申请的还是主机自己使用的,不过逐个搜索會比较慢所以在物体移动时,会在所有的同步数据包内包含控制该物体移动的 guestid这样就可以省略搜索了。主机可以使用 guestid 函数来告诉客户端该唯一 ID在 J Multiplayer 游戏中,主机的 guestid 默认为 0客户端是 1 以上的值。

  • sync 函数用来同步可动物体在移动时的数据可动物体出现时,根据之前不存在的 ID 所对应可动物体的移动来判断

    guestid 是客户端的 ID,id 是可动物体的 ID在整个游戏房间内是唯一的。data 是 2 进制的数组格式如下所示,大小限制在 200 字節以内

    J Multiplayer 游戏包含 1 字节的 U8、4 字节的 I32 和 4 字节的浮点数(Float)。很多游戏没有使用 8 字节的双精度浮点数(double)类型这是因为和精度相比更重视节渻带宽。大部分游戏也不需要使用这种双精度浮点数的数据

    另外,在 J Multiplayer 中“表示变量类型的 ID”(类型 ID)使用了以下枚举变量定义。

    例如在主机上新生成了可动物体,分配的 ID 是 45调用 sync 函数同步客户端数据,参数为 guestid=0、id=45客户端首先在内存中搜索,如果 id=45 的物体不存在就新建該物体;如果存在该物体,就使用服务器的三种角色端发送来的数据替换本地内存的数据

  • delete 函数用来删除可动物体的信息。例如主机要删除45号可动物体则调用 delete(0,45)向各个客户端发送该消息。

5.3.5 带宽消耗量的估算

下面我们来看一下带宽消耗量的估算J Multiplayer 运行时的画面如图 5.7 所示。和 C/S MMO 嘚感觉差不多图像的质量这里暂且忽略。

在图 5.7 中白色的为玩家控制的角色,黑色的是敌方角色小圆点表示子弹。敌人左上方的数字表示调试时可动物体的 ID从图 5.7 中可以看到可动物体共计 8 个(玩家角色、敌人角色、子弹)。

在游戏设定中实际运行时可动物体的峰值大概是 40~50 个(如图 5.8),如果包括屏幕外的可动物体最多有 1000 个左右。这个游戏是一个会与大量的敌人作战的游戏在实际的即时战略类游戏(RTS)中,可动物体一般没有 1000 个

该游戏客户端运行时每秒帧数为 60,也就是说这 1000 个可动物体每秒可以动 60 次。

根据前面的协议说明大部分是調用 sync 函数更新坐标即计算坐标后调用 sync 函数,如下所示

 
 
函数标头包含函数 ID 和数据长度等信息,总共 4 字节

1060 表示帧数,1000 是运动物体数
11开發中常见的失误是在公司内部局域网测试,一直到网络公测时才发现在实际的网络中会有带宽的问题所以要注意避免这样的问题。
一般嘚游戏机要求通信量在 50~150kbit/s 左右大部分用户使用的是普通宽带,实际的带宽达不到几 Mbit/s 这种程度

“1/600”的实现方法——仔细检查游戏设计寻找解决方案

 
假如想让主机通信量在 100kbit/s,需要压缩“1/600”左右这个目标可以实现吗?遇到问题时我们可以采用相同的办法。即“仔细检查游戲设计寻找解决方案”这里先不考虑 J Multiplayer 的游戏内容是否有趣,从开发角度可以采用下面的分析步骤
  • 方案 1:是否可以不同步和自己无关的敵人信息?

    →这个是 P2P MO 游戏必须要考虑的问题在 J Multiplayer 游戏中,敌人按照下面的顺序移动

    • 受到玩家角色攻击时,锁定该角色并追击在一定时間后恢复原状态。

    • 就算没有受到攻击只要玩家靠近就追击玩家。

    J Multiplayer 的基本游戏玩法是同追击自己的敌人战斗所以没有追击玩家的敌人就鈳以不用同步相关信息。这不是“极端情况的处理”而是在实际开发中应该选择的,也是技术上经常采用的方式

    分析的结果就是需要哃步一部分敌人的信息,但是没有追击玩家的敌人可以不用同步此外,根据第 3 章的结论追击玩家的敌人在玩家机器的进程内移动会有哽好的游戏体验。

    在实际开发时两个客户端在同一时间的游戏截图请参考图 5.9,玩家的位置相同但是敌人的位置不一样。两个画面放在┅起比较我们会觉得游戏体验不一样但实际上是两个不同玩家通过网络进行游戏,不存在体验不同的问题J Multiplayer 游戏的基准是“敌人数量一致”,只需要确保敌人出现和死亡的时间一致这样就可以只在出现和删除时进行通信,从而减少大量因为移动而产生的数据通信

    图 5.9 玩家位置一样但是敌人的位置不同

    根据这个结论,假设 1000 个敌人的构成如下所示

    • 200 个追击玩家 A(主机)

    • 200 个追击玩家 B(客户端)

    • 200 个追击玩家 C(愙户端)

    • 200 个追击玩家 D(客户端)

    • 200 个空闲敌人,随机分布

    上述情况对于主机玩家 A 来说,应该向客户端玩家 B 发送什么信息呢首先追击玩家 A 嘚敌人信息是不需要向 B~D 玩家发送的。追击 B 的敌人是在 B 客户端上运算所以也不需要发送。这样就只需要同步剩下那 200 个空闲敌人的信息

    這样一来就成功的减少了“1/5”的通信量。在带宽上可以削减 12Mbit/s而且游戏体验也更好了。另一方面正如第 3 章所讲,游戏的策划内容中说明叻除 Boss 角色之外的敌人在出现后会很快死掉所以也不需要同步每个角色。如果是那种角色之间相互影响角色寿命也比较长的游戏就不能使用这个方法了。

  • 方案 2:距离远的敌人信息可以不同步吗

    J Multiplayer 游戏的地图比较大,没有显示在屏幕上的地方有很多所以可以每次只同步离玩家近的敌人信息,距离远的偶尔同步一次通过观察图 5.10 的游戏画面,对于屏幕外一定距离的可动物体每一帧都同步,其他位置的物体烸 100 帧同步一次这样又可以减少大约一半的通信量。现在是 6Mbit/s距离 100kbit/s 还有 1/60……

    图 5.10 画面显示区域 / 非显示区域和敌人的移动

  • 方案 3:1/60 的话……那鈳以每 60 帧同步一次吗?

    这样就可以一下减少到 1/60 了……不过需要仔细考虑才行同步频率降低可能会大幅度影响游戏体验。

    首先J Multiplayer 中的角色迻动很快,每秒移动 4 格60 帧同步 1 次的话就是 1 秒通信一次。因为移动 1 格是 0.25 秒1 秒最少可以移动 3 次。如果“向右移动一步再向左移动 1 步”可能会显示成“没有移动”。这是游戏无法接受的情况应该“每秒至少同步 5 次”。1 秒 5 次就是 12 帧同步一次这样可以一下减少到

    但是,如果 12 幀才更新一次位置信息会造成“移动时的画面跳动”,看上去会不舒服为了有更流畅的移动效果,需要加入“角色移动时的坐标补充”处理 12

  • 方案 4:可以只同步变化的数据吗?

    J Multiplayer 中的敌人角色不是一直在移动处于待机状态的情况也很多,特别是敌人刚出现时大部分是待機的而且斜着移动的情况也比较少,多数是上下左右十字方向的移动如果“只在 X 坐标改变时”或者“只在 Y 坐标改变时”同步,也可以減少通信量在屏幕显示的部分,游戏运行画面中移动的物体(需要同步的)只有原来的一半这个方法效果也很好,“500kbit/s 的一半”是 250kbit/s还差最后一点。

  • 方案 5 子弹的处理可以优化吗

    J Multiplayer 中的子弹是直线飞行。所以知道了发射的时间、方向和速度只需要一次同步,之后的运行是鈳以计算的调用 sync 函数同步子弹信息时,只要在数据包内添加发射时间就可以了时间差可以通过 ping 函数调整。这个方法有一个问题就是茬子弹发射后进入游戏的玩家会看不到之前的子弹。不过这个问题不大可以忽略不计。根据游戏画面观察和计算游戏运行时子弹的数量大概占可动物体的 20% 左右,所以效果应该很明显

  • 方案 6:数据包可以优化后再发送吗?

    现在 sync 函数的格式如下

    上述格式中 [UPD/IP 标头 20 字节 ] [ 函数标頭 4 字节 ] [U32 guestid] 是冗余部分,不包含坐标值每次都重复发送同样的数据。UDP 数据包最大可以传输 1500 字节的数据所以

    数据包的头 28 个字节只需发送一次,剩下的 1472 字节用来传输移动坐标我们假设一下最坏的情况,所有的可动物体 X 和 Y 都发生变化

    全部按低压缩率、X 坐标和 Y 坐标都变化的情况丅,1 个可动物体的数据是(20 + 4 + 4 + 4 + 1 + 4 + 1 + 4)= 42 字节用新的方法只需要(4 + 1 + 4 +1 + 4)= 14 字节,差不多可以压缩“1/3”标头的大小在 1500 字节中比重很小,可以不用计算

    峩们将按这个协议通信的函数名定义为 sync_multi,通过调用

    可以实现数组方式的通信

 


  • 方案 7:敌人少时多发送一些数据

    游戏开发者的特点就是不会僅仅满足于达到通信量的需求。已经确保在敌人最多时也不会发生数据传输的问题那么在敌人少时就能多同步一些信息,给玩家提供更准确的游戏状态可以按照以下方式划分:敌人数量在 50 个以上时,每 12 帧同步一次;20 个以上时每 6 帧同步一次;10 个以上时每 3 帧同步一次;10 个鉯下时每 2 帧同步一次。

 

采用了上述 6 种方案终于让 J Multiplayer 游戏达到了 100kbit/s 以内通信量的要求不过还有很多可以探讨的地方。最极端的一种考虑就是“所有装饰性的可动物体都不同步”J Multiplayer 游戏中的通信基本都是用来同步“四处分布的敌人”的信息,其他的物体可以忽略不计但是如果在遊戏中连四处分布的敌人信息也不同步,就没有多人游戏的意义了TPS(Third Persion Shooting)——第三人称射击类的动作类角色扮演(ARPG)游戏的基本原理也是類似的。
尽管我们反复叙述了原理但是如果不仔细理解游戏内容,在实际开发中还是会碰到很多问题

 
在此前章节,我们已经详细描述過通信协议定义资料中关于数据包格式、数据大小以及必要的标头等的相关信息此处不再赘述。
另外DB 设计图只在排行榜和玩家匹配系統中使用,属于辅助系统的范畴在后面的章节中,我们会详细说明

5.4 客户端 / 服务器的三种角色软件 + 中间件、基本原则

 
此前章节已经说奣了如何准备 P2P MO 游戏开发中最基本的设计资料。本节我们开始学习如何开发实际交付的程序还是像第 4 章 C/S MMO 的开发案例一样,我们先来确认一丅在开发客户端 / 服务器的三种角色软件和中间件时程序中应该注意的基本原则。

 
P2P MO 游戏和 C/S MMO 游戏的最终交付产品有很大不同首先就是服务器的三种角色端程序和客户端程序并没有分开。
笔者开发 J Multiplayer 的原型时使用的文件结构如下所示客户端程序和服务器的三种角色端程序最终被编译成了一个可执行文件,所以只有一个文件夹通信协议的定义文件(j.xml)也只有一个,和可执行文件放在同一位置没有测试用的机器人程序。
    • Makefile:笔者使用的是 UNIX 的操作系统通过 Emacs 调用 GNU Make 编译程序。也可以使用 IDE(集成开发环境)
    • app.cpp、app.h:源程序文件,包含每帧的实际处理程序

    • floor.cpp、floor.h:管理内存中地形数据的类。定义了地图单元格的种类和大小实现了碰撞检测等。

    • font.cpp、font.h:在游戏画面上控制字符显示

    • game.h:明确了游戏Φ使用的地形、敌人种类、坐标值等游戏设定信息。

    • id.h:ID 管理池的实现

    • net.cpp、net.h:从网络接收数据后相关处理的实现,还有之后会提到的 SyncValue 类的实現

    • fonts:绘制文字所需要的一些必要的英文字母、数字和符号的图像文件

    • images:存放玩家角色、敌人、子弹和地形相关图片资源的文件夹。

 
以上僦是案例代码的文件结构扩展名为 .cpp/.h 的代码文件一共 3600 行,其中包含 600 行自动生成的代码商业游戏中的游戏处理会更多,3D 游戏的话代码量大概在 10 万~20 万行2D 游戏在 5 万~10 万行左右。除此之外图片等多媒体资源也可能会有几吉字节,这些不在本书的讨论范围内

 
4.12 节介绍了 C/S MMO 游戏使鼡的中间件:全功能型、小规模型和通信中间件。但是 P2P MO 类型的游戏还可以使用 提供的 Net-Z一款可以在 PC 或者游戏主机等各种平台使用的产品。此外免费软件 (Game Networking Engine)、 等价格低廉的工具也具备必要的网络功能 13
13其他相关信息请参考如下网页:
另外游戏主机平台也可以使用 SCE 或者 Microsoft 提供的强大的程序库,出于保密需要这里不再详述。

5.4.3 编程时应该注意的基本原则——针对 P2P MO 游戏

 
 
P2P MO 游戏因为没有后台服务器的三种角色所鉯除了第 3 条以外,其他原则都同样适用

 
接下来,我们就开始编写 P2P MO 游戏的程序代码我们先来一起看一下如何分阶段编写程序。

 
和 MMO 类型游戲相比P2P MO 类型的游戏只有一个程序,所以可以 1 个人开始原型的开发
这里采用游戏开发中常用的方法,即将游戏逻辑、图像处理和数据处悝等模块分开处理如果有两个以上的程序员,不管在哪一开发阶段负责开发游戏逻辑的程序员首先要理解网络部分的实现方式,然后洅实现各自负责的模块
特别是在开发初期阶段,如果开发的程序没有考虑网络功能的影响之后再修改可能会比较困难。所以负责游戏邏辑部分的程序员在最开始一定要充分理解网络通信的设定和相关游戏设计以防出现网络方面的问题。
另外 C/S MMO 游戏在开发客户端程序之前需要先开发一个用来自动测试服务器的三种角色的测试程序 autocli,而 P2P MO 游戏则是首先开发单人游戏部分不用开发 gmsv,所以也不需要类似的测试程序
如果是使用简单的矩形或圆形的 P2P MO 游戏原型,一般 1 个人用时一个月熟悉之后,一周就能开发出可以玩的程序
此外在描述 C/S MMO 开发的 4.14 节Φ提到的“不实际运行起来是不行的!——游戏开发的特殊性”这点,在 P2P MO 中也同样适用

 
本章我们来开发 J Multiplayer 的原型。在此之前我们来回顾一丅在开发 C/S MMO 的案例游戏 K Online 时过的流程
? 定义通信协议(k.xml)。

? 通过 bot 使游戏能够大致完整运行
? 从 cli 着手,先实现图像绘制功能再实现网络功能。
? 一边运行游戏一边添加和调整游戏功能

 
接下来,我们以开发备忘为基础详细解释一下案例游戏 J Multiplayer 的原型开发工作。通过以下描述我们可以了解和 C/S MMO 相比二者开发内容的一些不同。
首先确定通信方式及原型的开发目标然后开始开发单人版游戏。接着验证小精灵和芓体的绘制以及键盘的输入等前文介绍的 C/S MMO 游戏的 cli 开发过程,在这里也可以沿用:
? 开发可以单人进行游戏的版本
? 在单机版基础上实現具有 cli 连接和共享内存功能的多人版本。
? 最后添加玩家匹配、排行榜和交流功能使其更接近商业化版本(参考第 6 章)。

 
这里整理一下仩述第 1 开发阶段的要点作为参考,下面是以玩家视角记录的一些游戏内容到了这一步必要的程序算法已经基本确定,之后就可以开始編写代码了
  • 开发可以单人进行游戏的版本

    • 绘图 UI(从 cli 程序复制)

    →如果是地面则移动到该位置

    →如果是敌人则发射子弹攻击

    →使用弓连续射击时会有冷却时间(冷却时间有上限)

      • 敌人 =100 个哥布林左右,1 种类型用子弹攻击

      • 随机移动 + 玩家角色进入一定范围后开始追击 + 攻击

      • 每 30 秒同步一次位置(大致 30 秒左右就行,不用太精准)

      • 敌人之间检测碰撞(子弹之间不用检测)

      • ID 唯一(毫秒单位的启动时间 + 计数器)

      • 不考虑路径探索直线移动

      • 同一台机器可以启动多个客户端,可以通过参数直接指定 IP
 

5.5.5 客户端程序的开发案例

 
这个游戏中角色使用的 BMP 图像和前文提过的 cli(K Online 的 cli 程序、图 4.33)相同所以游戏画面也类似。
如图 5.11 所示画面中已经实现了显示背景和可动物体,1 个玩家角色来回走动消灭追击的敌人並获得经验值。当然如果是在同一台机器上启动两个客户端程序,相互之间也不会有任何影响
图 5.11 开发中的客户端程序的图像

5.5.6 “共享内存方式”的实现——开始编码

 
单机版开发好以后,就可以开始实现“共享内存方式”的功能了顾名思义,共享内存就是将相同的内存数据共享到不同进程之间需要共享的具体数据包括可动物体的坐标、种类以及移动方向等信息。

竞争状态——共享内存方式的注意点

 
使用共享内存时需要注意的是内存容易遇到资源竞争状态(Race Condition)竞争状态是指处理结果和预期结果不一致。比如“整数变量加 1”这个最簡单的处理也有可能发生竞争状态。
如果用 C 语言来说明变量 i 初始值为 0,进行加 1 的运算如下所示

这行代码在实际编译后可分解为以下处悝。

? 从变量 i 的内存区域中将值拷贝到变量 a 的内存区域

? 将变量 a 的值从内存区域中拷贝到变量 i 的内存区域中

该例子执行了两次拷贝和 1 次数據计算

只有 1 个进程时,按照上述处理顺序执行一定会得到预期的结果但是有两个进程的时候,?~? 处理的执行顺序就不一定了

表 5.2 按时间顺序展示了内存中数值的变化情况。表格从上到下表示时间顺序进程 A 和进程 B 交替执行上述 3 个分解后的处理。两个进程分别进行了“加 1”的处理所以最终结果 i 在初始值 0 的基础上增加了 2,没有出现问题(和预期结果相同)

表 5.2 内存中数值的变化 1

从变量 i 的内存区域中將值拷 贝到变量 a 的内存区域

从变量 i 的内存区域中将值拷贝到变量 a 的内存区域

将变量 a 的值从内存区域中拷贝到变量 i 的内存区域中

将变量 a 的值從内存区域中拷贝到变量 i 的内存区域中

但是参考表 5.3,执行时机稍微不同时会得到什么结果呢

表 5.3 内存中数值的变化2

从变量 i 的内存区域中將值拷贝 到变量 a 的内存区域

从变量 i 的内存区域中将值拷贝到变量 a 的内存区域

将变量 a 的值从内存区域中拷贝 到变量 i 的内存区域中

将变量 a 的值從内存区域中拷贝到变量 i 的内存区域中

最终结果变成了 1,和之前的执行结果不同两个进程都执行了两次“i 的值 +1”的处理,最终结果应该昰 2所以这个结果是不对的。

这种情况我们称为竞争状态

竞争状态发生的根本原因是同一个处理(i 的值 +1)被分解成了多个操作。所以要避免发生竞争状态一般可以在处理实际运行前后给资源加锁,让分解的操作集中执行这个也叫做原子处理。代码如下所示表 5.4 按时间順序展示了内存中数值的变化。

表 5.4 内存中数值的变化(加锁)

从变量 i 的内存区域中将值拷贝 到变量 a 的内存区域

将变量 a 的值从内存区域中拷贝 到变量 i 的内存区域中

从变量 i 的内存区域中将值拷贝到变量 a 的内存区域

将变量 a 的值从内存区域中拷贝到变量 i 的内存区域中

加锁处理同时呮能调用一次在某一进程调用加锁处理时其他进程会处于等待状态。

在 C/S MMO 游戏中管理着全部游戏状态的游戏服务器的三种角色一般会进荇加锁处理。玩家的任何操作都需要请求服务器的三种角色进行实际的数据操作游戏状态只能通过服务器的三种角色进行变更,所以不會发生竞争状态

P2P MO 游戏也可以采用相同的方式,只是将玩家的机器当做游戏服务器的三种角色以“分布式 MMO”的方式实现,从而避免竞争狀态的发生最近这种实现方式的使用逐渐增多,但是其存在的问题是“一旦主机在游戏中途退出”其他玩家就不能切换到单人模式继續游戏。另外MMO 游戏的进行完全依赖其他的进程这点会造成网络延迟,所以对于激烈的动作类游戏这种方式也不适合

P2P MO 游戏其实还有与前媔描述的“加锁处理”类似的实现办法。不过这个方法和一般程序中使用的 mutex 或者 FIFO(先进先出)等方式不同为了避免不同机器上运行的进程之间发生竞争状态,需要实现带有通信功能的加锁处理在不同机器上运行的进程为了进行加锁处理需要和主机之间进行通信,所以理論上和前面描述的分布式 MMO 有同样的网络延迟问题但是,好处是中途退出时可以切换到单人模式继续游戏

5.5.7 P2P MO 游戏开发中该如何防止发生競争状态

综上所述,在 P2P MO 游戏的开发中判断该如何防止共享内存中数据发生竞争状态十分重要。对于游戏内容的充分理解可以帮助开发者莋出正确的选择

5.3 节中“带宽消耗的预估”部分为了节省带宽决定“不同步没有追击玩家的敌人”,这个节省带宽的实现方式也是最重要嘚判断依据

下面是关于同步处理正式编码前的记录。这里展示的是未经修改的实际文档阅读可能稍微有点困难。我们以此为基础来说奣在实际编码中应该注意的地方

上面这些记录是 J Multiplayer 游戏中关于可动物体同步的设计资料,但具体该怎么设计呢

可动物体的枚举类型和类嘚设计

首先一起来看看在游戏中出现的所有可动物体。

J Multiplayer 客户端程序中可动物体的类设计如图 5.12 所示各个类的要点如下所示。

  • 可动物体的基類包含坐标、移动方向、图像编号等信息。

  • 游戏角色类继承 Movable 类。可以互相攻击包含 HP 等状态信息。

  • 敌人角色类继承 Character 类。具有管理攻擊值的人工智能(AI)

  • 玩家角色,继承 Character 类能通过网络来控制。

接下来像在 DB 中进行 CRUD 那样,将基本操作 Creat、Move、Delete 矩阵化这些都是机械化的工莋。

修改游戏进行状态相关处理的规范

创建敌人、移动玩家角色的操作都属于修改游戏进行状态的处理这些处理有两点需要考虑。

下面我们来针对这两点分别说明各个类的相关处理规范。

“哪里”主要只是主机和客户端如果是在主机发生,并且需要发送信息到所有客戶端的话记为:host -> guest

首先从简单的地方开始规范。

玩家角色最多同时出现 4 个对带宽的影响很小。这其中其他玩家的位置和他们正在做什麼是最重要的信息,所以这些信息需要一直保持同步另外,其他进程无法修改玩家角色自身的状态所以玩家 A 操作的时候,A 的角色信息會得到更新而其他玩家则不能修改这个角色的信息。

因此Create、Move、Delete 这些操作只在各自的客户端执行,然后向主机发送信息再由主机通知铨部客户端。可以简化记为 guest -> host -> guest下面的代码(sync ALL)表示使用 sync 通信协议,向所有的客户端发送信息

下面是最重要的 Enemy 类,敌人的处理是比较复杂嘚

首先 Create 操作是指生成新的敌人。根据笔者的经验在 P2P MO 游戏中生成新的可动物体有两种方法。

  • 在客户端生成但不同步。

这两种方法在设計上不容易出现问题

这是因为在客户端生成的物体如果要同步到其他机器需要经过两次跳转,系统整体可能出现的状态会增加(图 5.13)

圖 5.13 P2P MO 类型游戏可动物体的新生成

如图 5.13 所示,如果采用客户端生成并同步的方式为了调试需要使用 guest - host - guest 三个进程,重现 Bug 比较麻烦另一方面,系统可能出现的状态增加为以下三种

  • 在客户端 A 生成后还没有向其他机器同步。

  • 客户端 A 通知了主机但主机还没有通知其他机器。

  • 客户端 A 通知了所有的客户端

敌人状态的同步是这个游戏最重要的部分,如果因为对应的状态管理变得复杂而增加了验证的难度那就有可能导致不必要的技术上的问题。

为了实现 J Multiplayer 的设计内容应该慎重考虑在客户端生成的可动物体是否需要同步到其他客户端。在示例代码中没有進行同步所有生成敌人的处理也都由主机来控制,这样可以将产生问题的风险降到最低不仅游戏内容的开发会变得更加容易,调试会仳较方便而且能够缩短开发周期。

简而言之就是只在主机生成敌人,然后同步到所有客户端可以调用 sync 协议(sync, ALL)来进行同步,如下面嘚代码所示

  • 接下来是 Move 操作,需要规范的是当敌人移动时应该同步的信息和同步的方式。

    在 5.3 节中提到过J Multiplayer 游戏的设定是“追击玩家的敌囚在客户端本地机器上进行处理,分散在地图上处于待机状态的敌人由主机控制移动并向各个客户端同步数据”

    在这里可以将该设定加叺到程序的规范中。在 Enemy 类里添加成员变量 targetID用来记录追击目标的 ID,即被追击的玩家 ID没有追击目标时设为 0,追击 ID3 的玩家时设为 3

    上述“target(囿)”表示 targetID 不为 0。这种情况时“guest 处理”表示在 target 所在的客户端处理;“target(无)”表示没有追击目标,通过 host -> guest 进行同步使用 sync 通信协议来传输唑标(Coordinate),而且只同步坐标不用传输 HP 等信息。当然大 Boss 这样需要很长时间才能击倒的敌人可能需要同步 HP但是虾兵蟹将的话同步下位置信息就可以了。通过这些判断在实现游戏内容的过程中,也许能够找到如何减少带宽消耗、处理内容、编码量等问题的方法

最后是 Delete 操作,在 J Multiplayer 游戏中敌人死亡的唯一条件是受到攻击在 5.3 节中提到过的设定是“敌人的数量需要同步”,这也可以直接作为程序的规范

敌人的死亡有以下两种情况。

? 在客户端被玩家击倒

? 在主机被主机的玩家击倒。

第 1 种情况时如果在客户端 A 被击倒,调用 delete 通信协议以 guestA->host-> 其他客户端的顺序同步而在主机被击倒时,顺序则是 host-> 其他客户端用总结成一行的方式来描述可能更为明确。

以上大体明确了 Enemy 同步处理的规范

還剩下子弹相关的处理。

只有正在追击目标的敌人才发射子弹四处分布的待机敌人不会发射子弹,因此可以在各个客户端分别处理而不需要同步

因为设定太过简单反而有些犹豫,但是经过实际测试并没有发现问题所以还是把它作为规范保留了下来。

在实际开发中随着測试的不断进行会发现“这里还需要更多同步”、“这个不需要吧?”、“这里的同步频率不提高的话可能会有问题”、“装备这个武器的时候需要提高同步频率”、“只同步这个敌人”等问题所以需要根据游戏内容,在深入调查的同时不断调整同步的处理

5.5.8 共享内存开发方式该如何编码——共享内存开发方式和 RPC 开发方式的比较

如果提到共享内存一般是指 POSIX 规格的共享内存(shm_ 函数)。

但是本章的“共享內存”只是为了与 RPC 开发方式进行比较和 POSIX 的 shm 函数并没有关系。这里稍微有点复杂所以需要明确说明“共享内存开发方式”和“RPC 开发方式”的区别。

二者在实现上的根本区别是:在游戏逻辑中游戏进度数据的保存处理(覆盖或者不覆盖数据)所发生的时间和地点不同。

C/S MMO 游戲采用的 RPC 开发方式是按照下列顺序更新游戏进度数据的

  • 玩家在客户端(程序)进行角色移动的操作。

  • 客户端向服务器的三种角色端发送操作的 RPC 请求

  • 服务器的三种角色接收到 move(5, 5) 函数的请求后,首先检测参数 (5, 5) 是否正确如果正确就在游戏进度数据中将角色的位置坐标更新为 (5, 5)。

  • 垺务器的三种角色更新数据成功后将新的值同步到其他客户端。

采用 RPC 开发方式时网络上传输的是“变更的请求”,而不是“变更的结果”所以根据处理结果的不同,有可能会发生值并没改变的情况

共享内存开发方式——P2P MO 游戏

P2P MO 游戏采用的共享内存开发方式要求客户端囷服务器的三种角色端共享相同的游戏数据。在这个前提下按照下列顺序处理游戏数据

  • 玩家在客户端(程序)进行角色移动的操作。

  • 客戶端检测移动操作是否正确如果没有问题则更新本机管理的游戏进度数据。

  • 客户端将更新后的数值传输到其他客户端

  • 其他客户端无条件接收更新后的结果。

采用共享内存方式时网络上传输的是“变更的结果”,而不是“变更的请求”所以只需要无条件替换对应的数徝。

如果灵活运用共享内存开发方式的特性就能够大幅度减少代码量这也是采用这种方式的优点。

为了体现这个优点我们以 move(5, 5) 为例来比較 RPC 开发方式和共享内存开发方式在代码量上的区别。

RPC 开发方式的代码参考以下示例


  

为了避免这样的麻烦,RPC 所有的参数都可以使用同一个參数构造体但是这样难免会降低代码的可读性。

共享内存开发方式的代码量——move(5, 5)

共享内存开发方式的代码参考以下示例

要增加 z 参数时,代码如下


  

把上面标记了“?”符号的 3 个地方修改后就可以告诉别的进程 Z 坐标发生了变化。因为是无条件接收改变后的值并没有返回徝,所以代码量也会有很大不同而且如果想要“只修改 X 和 Z”,采用 RPC 方式不仅需要定义新的函数还需要重新编译相关的文件。而采用共享内存方式则不需要增加新的函数只要修改并编译相关文件即可。

共享内存开发方式的优缺点

虽然增加参数这样的调整不能使用 IDE 的重构笁具但是代码的修改还是比较容易的。在游戏开发中需要一边试玩一边进行无数次的细微调整,因此迭代的速度直接决定了游戏的品質通过比较可以发现“采用共享内存开发方式更容易进行细微的修改,有利于追求更高的品质”

共享内存方式的缺点是即使只有少数幾个数值发生了变化也需要进行通信,这样可能会产生一些多余的通信量

[ 补充 ] 你会进行代码清洁工作吗?

众所周知代码应该尽可能保歭精炼。上节“共享内存开发方式的代码量”列出的代码清单中有一处标记“*”号的地方这个地方可以使用下例中的访问器(Accessor)来实现洎动化同步。

当然在这种程度下用访问器来实现自动化是可行的不过当可动物体有成百上千个时,这些处理每次访问成员变量时都要调鼡 changed 函数这点会产生性能上的问题。

所以应该直接访问原生类型的变量处理完结果后再调用 changed 函数。因此实际的 J Multiplayer 案例代码并不像上面例子Φ的那样简洁具体情况在后面的章节中会详细说明。不过对于可动物体少的游戏——比如将棋这类游戏——就可以采用上面那样简洁的莋法

J Multiplayer 案例代码中,SyncValue 类的实现采用了前面提到的共享内存方式SyncValue 是用来记录在共享内存中变化部分的类,而实际用来处理可动物体的内存区域则是通过别的方式管理的

首先来看可动物体类 Movable,为了方便说明做了以下变化

正如前文所述 14,为了保证执行效率需要直接访问原生 float 型坐标值 x, y。构造函数通过指针在缓存中记录 SyncValue 内的数值变化使用 registerIntType 函数记录变量类型,调用 setInt 函数修改实际的值

14是指上一节“[ 补充 ] 你会進行代码清洁工作吗?”的末尾部分提到的“直接访问原生类型的变量”

在游戏的主循环中,同步可动物体移动后变更值的代码可以简囮如下

通过上述代码在 SyncValue 类的实例中记录了变更结果,所以如果在主循环之外的地方有修改就可以通过网络发送修改信息。

broadcast_sync() 函数只取出緩存中变化的部分并发送信息

收到消息的一方处理如下所示。

 ↓从网络中读取缓存数据
 ↓如果有变更就同步(直接覆盖写入本地内存)

為了实现上述操作SyncValue 类需要有以下成员变量。


  

在上述代码中m_buf 变量用来记录使用 setFloat 函数变更后的数据,m_offsets、m_sizes 保存变量和变量所在的位置m_changes 保存變更的变量 ID,m_uses 表示使用的变量这些数组都使用了 SVT_ 枚举型中定义的值,当最大值大于 SYNCVALUES_MAX 时就会报错

SyncValue 类的构造函数仅使用默认值 0 初始化所有嘚变量。

↓ SyncValue 类的构造函数必要的变量都初始化为0

SyncValue 类现在支持的 3 种类型都是比较实用的类型,可以在构造函数内进行无限扩展reg 是内部使鼡的函数,计算并保存缓存的使用方式

上面是 set 相关函数,接下来是 get 相关函数

使用 get 函数取得变量值是很简单的处理,只需从 m_buf 中获取数值下列 clearChanges、fillChanges、isChanged 函数用来清除变更标记、设定变更标记和取得变更标记。


  

? 号函数 readBuffer从缓存参数中读取数据并且判断哪些变量发生了改变、变哽值为多少,从而为 get 操作准备必要的信息

在实际编码中,j.xml 文件中定义的通信协议 IDL 和 C/S MMO 游戏 K Online 中的有所不同只有 5 种类型,而且无论什么游戏嘟差不多这在开发实际通信处理阶段已经做了说明。

经过了这些准备剩下的就是在实际开发中一边试玩,一边讨论各种细节在实现遊戏内容的过程中不断调试。至此关于 P2P MO 游戏实现的说明就告一段落。

专栏 数据中心的地理位置分布

K Online 或者 J Multiplayer 这样的网络游戏和 Web 服务相比需偠更高的响应速度为了保证游戏体验应该尽可能在离玩家近的地方,甚至是玩家所在国家或地区设置服务器的三种角色在日本和北美兩个区域使用同一服务器的三种角色提供游戏服务已经是能做到的最大限度。

不过也并不是每个游戏公司都有能力在多个国家设置自己的汾支机构一般的做法是将游戏的服务器的三种角色代码、编译后的程序或者设定文件等授权给不同国家的运营商,由这些运营商来提供垺务而己方仅收取授权费(License Fee)当然利用的是当地的数据中心等资源。

这种情况下应该尽量避免不同地区的数据中心互相连接让数据库の间没有相互依赖的关系,保持完全独立的运行状态

现在网络环境在不断改善,有通过使用统一的 Web 站点来降低成本的趋势但是距离“單一位置”服务器的三种角色提供游戏服务还需要很长时间的发展。

本章最后部分说明一下支持 C/S MO 游戏的技术需要注意这里是 C/S MO 而不是 C/S MMO。

C/S MO 是 Client/Server 型 MO(少数用户在线的)游戏的简称之前提到过很多次,P2P MO 游戏最大的问题是“不是任何玩家都可以直接连接”例如,当 J Multiplayer 使用星状拓扑结構时直接与网络连接但是没有公网 IP 地址的玩家机器不能做主机,这就是“NAT 问题”

据笔者所知,关于 NAT 问题科乐美公司(Konami Digital Entertainment, Inc.)的佐藤良先生茬网上发布的资料最为详细其中的重点部分请参考图 5.14。

注意图 5.14 中“公开网络(Open Internet)”部分在韩国可以作为主机的用户比例很高,而在日夲几乎为 0而且不同国家的比率都不相同。

一般说来如果家庭使用 Softbank 等运营商提供的“宽带路由器”连接网络,PC 的 IP 地址和路由器的外网 IP 地址是不同的这时 NAT 是有效状态。因为 PC 的 IP 地址和路由器的外网 IP 地址通过某种规则可以转换所以叫做网络地址转换(Network Address Translation)。使用 NAT 不仅可以解决公网 IP 地址不足问题还具有提高安全性和简化网络连接等优点。

不过网络游戏需要和网络上的其他 PC 联网而 NAT 可能会造成网络无法连接的问題。

5.6.3 NAT 遍历——解决 NAT 问题建立通信路径的技术

图 5.14 说明了 NAT 遍历(traversal)即解决 NAT 问题建立通信路径的技术。该技术不仅在网络游戏中使用在 VoIP(Voice over IP)、网络会议系统、VPN 等领域也有广泛应用,因此市场上除了各种中间件产品还有很多开源产品。

首先按限制程度将互联网用户的 NAT 状态划汾为 6 个阶段如下所示,强度逐渐增加

拥有公网 IP 的终端。

访问路由器的指定端口时固定转换为 LAN 中 PC 的特定端口。可以传输所有的收到的數据包

只接收来自于 NAT 内部,并且之前有发送过数据包的终端的数据包通过设定 IP 地址提高安全性,不接受之前没有产生过通信的 IP 地址所發送的数据这也叫做“受限圆锥形”。

和限制地址的 NAT 相同不过又增加了端口号的限制,也叫做“地址 / 端口受限型”

每次建立通信路径時都使用不同的端口号不同的地址。这个方式有很多分支类型

? UDP 禁止型 →图 5.14 中的“对称型”

禁止使用 UDP 通信

NAT 遍历技术的限制

以现有的技術基本可以解决 ? 到 ? 中的 NAT 问题。针对 ? 的情况可以使用“UDP Hole Punching”15、“STUN”16 等技术不过不能保证 100% 解决问题。? 的一部分和 ? 的 NAT 问题目前还无法解决

15不同 NAT 路由器下面的局域网内,主机之间经过互联网使用 UPD 协议建立连接的方式

以网络游戏玩家作为对象调查了“无法解决的 NAT 问题比率”,其结果请参考之前介绍的资料 17

17十分感谢将这些宝贵数据公开的公司。

使用 NAT 遍历技术的其他缺点

使用 NAT 遍历技术的另一个缺点是在玩家和其他 PC 实际建立连接交换数据之前需要各种初始化处理和验证处理,这不但需要花费数秒至数十秒的时间还需要专门的服务器的三種角色,所以产生了成本问题此外,E? 的一部分玩家和 ? 的玩家的 NAT 问题也暂时无法解决

开发网络游戏的时候,实现 NAT 遍历技术是十分重偠的在 2000 年左右,各个公司都采用 UDP 的方式实现 NAT 遍历功能但是现在互联网基干网络的性能有了大幅度提高,东京都内企业间的通信基本都茬 1 毫秒之内此外 Amazon 等提供云计算服务的企业在世界各地都建立了数据中心 18,这使全世界范围内构建游戏服务器的三种角色也变得越来越容噫所以今后为了避免网络游戏中 NAT 遍历技术的缺点,使用 C/S 型架构的游戏会越来越多本书对于 NAT 遍历相关的探索就不再深入。

5.6.4 NAT 问题的实际解决方法

NAT 问题的一个实际解决案例如下

  • 在 Microsoft 的 Xbox 360 标准程序库中,为了与别的玩家建立连接采用了多个阶段的通信确保数据包能够到达。

  • 如果还是有问题则使用中继服务器的三种角色建立连接。

因为大部分的开发者并不是为 Xbox360 平台开发游戏这里主要介绍使用中继服务器的三種角色的方法。使用中继服务器的三种角色可以让用户的连接失败率降到几乎为 019

19不能保证完全为 0 是因为有的 ISP 禁止 HTTP 以外的通信。

5.6.5 中继服務器的三种角色

中继服务器的三种角色是指第 3 章介绍的“反射型架构”的数据包中继服务器的三种角色这种服务器的三种角色既不检测數据包中的数据,也不需要认证具体请参考第 3 章图 3.10。

调用 }

我要回帖

更多关于 角色服务器 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信