好的,所以我听说基于计时器的运动比 FR 更好。V = V + n 每 1/60 秒,而不是每帧 @ 60 fps。他们说它使速度变得实际,而不是因为 FR 滞后而降低。但是当我尝试过时,计时器真的一点也不可靠。难道我做错了什么?原因 Timer(20,0) 随着动画的进行而变慢。所以没有区别,如果剪辑超重,无论基于计时器还是FR,它都会减慢速度?是的,我有一个测试剪辑,每秒钟都会做出新的形状,所以一段时间后会有很多,但计时器真的比我的时钟慢,秒变长。但是计时器是额外的工作要做,更令人头疼。所以这不值得还是我用错了?(没有让它优先于其他功能吗?)
4 回答
是的,如果您的 SWF 能够在不到一帧的长度内渲染舞台,那么两者都很好,否则,无论您做什么,您的帧率都会受到影响。如果您想要这么大的 FPS,您需要调整 SWF 的性能。此外,计时器触发其事件的速度不能超过每帧一次。(事实上,我认为帧时间方法通常更好,因为您不知道您的 SWF 是否会在速度足够慢的 PC 上运行,否则将无法与正常时间流竞争。)
在您的情况下,我会放弃计时器,它们每帧再抛出一个事件,它们在很大程度上是不可靠的,因为它们的事件是异步的,这意味着您不能始终说计时器事件将在下一帧之前触发,并且使用更大的间隔计时器,a主机 PC 的任何延迟都会破坏许多玩家的乐趣。(我记得 Pyro 与我的旧 PIII,它使用系统时间来记录关卡节拍时间,但是一旦你开球就无法加快速度,而且动画重到会降低帧率,基本上阻止了我快速时间分数。)您的计时器已经在每帧大约触发一次事件,并且无法变得更快。
AS3 中的定时器确实不可靠。AS3 中的计时器的值不能低于 1000。Adobe 正式记录了这一点。您还可以对限制为 1000 毫秒的计时器进行测试,您会注意到它会以 800-999 毫秒的间隔随机触发,这永远不会准确。
如果你想制作一个帧限制/免费的应用程序,一个更好的候选者是“getTimer”。您可以使用传递的毫秒数来计算传递的正确时间量,然后渲染一帧。
看一下这个项目中的Clock类: Realtime Clock
你没有做错什么。它不太理想,但 Flash 将更新限制为最大帧速率,这意味着Timer
事件不准确。就个人而言,我倾向于使用基于帧的循环来对时间敏感,该循环使用 检查当前系统时间new Date().getTime()
,所以我会使用类似的东西:
private var lastFrameTime:Number = new Date().getTime();
private var now:Number;
addEventListener(Event.ENTER_FRAME, frameTick);
private function frameTick(e:Event):void {
now = new Date().getTime();
V = V + n * (now - lastFrameTime) * 0.001;
lastFrameTime = now;
}
可能这会有所帮助。
public class Timer extends EventDispatcher
{
private var instance:int;
private var _interval:Number;
private var _updateInterval:uint;
private var _lastCount:int
private var _repeatCount:int;
private var _count:int;
private var _started:Boolean;
public function Timer(interval:Number,repeatCount:int=0)
{
_interval=interval;
_repeatCount=repeatCount;
}
private function checkTime():void
{
var curCount:int=int(currentTime()/_interval);
if(curCount<=_lastCount)return;
_lastCount=curCount
_count++;
dispatchEvent(new TimerEvent(TimerEvent.TIMER));
if(_count==_repeatCount&&_repeatCount>0)
{
stop();
dispatchEvent(new TimerEvent(TimerEvent.TIMER_COMPLETE));
_count=0;
}
}
public function start():void
{
if(_started)return;
_started=true;
instance = getTimer();
_updateInterval=setInterval(checkTime,10);
_lastCount=int(currentTime()/_interval);
}
public function stop():void
{
_started=false;
clearInterval(_updateInterval);
}
public function reset():void
{
_count=0;
stop();
start();
}
private function currentTime():Number
{
if (instance == 0)
{
instance = getTimer();
}
return (getTimer() - instance);
}
public function get currentCount():int
{
return _count;
}
}