AS3多人游戏开发—同步人物移动1
在实时性要求比较高的多人游戏中,我们将面临不同客户端间的同步问题,而其中人物移动的同步是最常需要考虑的。这篇文章将描述作者对这个问题的一些思考和解决方案(基于ActionScript3)。
大多数RPG游戏中,人物的移动是由鼠标点击激发的,本文将着重探讨这种移动方式,关于鼠标控制移动的同步,我们以后的文章将会涉及。
最简单的方式是你不断广播自己的当前位置,其他玩家收到数据的时候将对应的人物放到那个位置上去,然而这样却会造成其他玩家电脑上人物移动不平滑,因为他们总要等到位置数据后才能更新显示。你可以通过提高发送频率来减少这种不平滑的感觉,但这会增加了带宽的消耗。
现在说下我自己使用的方法,这也是目前最常用的解决人物移动同步的方式。
当我点击鼠标,人物开始移动的时候,我会发送以下数据给服务器,让其广播给其他玩家
// avatar movement start time public var startTime:Number // avatar's destination public var endPoint:Point // avatar's current position public var currentPoint:Point // avatar's speed public var spd:Number
我们会发送人物开始移动的时间,人物的目的地坐标,人物的当前位置坐标,以及人物的速度(如果速度是不变的,就没有必要每次都发送)。我们现在来看看其他玩家的电脑如何通过这些数据来同步人物的移动的。
玩家1控制着他的人物avatar1,玩家2电脑上有avatar2,它是avatar1在玩家2电脑上的模拟。玩家1点击了鼠标,他的人物avatar1开始移动,同时这些数据被发送出去,玩家1收到了数据,他可以通过自己的时间减去数据包中的startTime,得到当avatar1开始移动后经过的时间间隔passedTime(请注意这里的时间都是指服务器时间,而不是玩家自己电脑上的时间,不同的客户端必须要用统一的时间标准-服务器时间,这是同步的基础。关于客户端如何同步服务器时间,我们以后的文章会详解)。然后通过数据包中的spd,currentPoint和endPoint,获得avatar1到达目的地的时间endTime。实际上,我们目前只有endTime-passedTime的时间来移动玩家2电脑上的avatar2。要想让avatar2和avatar1同时到达目的地,我们可以提高avatar2的移动速度。这种做法确实可以让avatar1和avatar2在停止运动的时候处于同一位置,但是在运动过程中,他们的位置无法同步,因为avatar2总是在追赶avatar1,虽然他们的距离越来越小。
我们还可以用更优雅的方式来同步他们的移动,那就是在最开始,avatar2使用一个更高的速度,然后在某一个时间点追上avatar1,然后再和avatar1以同样的速度移动,最后到达终点。时间点的选择权在你自己手中,时间点越靠前,你的同步越早,但是最开始的速度也最大,会影响用户体验。反之同步的时间越晚,但速度变化不明显,移动更平滑。
原理就是这样,在AS3环境中,我们必须摒弃基于帧速的移动,因为不同性能的电脑将会有不同的帧速,让你产生不同的移动速度。要解决这个问题,我们可以使用getTimer()这样的代码来创建自己的基于时间运动的程序。这并不复杂,原理就是在每一帧中判断经过了多少时间,然后通过时间和速度计算应该达到的位置。对于我们的avatar2,它的运动分为了两个阶段,第一个阶段的速度比avatar1快,第二个阶段是的速度和avatar1一样。这两个都是直线匀速运动,所以代码编写很容易。当你实现了这个功能后,如果你有足够的勇气,可以尝试使第一阶段先加速,再减速,在时间点的时候正好达到和avatar1同样的速度。这将使两个阶段的衔接更平滑,带来更好的用户体验。
在你自己尝试的过程中,专门配备一台服务器供你测试是很奢侈的,我们可以很简单的在客户端自己模拟网络延迟。我是这样做的,我在自己的代码中同时创建了avatar1和avatar2,每次我操作avatar1的时候,会延迟给avatar2赋值(模拟广播数据),这很不错,因为你可以随意改动延迟的时间。当你看到avatar2很执着的追赶上avatar1,然后他们并肩前行并一齐到达终点的时候,你会觉得努力没有白费。
下次我将尝试使用键盘控制avatar1,看看这种控制方式会给我们的同步带来哪些改变。
下面是我完成的demo,请点击flash屏幕进行测试,红色表示avatar1,绿色表示avatar2。
posted on 2011-05-28 21:39 Dongxue.xie 阅读(3630) 评论(2) 编辑 收藏 举报