代码之家  ›  专栏  ›  技术社区  ›  MidnightGun

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

  •  3
  • MidnightGun  · 技术社区  · 17 年前

    在我们的游戏项目中,我们确实有一个定时器循环设置为每秒20次(与应用程序帧速率相同)。我们用这个来移动一些精灵。 我想知道这是否会导致问题,我们应该使用EnterFrame事件处理程序进行更新? 我的印象是,计时器循环的运行速度比应用程序的帧速率要快,这可能会导致问题。。。是这样吗?

    作为一个更新,尝试在EnterFrame上执行它会导致非常奇怪的问题。不是每75毫秒一帧,而是突然跳到了25毫秒 声称 帧速率不一样,动画突然加速到疯狂的速度。

    5 回复  |  直到 17 年前
        1
  •  4
  •   grapefrukt    17 年前

    我会选择Enter frame,在某些特殊情况下,有两个“循环”可能很有用,一个用于逻辑,一个用于视觉,但对于大多数游戏,我会选择Enter frame事件监听器。有一个单独的定时器来移动你的东西是有点不必要的,因为它设置为除帧速率以外的任何东西都会使运动变得不稳定或只是不可见(因为帧没有重绘)。

    但是要考虑的一件事是将逻辑与帧速率分离,这是通过使用getTimer(在as2和as3中都可用)来计算自上一帧以来已过期的时间并相应地调整运动或其他东西来实现的。

    计时器并不比进入帧事件更可靠,flash将尝试跟上您设置的任何速率,但如果您正在进行繁重的处理或复杂的图形,它将减慢计时器和帧速率。

        2
  •  4
  •   fenomas    17 年前

    下面是Flash如何处理帧速率以及为什么你看到你的内容播放得更快的简要说明。

    在最深层次上,Flash运行的任何主机应用程序(通常是浏览器)都会每隔一段时间轮询Flash。在一个浏览器中,间隔可能是每10毫秒,在另一个浏览器中,间隔可能是50毫秒。每次投票时,Flash都会这样做:

    • 自上次帧更新以来(1000/framerate)毫秒是否已过?
      • 如果没有:什么也不做,然后返回
      • 如果是:执行帧更新:
        • 将所有(播放)时间线提前一帧
        • 调度所有事件(包括 ENTER_FRAME 事件
        • 使用挂起事件执行所有框架脚本和事件处理程序
        • 绘图屏幕更新
        • 返回

    但是,某些类型的外部事件(如按键、鼠标事件和计时器事件)是与上述进程异步处理的。因此,如果有一个事件处理程序在按下键时触发,则该处理程序中的代码可能在帧更新之间执行多次。除非使用 updateAfterEvent() 方法(AS2中的全局,附加到AS3中的事件)。

    注意,这些事件的异步行为不会影响帧更新的时间。即使您使用计时器事件(例如,每秒50次重绘屏幕)来重绘屏幕,帧动画仍将以已发布的帧速率出现,并且脚本动画在由enterFrame事件(而不是计时器)驱动时不会执行得更快。

        3
  •  2
  •   Marc Hughes    17 年前

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

    两种方法都不能保证在特定的时间间隔内发生。因此,您的事件处理程序应该确定它自上次执行以来的时间,并据此做出决策,而不是仅仅确定它运行了多少次。

        4
  •  0
  •   Tom    17 年前

    我认为timerEvent和EnterFrame都是不错的选择,我在我的游戏中都使用过它们。(你的意思是按定时器循环计时?)

    注意,在慢机器中定时器可能刷新不够快,所以你可能需要调整你的代码,使游戏在慢机器中“更快”运行。

        5
  •  0
  •   Will Brian Hodge    9 年前

    我建议你上一门课,比如Twenlite( http://blog.greensock.com/tweenliteas3/ )它的重量约为3kb,如果你需要更多的能量,你可以使用TweenMax,我相信是11kb。这里有很多优点。首先,这个“引擎”已经过了彻底的测试和基准测试,并且是众所周知的最有利于资源的方式之一,可以使很少甚至很多东西产生动画效果。我看过一个基准测试,在AS3中,1500个精灵被TweenLite动画化,它拥有强大的20 fps,像Tweener这样的竞争对手将陷入9 fps的困境 http://blog.greensock.com/tweening-speed-test/ . 下一个优势是易用性,我将在下面演示。

    //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});
    

    因此,这需要BalyMC并将其从X轴上的当前位置移动到400,并且在相同的时间内,它将α从其当前值降低或增加到0.5。

    在导入所需的类之后,只需一行代码就可以为每个对象设置动画,这非常好。我们也可以影响轻松,我相信默认情况下是Expo.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.*import,我相信这是通过TweenLite使用的Penner的放松方程。

    最后,我们没有轮询(开放循环)来管理计时器,我们有非常可读的代码,可以很容易地修改或删除。

    值得注意的是,TweenLite和TweenMax提供的服务远远超过了我在这里展示的内容,可以肯定地说,我在每个项目中都使用这两个类中的一个。这些动画是自定义的,它们附加了功能(onComplete:functionCall),而且它们是最佳的,而且对资源友好。

    推荐文章