Flash 上的跳帧 [英] Frame skipping on Flash

查看:15
本文介绍了Flash 上的跳帧的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有没有办法在 Flash 上本地启用跳帧?

Is there a way to natively enable frame skipping on Flash?

当您开发游戏时,您会开发动画以匹配游戏玩法的节奏,并以目标帧速率(Flash 通常为 24-40fps)进行制作.但是如果用户的电脑速度太慢,无法保持目标帧率,Flash会自动降低fps,导致应用播放速度变慢.

When you develop a game, you develop animations to match the pace of the gameplay, and do it on a target frame-rate (usually 24-40fps for Flash). But if the user's computer is too slow, and cannot maintain the target frame-rate, Flash will automatically lower the fps, making the application play slowly.

如果你使用基于时间的逻辑,基于帧的渲染将与基于时间的逻辑不匹配,事情会变得很奇怪,会有很多极端情况需要解决.

If you use a time based logic, the frame based rendering will not match the time based logic, and things will be weird and there'll be a lot of corner cases to work around.

事实上,我知道有些游戏使用这种跳帧逻辑,例如 Popcap 的 Zuma Blitz.他们自己实现了跳帧吗?

I know by fact that some games use this sort of frame skipping logic, such as Popcap's Zuma Blitz. Are they implementing the frame skipping on their own?

除非我能以某种方式重新实现 MovieClip 类并使其易于跳帧,否则我无法在项目中这么晚才实现它.另外,自己控制动画(覆盖 Flash 原生 MovieClip 控件)的开销会不会太大?

I cannot afford to implement this so late in the project unless I can somehow reimplement the MovieClip class and make it easily frame skipabble. Also, wouldn't the overhead of controlling the animations on your own (overwriting Flash native MovieClip control) be too much of an overhead?

推荐答案

好吧,我意识到您不是在寻找以下解决方案",这将不起作用,因为所有帧仍将播放:

Okay, I realize that you're not looking for the following 'solution', which won't work, as all frames will still be played:

stage.frameRate = new_frame_rate;

唯一的解决方案是在 enterFrame 回调中跳过帧:

The only solution is to just skip frames in your enterFrame callback:

// Defined elsewhere.
var current_frame:Number = 0;
var frame_skip_factor:uint; // Skip one frame every 'x' frames.
var is_frame_skip_active:Boolean;

function on_enter_frame(event:Event):void
{
   if ( is_frame_skip_active && current_frame++ % frame_skip_factor == 0) { return; }

   // Game logic/rendering code...
}

(假设,根据最佳实践,您在单个回调中集中了游戏逻辑/动画),但这可能会在运行任何异步回调时出现竞争条件/复杂性.

(assuming, per best practices, you've centralized game logic/animation in a single callback), but that may present race conditions/complications when any asynchronous callbacks are run.

实际上没有办法在运行时级别跳帧;这是 AVM 合同的一部分 - 无论如何都不会跳过任何帧,运行所有代码.如果性能是一个问题,您可以尝试异步代码执行.有几种方法可以做到:

There is no way to actually skip frames at the runtime level; this is part of the contract of the AVM - no frames are skipped, all code is ran, no matter what. If performance is an issue, you might try asynchronous code execution. There are a couple of ways to do it:

1) 将部分计算卸载到 Pixel Bender,以便可以异步和/或并行处理 (http://www.adobe.com/devnet/flex/articles/flashbuilder4_pixelbender.html)

1) Offload some computing to Pixel Bender, so that it can be processed asynchronously and/or in parallel (http://www.adobe.com/devnet/flex/articles/flashbuilder4_pixelbender.html)

2) 在多个帧上分散执行冗长的操作(需要状态保存和状态恢复,一种纪念品模式).此处的详细信息(和精彩阅读):http://www.sencular.com/flash/tutorials/异步操作/

2) Spread out the execution of lengthy operations over multiple frames (requires a state save and state restore, a la memento pattern). Details (and a great read) here: http://www.senocular.com/flash/tutorials/asyncoperations/

在任何情况下,我都(首先)建议使用 Flash Builder Profiler 或 Stats 类(Doob 先生)等工具明确确定性能瓶颈.

In any case, I'd (first and foremost) recommend definitively identifying the performance bottleneck with a tool like the Flash Builder Profiler or the Stats class (Mr. Doob).

Blitting 也可能是解决方案(为动画的每一帧创建一个带有 tile 的 spritesheet).但无论如何,我认为您需要做的是子类化 MovieClip 并覆盖 play()、stop() 和 gotoAndPlay() 方法.你的类应该是这样的:

Blitting might be the solution (create a spritesheet with a tile for each frame of the animation) as well. But in any case, I think what you'll need to do is subclass MovieClip and override the play(), stop(), and gotoAndPlay() methods. Your class should look something like this:

public class MyMovieClip extends MovieClip
{
   override public function play():void
   {
      addFrameSkipListener();

      super.play();
   }

   override public function gotoAndPlay(frame:Object, scene:String = null):void
   {
      addFrameSkipListener();

      super.gotoAndPlay(frame, scene);
   }

   // ....
}

如果需要,跳帧侦听器将根据当前帧速率或帧时间跳过帧.当然,您还需要在动画结束时移除 frameSkipListener.

Where the frame skip listener will skip frames according to the current frame rate or frame time, if necessary. Naturally, you'll also need to remove the frameSkipListener when the animation has reached an end.

虽然 MovieClip 覆盖解决方案可能会在纸面上执行您想要的操作,但如果您有很多对象,这实际上可能会降低性能,因为额外的 ENTER_FRAME 侦听器会增加一些开销.

While the MovieClip override solution might do what you want on paper, if you have a lot of objects, this might actually degrade performance as the additional ENTER_FRAME listeners will add some overhead.

这篇关于Flash 上的跳帧的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆