【问题标题】:Is it a bad idea to implement a timer loop in Flex?在 Flex 中实现定时器循环是不是一个坏主意?
【发布时间】:2008-09-24 10:26:44
【问题描述】:

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

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

【问题讨论】:

  • 您是真的使用 flex 框架制作游戏,还是只是使用 flexbuilder 在 as3 中编码?
  • 游戏大部分是纯AS3,加载了很多CS3创建的SWF。然而,我们确实将 MXML 用于 UI,我认为它是两全其美的。我应该补充一点,当我们尝试加载特别大的游戏关卡时,我们只会遇到性能问题......通常没问题。

标签: apache-flex actionscript-3 performance


【解决方案1】:

我会选择 Enter 帧,在某些特殊情况下,有两个“循环”会很有用,一个用于逻辑,一个用于视觉效果,但对于大多数游戏,我坚持使用 Enter 帧事件侦听器.有一个单独的计时器来移动你的东西有点不必要,因为将它设置为除帧率之外的任何东西都会使运动变得生涩或不可见(因为没有重绘帧)。

但是要考虑的一件事是将您的逻辑与帧速率解耦,这最容易通过使用 getTimer(在 as2 和 as3 中都可用)计算自上一帧以来已过期的时间并调整运动或其他方式来完成因此。

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

【讨论】:

    【解决方案2】:

    这里简要介绍了 Flash 如何处理帧速率以及您看到内容播放速度更快的原因。

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

    • 自上次帧更新以来已过去 (1000/帧速率) 毫秒?
      • 如果不是:什么都不做,然后返回
      • 如果是:执行帧更新:
        • 将所有(播放)时间线推进一帧
        • 调度所有事件(包括ENTER_FRAME 事件
        • 执行所有帧脚本和事件处理程序与未决事件
        • 绘图屏幕更新
        • 返回

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

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

    【讨论】:

      【解决方案3】:

      使用输入帧事件的好处是,您的处理速度将与渲染同步,并且您将在代码块完成后立即获得屏幕更新。

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

      【讨论】:

        【解决方案4】:

        我认为 timerEvent 和 Enter Frame 都是不错的选择,我在我的游戏中都使用了它们。 (你是指定时器循环中的 timerEvent 吗?)

        PS:请注意,在慢速机器中,计时器可能刷新不够快,因此您可能需要调整代码以使游戏在慢速机器中“更快”运行。

        【讨论】:

          【解决方案5】:

          我建议使用 TweenLite (http://blog.greensock.com/tweenliteas3/) 之类的轻量级类,大约 3kb,或者如果您需要更多功率,您可以使用 TweenMax,我相信它是 11kb。这里有很多优点。首先,这个“引擎”已经过彻底的测试和基准测试,并且是众所周知的最资源友好的方式之一,可以为少数甚至很多东西制作动画。我看过一个基准测试,在 AS3 中,1,500 个精灵正在使用 TweenLite 进行动画处理,并且它保持强劲的 20 fps,而像 Tweener 这样的竞争对手会陷入 9 fps http://blog.greensock.com/tweening-speed-test/。下一个优点是易于使用,我将在下面演示。

          //确保您有一个指向包含以下内容的文件夹的类路径。 导入 gs.TweenLite; 导入 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(); //现在我们动画ball_mc //示例: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。

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

          最终,我们无需管理诸如计时器之类的轮询(开环),而且我们拥有可以轻松修改或删除的可读性极强的代码。

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

          【讨论】:

            猜你喜欢
            • 2017-01-20
            • 2011-06-22
            • 2010-12-03
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2011-02-03
            • 2019-02-01
            • 1970-01-01
            相关资源
            最近更新 更多