简体   繁体   中英

Actionscript-3 - How to fix display frame rate to 60?

There are 2 different FPS:

  • background FPS for sprite update
    • goes as fast as CPU allows
    • more or less constant 60 FPS (cheap sprite update)
  • display FPS (visible with Fraps)
    • goes up to 60 when sprites move wild around
    • drops to 0 when no sprite moves

I want to make the display FPS stay at 60 FPS. If Adobe made it impossible to change that I need to know or ...

How do I make the display FPS stay at 60 ?

To clear misunderstandings: Fraps hooks the WinApi function SwapBuffers . So every time a game window displays a new rendered scene by swapping buffers, Fraps has the chance to copy buffer content and put some FPS counter on it. Flash is optimized to save GPU time. When nothing changes nothing is drawn to the other buffer and no buffer swapping is performed. Actually this is a good thing. But I still want to know if I can disable this optimization. I'm not trying to disable vsync but to equal the GPU FPS with the CPU FPS.


This is how I update:

import flash.display.MovieClip;
import flash.events.Event;

[SWF(frameRate="60",backgroundColor="0xffffff",width="960",height="540")]
public class SimpleSprite extends MovieClip
{
    public function SimpleSprite()
    {
        for (var i: int = 0; i < 32; i++)
        {
            var angle: Number = 2 * Math.PI * Math.random();
            var color: uint = 0x1000000 * Math.random();
            var length: Number = 1024;

            graphics.lineStyle(2, color);
            graphics.moveTo(-Math.sin(angle) * length, -Math.cos(angle) * length);
            graphics.lineTo(Math.sin(angle) * length, Math.cos(angle) * length);
        }

        x = stage.stageWidth / 2;
        y = stage.stageHeight / 2;

        stage.addEventListener(Event.ENTER_FRAME, onEnterFrame);
    }

    private function onEnterFrame(event: Event): void
    {
        rotation += 0.002;
    }
}

Example:

 import flash.display.MovieClip; import flash.events.Event; [SWF(frameRate="60",backgroundColor="0xffffff",width="960",height="540")] public class SimpleSprite extends MovieClip { public function SimpleSprite() { for (var i: int = 0; i < 32; i++) { var angle: Number = 2 * Math.PI * Math.random(); var color: uint = 0x1000000 * Math.random(); var length: Number = 1024; graphics.lineStyle(2, color); graphics.moveTo(-Math.sin(angle) * length, -Math.cos(angle) * length); graphics.lineTo(Math.sin(angle) * length, Math.cos(angle) * length); } x = stage.stageWidth / 2; y = stage.stageHeight / 2; stage.addEventListener(Event.ENTER_FRAME, onEnterFrame); } private function onEnterFrame(event: Event): void { rotation += 0.002; } } 

I found an unsatisfying way to accomplish what I asked for:

Add a sprite to the stage that is invisible by alpha and let it move on the screen. If it leaves the screen the frame rate will drop again.

If you add an ENTERFRAME event listener, it will fire with each frame (up to requested FPS rate), regardless if there's any redrawing going on or not. If it drops below that, then it just means it didn't manage to render frames that fast. A wild guess? I'd say it's code performance. :-)

Also, Timer documentation states that you shouldn't use it for intervals shorter than 20ms, and setting it lower than 16.6ms will mess with flash inner workings.

Timer Documentation

I would suggest refactoring your app to use ENTERFRAME events instead of Timer events, and using actual elapsed time between frames to calculate animation positions.

Try using Adobe Scout. I it will show you when flash frames are running and when the display is updated. You can get a lot more detail on how your application is working. Why do you want Flash to update the physical display when nothing has changed? It won't accomplish anything. If you really want to force this, modify some bits on the display and set them back again. Scout will show exactly which bits are updated in each frame.

  1. Do not use timers. It's not meant to do what you're trying to get it to.
  2. Set your SWF framerate to 60 during compilation, either on the SWF header meta tags or your compiler settings.
  3. Use an ENTER_FRAME event to run your code (eg updateSprites() ).

You may skip some frames depending on how complex the animation is. That is inevitable . Trying to "force" the framerate won't work and will only make things worse. If you need something to run 60 times a second you can check getTimer() inside your ENTER_FRAME event and make sure something is being done that number of times. But it'll still be rendered at a lower framerate.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM