面向Web服务的游戏设计6:不同客户端的精灵运动同步

由于网络延迟和轮询间隔的影响,在一个客户端操作精灵运动,其运动结果并不能马上反映到另外一个客户端上,时间上相对滞后一些,造成该精灵在两个客户端的运动不同步。本文试图寻找一个预测算法,从延迟的运动数据来预测真实的数据,从而解决运动不同步的问题。
 
为方便讨论,我们假设以下环境。
  • 客户端把自己的精灵运动数据发送给服务器,然后另一个客户端从服务器取得数据。
  • 服务器不主动更新客户端数据,必须由客户端发起服务请求,获取数据。
  • 所有客户端的时间严格同步,即同时向服务器发送服务请求。
  • 设定轮询间隔为1秒,即客户端每隔一秒向服务器发送一次服务请求。
  • 忽略网络时间延迟(毫秒量级),假定两个客户端的时间延迟完全由轮询间隔造成。
从上面假设可以得出,在第一秒客户端A把精灵运动数据发送给服务器,由于客户端服务请求时间严格同步,客户端B必须在第二秒的服务请求时才能得到该精灵数据。也就是说,精灵运动数据在客户端B相对于客户端A滞后一秒。如果不做任何处理,根据原始数据来生成动画,会发现客户端B总是在重复客户端A一秒前的运动轨迹。

本文提出的预测算法其实很简单。为简化讨论,我们只考虑三个因素:时间,位置和速度,不考虑加速度等额外因素。在第二秒,客户端B获得的是客户端A第一秒的精灵运动数据:LocationA(t1),SpeedA(t1)。假设此时精灵在客户端B的位置为LocationB(t2)。我们需要根据LocationA(t1),SpeedA(t1)来预测第三秒的真实位置EstimatedLocationA(t3)。最后设定从LocationB(t2)到EstimatedLocationA(t3)的精灵运动动画。如果每次的预测位置都与真实位置比较温和的话,在客户端B的精灵动画应该与客户端A大致同步。

预测公式:
EstimatedLocationA(t3)= LocationA(t1) + SpeedA(t1) * (t3 - t1)

理论上似乎可行,具体实现上会是什么效果呢?我用silverlight制作了一个模拟程序,来观察和检验实际效果。在模拟程序中,红色的方块A模拟客户端A上精灵的运动,蓝色的方块B模拟客户端B上精灵的运动。从运行可以看到蓝色的方块B的运动总是滞后红色的方块A一秒启动。由于蓝色的方块B的速度大小和方向总是根据红色的方块A的预测位置而修正,蓝色的方块B逐渐与红色的方块A靠近并重合。

从模拟程序观察结果可以得出下面结论:
  • 当红色的方块A做匀速直线运动时,预测效果最好,蓝色的方块B很快与红色的方块A靠近并重合。
  • 当红色的方块A频繁改变方向时,预测的效果不是很理想,蓝色的方块B与红色的方块A经常南辕北辙。此时需要修正蓝色的方块B的速度因子,使蓝色的方块B不会在错误的方向上跑得太远。

总的来说,预测的效果主要与轮询间隔,精灵速度等因素有关。本文提出的算法比较原始,更智能的算法会考虑更多的因素,来减小频繁改变方向带来的误差。

最后需要说明的是,如果预测算法带来的误差太大,其效果可能还不如直接用延迟的数据。例如,我们可能不希望看到精灵走到河里或钻进石头里。
 
代码在这里下载( http://files.cnblogs.com/erichan/SpriteSync.rar)。具体算法请看里面注释和源码。定时器部分参看这里( http://www.cnblogs.com/erichan/archive/2010/05/12/1733130.html)。

转载于:https://www.cnblogs.com/erichan/archive/2011/06/23/2088372.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值