【问题标题】:TimerEvent vs. ENTER_FRAME in AS3/Flex games?AS3/Flex 游戏中的 TimerEvent 与 ENTER_FRAME?
【发布时间】:2013-04-23 21:10:15
【问题描述】:

我正在尝试在 AS3 / Flex 4 中编写一个简单的游戏,并且我正在尝试从一开始就找到处理代码定时执行的最佳方法。

最自然的方法是在整个程序中使用一堆Timer 对象。然而,与 ENTER_FRAME 相比,这在 CPU 周期上的成本应该很高。

但是我不确定将所有程序的定时执行都基于ENTER_FRAME 是否自然,并且我在stackoverflow 上读到它有问题-Timer 没有-关于当程序复杂度增加时,将动画和帧率拉低。

想到的另一个选择是在程序中简单地使用一个Timer 对象,它的事件处理程序将遍历并检查所有内容 - 有点像混合通常的Timer 和ENTER_FRAME接近。

我的问题是:对于 AS3/Flex 4 中的视频游戏来说,真正的最佳创意是什么,为什么?谢谢!

【问题讨论】:

  • 在我看来,最好的方法是使用一个主定时器或ENTER_FRAME。然后在该计时器内,只需调用游戏中需要时间的每个对象的更新函数。计时器可能是您最好的选择。
  • 这是一篇关于定时器使用主题的不错的文章 - bit-101.com/blog/?p=910 - 我个人使用过这两种方法,不能说这两种方法都产生了重大影响。我倾向于使用 ENTER_FRAME 并计算帧之间的时间以进行运动计算并更新所有对象。我会更详细地介绍,但互联网上确实已经有大量关于这场辩论的信息,只需 google 一下。
  • 从阅读中我很难判断使用 ENTER_FRAME 或单个 Timer 是否真的有任何特别的优势。听起来使用多个计时器的想法很糟糕。
  • 是的,我真的会专注于更大的问题,比如制作你的游戏。从一个切换到另一个真的很简单,正如我所说,我不能说我经历了一个重要的因素,使一个或另一个成为一个明确的选择。我发布的文章只是为了让您了解 Timers 的行为,这可能不是您所期望的。
  • 我忘了提到我喜欢 ENTER_FRAME 的一个主要优点是它与 Flash 播放器的渲染过程直接相关。 ENTER_FRAME 处理程序中发生的任何事情都会在每个帧渲染之前执行。使用 Timer 事件,不能保证您不会偶尔在给定帧中执行两次更新,因为您的更新和渲染不同步。同样,那里有关于这个主题的信息。

标签: actionscript-3 apache-flex events timer flex4


【解决方案1】:

这完全取决于何时您想要更新值、检查冲突、管理输入等等,以及您何时想要真正看到屏幕上发生的事情。

  • ENTER_FRAME 将使您的更新逻辑和游戏的渲染同步。

    每次发送ENTER_FRAME 事件时,都会重绘场景。这意味着您的所有游戏更新逻辑总是紧跟被渲染的屏幕。如果由于屏幕上的复杂图形需要很长时间渲染而导致游戏中的帧速率下降,那么游戏更新的速率也会下降。 ENTER_FRAME 调度是不稳定的,这意味着它们不适合更新任务,您需要在它们之间以均匀的间隔执行。

  • 计时器将使您的更新逻辑和游戏渲染变为异步。

    与ENTER_FRAME 处理程序相比,定时器的触发频率可能更高或更低。这意味着您的更新循环可以在重绘场景之前运行多次,或者可以多次重绘场景而不进行任何更改。计时器比ENTER_FRAME 处理程序更不稳定,使它们更擅长按设定的时间间隔做某事。尽管如此,更新之间仍然会有一点偏移:

    根据 SWF 文件的帧速率或运行时环境(可用内存和其他因素),运行时可能会以稍微偏移的间隔调度事件。例如,如果 SWF 文件设置为以每秒 10 帧 (fps) 的速度播放,即 100 毫秒的间隔,但您的计时器设置为以 80 毫秒的间隔触发事件,则该事件将在接近 100 毫秒的间隔时调度.内存密集型脚本也可能抵消这些事件。
    - help.adobe.com | flash.utils.Timer

就我个人而言,我一直使用ENTER_FRAME 与计时器。对我来说,如果我对游戏中的对象进行更改,这些更改应该立即显示在屏幕上,这是合乎逻辑的。

如果您希望能够以比帧速率能够管理的速度更快的速度更新游戏中的组件,那么计时器是很好的选择。如果您希望在特定时间范围内完成给定数量的更新,计时器也很好,因为它们不受屏幕重绘速率的限制,就像ENTER_FRAME 那样。


至于实际实现,您最好选择一个并实现一个处理程序。这意味着您应该在整个游戏中只有一个函数将由 Timer 或 ENTER_FRAME 触发。您不想在每个应该更新的类中创建单独的处理程序。相反,您希望让您的顶级类(或该类的近亲)定义处理程序。您还想在该类中创建一个列表,该列表将代表游戏中需要更新的所有内容。

从那里,您将创建一个小的方法集合,这些方法将处理从该类中列出和删除可更新实例。每个可更新实例要么实现一个接口,要么扩展一个定义update() 方法的类。它可能看起来像这样:

public interface IUpdatable
{
    function update();
}

从那里,更新程序类中的更新处理程序将简单地遍历列表中的所有可更新对象并调用它们的 update() 方法,如下所示:

for each(var i:IUpdatable in updateList)
{
    i.update();
}

最后要注意的是,这种方法意味着如果您决定从使用 ENTER_FRAME 处理程序切换到 Timer,反之亦然,这是更新程序类中的一个简单切换,不需要您更改任何其他部分游戏代码。如果您在每个需要更新的类中创建处理程序,那么您的改变将意味着对每个单独的类进行更改。

【讨论】:

  • 使用 ENTER_FRAME,您仍然可以通过划分时间增量和更新多次迭代,在给定帧中多次更新您的逻辑。而且..您仍然与渲染过程保持同步。
  • @prototypical 当然可以,但这仍然是预期的一批更新,而不是像计时器那样在给定帧数上的不稳定更新集合。
  • 也许我误解了你,你是说在给定数量的帧上不稳定的更新集合比每帧的预期批量更新更可取吗?
  • @prototypical 不不,我是说进入帧处理程序中的单个更新与有意触发每个进入帧的多个更新相同,但与使用可能发生多个更新的计时器不同从屏幕呈现同步作为意外事件。
  • 啊,我明白你的意思了。是的,刚收到你的电子邮件,给你回了一个。
猜你喜欢
  • 2010-11-09
  • 2010-12-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-22
  • 2018-03-26
相关资源
最近更新 更多