在Flex中实现计时器循环是个坏主意吗?

时间:2020-03-06 14:39:12  来源:igfitidea点击:

在我们的游戏项目中,我们确实将计时器循环设置为每秒触发约20次(与应用程序的帧速率相同)。我们用它来移动一些精灵。
我想知道这是否会引起问题,我们应该使用EnterFrame事件处理程序来进行更新吗?
我给人的印象是,计时器循环的运行速度快于应用程序的帧速率可能会导致问题……是这种情况吗?

作为更新,尝试在EnterFrame上执行此操作引起了非常奇怪的问题。而不是每75毫秒发送一帧,而是突然跳到25毫秒。请注意,不仅仅是我们的计算声称帧速率不同,而且突然之间,动画加速到了疯狂的速率。

解决方案

我认为timerEvent和Enter Frame都是不错的选择,我在游戏中都使用了它们。 (我们是说通过计时器循环进行timerEvent吗?)

PS:请注意,在慢速计算机中,计时器可能无法刷新得足够快,因此我们可能需要调整代码以使游戏在慢速计算机中"更快"运行。

我会选择Enter框架,在某些特殊情况下,有两个"循环"对于逻辑而言是一个,而对于视觉效果则是有用的,但是对于大多数游戏,我还是坚持使用Enter框架事件监听器。不需要单独的计时器来移动内容,因为将其设置为除帧速率以外的任何值都会使动作变得抖动或者不可见(因为不重绘帧)。

但是,要考虑的一件事是使逻辑与帧速率脱钩,这最容易通过使用getTimer(在as2和as3中都可用)来计算自上一帧以来已经到期的时间并调整运动或者相应地进行。

计时器比输入帧事件更可靠,Flash会尝试跟上我们设置的任何速率,但是如果我们要进行大量处理或者处理复杂的图形,计时器和帧速率都会变慢。

关于使用enter frame事件的好处是,处理将以与渲染相同的速度降级,并且在代码块完成后立即获得屏幕更新。

不能保证这两种方法都会在特定的时间间隔内发生。因此,事件处理程序应该确定自上一次执行以来已经执行了多长时间,并据此做出决定,而不是纯粹执行了多少次。

我建议使用诸如TweenLite(http://blog.greensock.com/tweenliteas3/)之类的类,该类的轻量级约为3kb,或者如果我们需要更多功能,则可以使用TweenMax,我相信它为11kb。这里有很多优点。首先,此"引擎"已经过全面测试和基准测试,并且众所周知,它是使很少或者什至很多事物动起来的最资源友好的方法之一。我看到了一个基准,在AS3中,使用TweenLite对1,500个精灵进行了动画处理,并具有20 fps的强劲速度,因为Tweener之类的竞争对手会将其降低到9 fps。测试/。下一个优点是易于使用,正如我将在下面演示的那样。

//Make sure you have a class path pointed at a folder that contains the following.
import gs.TweenLite;
import gs.easing.*;

var ball_mc:MovieClip = new MovieClip();
var g:Graphics = ball_mc.graphics;
g.beginFill(0xFF0000,1);
g.drawCircle(0,0,10);
g.endFill();

//Now we animate ball_mc
//Example: TweenLite.to(displayObjectName, totalTweeningTime, {someProperty:someValue,anotherProperty:anotherValue,onComplete:aFunctionCalledWhenComplete});
TweenLite.to(ball_mc, 1,{x:400,alpha:0.5});

因此,这需要ball_mc并将其从x轴上的当前位置移动到400,并且在同一Tween期间,它将alpha从其当前值减小或者增加到0.5.

导入所需的类之后,对每个对象进行动画处理实际上只需要一行代码,这非常好。我们也会影响缓动性,我相信默认情况下是Expo.easeOut(Strong easeOut)。如果我们希望它弹起或者具有弹性,则只需向对象添加一个属性即可获得这种效果,如下所示。

TweenLite.to(ball_mc, 1,{x:400,alpha:0.5,ease:Bounce.easeOut});
TweenLite.to(ball_mc, 1,{x:400,alpha:0.5,ease:Elastic.easeOut});

所有的缓动都来自gs.easing。*导入,我相信这是Penween通过TweenLite使用的缓动方程式。

最终,我们没有诸如Timer之类的轮询(开放循环)来进行管理,并且我们具有易于阅读的代码,可以轻松地对其进行修改或者删除。

还需要注意的是,TweenLite和TweenMax提供的功能远远超出我在此处显示的内容,可以肯定地说,我在每个项目中都使用了两个类之一。动画是自定义的,它们具有添加的功能(onComplete:functionCall),并且它们是最佳的并且对资源友好。

以下是Flash处理帧速率的方式以及为什么看到内容播放更快的原因。

在最深层次上,运行Flash的任何主机应用程序(通常是浏览器)都会以一定的时间间隔轮询闪存。该间隔可能在一个浏览器中为每10毫秒,在另一浏览器中为50毫秒。每次进行轮询时,Flash都会执行以下操作:

  • 调度所有事件(包括一个" ENTER_FRAME"事件)
  • 执行所有带有待处理事件的框架脚本和事件处理程序
  • 绘制屏幕更新
  • 返回

但是,某些类型的外部事件(例如按键,鼠标事件和计时器事件)与上述过程异步处理。因此,如果我们有一个事件处理程序在按下某个键时触发,则该处理程序中的代码可能在两次框架更新之间执行了几次。除非我们使用updateAfterEvent()方法(AS2中的全局控件,添加到AS3中的事件),否则每帧更新一次屏幕仅会重绘一次。

请注意,这些事件的异步行为不会影响帧更新的时间。即使我们使用计时器事件(例如,每秒重绘屏幕50次),帧动画仍将以发布的帧速率发生,并且如果脚本动画是由enterFrame事件驱动的,则脚本动画的执行速度不会更快计时器)。