Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Frame skipping on Flash

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

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.

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?

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?

like image 561
felipemaia Avatar asked Oct 28 '11 21:10

felipemaia


1 Answers

The approach to use, is to think of changes in pixels-per-second, instead of pixels-per-frame. Then you can run your main loop on an EnterFrame. In the enterframe, call getTimer() to get the systemtime in miliseconds. And compare that to the value the last time the script was run. This will let you know exactly the amount of time that passed since the last frame. Use that amount to determine how to move stuff.

Here is an example of that will move a circle the at the same rate regardless of the frame rate:

package

{
    import flash.display.Shape;
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.utils.getTimer;

    /**
     * ...
     * @author Zachary Foley
     */
    public class Main extends Sprite 
    {
        private var lastFrame:int = 0;
        private var thisFrame:int;
        private var pixelsPerSecond:Number = 200;
        private var circle:Shape
        private var percentToMove:Number; 
        public function Main():void 
        {
            if (stage) init();
            else addEventListener(Event.ADDED_TO_STAGE, init);
            circle = new Shape();
            circle.graphics.beginFill(0xFF0000);
            circle.graphics.drawCircle(0, 0, 25);
            circle.x = 50;
            addChild(circle);
            addEventListener(Event.ENTER_FRAME, onEnterFrame);
        }

        private function onEnterFrame(e:Event):void 
        {
            // Get the miliseconds since the last frame
            thisFrame = getTimer();
            percentToMove = (thisFrame - lastFrame) / 1000;
            // Save the value for next frame.
            lastFrame = thisFrame;
            // Update your system based on time, not frames.
            circle.x += pixelsPerSecond * percentToMove;

        }

        private function init(e:Event = null):void 
        {
            removeEventListener(Event.ADDED_TO_STAGE, init);
            // entry point
        }

    }

}

If you find that low framerates are impacting the accuracy of collision calculations, the run them separately with a timer. This is just the drawing loop, which is inevitably tied to the frame rate.

And just so you know, you can't for frame skipping in flash. It's handled by the player. The best approach is to adjust your frame rendering technique to accomodate the variable frame rate.

like image 81
Plastic Sturgeon Avatar answered Oct 26 '22 06:10

Plastic Sturgeon