小谈网络游戏同步
有个解决方案,我给它取名叫 预测拉扯,虽然有些怪异了点,不过基本上大家也能从字面上来理解它的意思.要解决这个问题,首先要定义一个值叫:预测误差.然后需要在服务器端每个玩家连接的类里面加一项属性,叫timemodified,然后在玩家登陆的时候,对客户端的时间与服务器的时间进行比较,得出来的差值保存在timemodified里面.还是上面的那个例子,服务器广播消息的时候,就根据要广播对象的timemodified,计算出一个客户端的currenttime,然后在消息头里面包含这个currenttime,然后再进行广播.并且同时在玩家a的客户端本地建立一个队列,保存该条消息,只到获得服务器验证就从未被验证的消息队列里面将该消息删除,如果验证失败,则会被拉扯回p1点.然后当玩家b收到了服务器发过来的消息“玩家a从p1到p2”这个时候就检查消息里面服务器发出的时间与本地时间做比较,如果大于定义的预测误差,就算出在t2这个时间,玩家a的屏幕上走到的地点p3,然后把玩家b屏幕上的玩家a直接拉扯到p3,再继续走下去,这样就能保证同步.更进一步,为了保证客户端运行起来更加smooth,我并不推荐直接把玩家拉扯过去,而是算出p3偏后的一点p4,然后用(p4-p1)/t(p4-p3)来算出一个很快的速度s,然后让玩家a用速度s快速移动到p4,这样的处理方法是比较合理的,这种解决方案的原形在国际上被称为(full plesiochronous),当然,该原形被我篡改了很多来适应网络游戏的同步,所以而变成所谓的:预测拉扯. 【程序编程相关:JNLP文件模板】
同步在网络游戏中是非常重要的,它保证了每个玩家在屏幕上看到的东西大体是一样的.其实呢,解决同步问题的最简单的方法就是把每个玩家的动作都向其他玩家广播一遍,这里其实就存在两个问题:1,向哪些玩家广播,广播哪些消息.2,如果网络延迟怎么办.事实上呢,第一个问题是个非常简单的问题,不过之所以我提出这个问题来,是提醒大家在设计自己的消息结构的时候,需要把这个因素考虑进去.而对于第二个问题,则是一个挺麻烦的问题,大家可以来看这么个例子:比如有一个玩家a向服务器发了条指令,说我现在在p1点,要去p2点.指令发出的时间是t0,服务器收到指令的时间是t1,然后向周围的玩家广播这条消息,消息的内容是“玩家a从p1到p2”有一个在a附近的玩家b,收到服务器的这则广播的消息的时间是t2,然后开始在客户端上画图,a从p1到p2点.这个时候就存在一个不同步的问题,玩家a与玩家b的屏幕上显示的画面相差了t2-t1的时间.这个时候怎么办呢? 【推荐阅读:如何使用Windows事件查看器和微软知】
另外一个解决方案,我给它取名叫 验证同步,听名字也知道,大体的意思就是每条指令在经过服务器验证通过了以后再执行动作.具体的思路如下:首先也需要在每个玩家连接类型里面定义一个timemodified,然后在客户端响应玩家鼠标行走的同时,客户端并不会先行走动,而是发一条走路的指令给服务器,然后等待服务器的验证.服务器接受到这条消息以后,进行逻辑层的验证,然后计算出需要广播的范围,包括玩家a在内,根据各个客户端不同的timemodified生成不同的消息头,开始广播,这个时候这个玩家的走路信息就是完全同步的了.这个方法的优点是能保证各个客户端之间绝对的同步,缺点是当网络延迟比较大的时候,玩家的客户端的行为会变得比较不流畅,给玩家带来很不爽的感觉.该种解决方案的原形在国际上被称为(hierarchical master-slave synchronization),80年代以后被广泛应用于网络的各个领域.
... 下一页