对于大部分Flash开发者,都已经知道Flash的帧频、Timer计时并不是十分精确的。如果您已经做过这方面测试,可以略过这篇文章的前面一部分,在后面有关于Flash Player可变跑道的文章链接,希望对您有帮助。这篇文章的主要目的是让一些不知道Flash计时不精确和知道但又没有做过测试的朋友,来分享我的测试结果。我使用的Flex开发工具,并创建了一个ActionScript项目。
测试我尽量使用最简单的代码,下面是针对于Timer的测试代码,设置了一个20毫秒每次的Timer,为了简单我只计时5次:
package { import flash.display.Sprite; import flash.events.TimerEvent; import flash.utils.Timer; import flash.utils.getTimer; public class TimerTest extends Sprite { // 定义一个计时器 private var timer:Timer; // 记录上一次计时的时间 private var prev:int; public function TimerTest() { // 计时器初始化为20毫秒执行一次,执行5次后结束 timer = new Timer(20, 5); timer.addEventListener(TimerEvent.TIMER, onTimer); timer.start(); // 启动计时器后,记录一下当前时间 prev = getTimer(); } private function onTimer(event:TimerEvent):void { // 计时器执行,获取当前时间 var t:int = getTimer(); // 打印出当前时间与上一次计时的时间间隔 trace(t - prev); // 记录下当前时间 prev = t; } } } /** 输出结果 26 28 38 27 20 **/
运行一下这个程序,可以看到输出的结果并不是准确的20毫秒,每次运行的结果都不一样,并且都大于等于20毫秒,由此可以得出Timer的计时并不是精确的。
继续看每次Flash帧频的时间间隔,这个测试例子中,设置了帧频为25帧每秒,理论上两帧之间的时间间隔为40毫秒(1000毫秒 / 25帧):
package { import flash.display.Sprite; import flash.events.Event; import flash.utils.getTimer; // 设置swf的帧频的25帧每秒 [SWF(frameRate = 25)] public class EnterFrameTest extends Sprite { // 记录上一次计时的时间 private var prev:int; public function EnterFrameTest() { // 监听ENTER_FRAME事件 this.addEventListener(Event.ENTER_FRAME, onEnterFrame); // 记录当前时间 prev = getTimer(); } private function onEnterFrame(event:Event):void { // 每次ENTER_FRAME事件,获取当前时间 var t:int = getTimer(); // 打印出当前时间与上一次计时的时间间隔 trace(t - prev); // 记录当前时间 prev = t; } } } /** 测试结果 47 32 44 47 32 47 29 **/
可以看出各帧之间的时间间隔也是不确定的,不过这些时间间隔的平均值还是很接近于40的。
上面的测试结果只是针对于较正常的情况下,并不能说明Timer计时和帧频的所有问题,那么我们继续走下去。如果我们设置Timer的时间间隔大一些、帧频低一些,那么计时的相对误差就会小一些;这个不是我们关心的问题,现在的问题是如果把Timer的时间间隔设的很小、帧频很高,就会出现较大的误差,我们来看一下结果:
/** 测试结果 Timer的计时时间为1毫秒 10 20 9 14 15 **/ /** 测试结果 帧频为200帧每秒 20 11 15 15 14 18 14 **/
对比开始的测试,对于Timer的误差,或许我们可以理解,但这里帧频平均值(15.5)跟理论间隔(5)差别就比较大。如果您把大量的输出结果平均一下,或许会发现帧频的平均值与Timer时间间隔的平均值会比较接近(具体平均值每台计算机的测试结果都会有一定的差别)。
对于为何会存在这些差异,就需要引入Flash Player的一些内部机制了,在不了解Flash Player的可变跑道之前,我只知道Flash Player的计时不精确,但并不了解原因,直到看了下面这篇文章:
执行模型之可变跑道
对于Flash Player的内部机制,一直希望能有一些资料可以学习一下,一直没有找到比较丰富的资源,如果您手上有这方面的资料,希望能分享一下哈,本人不胜感激,也希望能和您交流一下Flash方面的技术。