Question

What is the best way of implementing a game speed function that speeds up game or pauses it reliably?

I'm looking to find the ideal way before I get too deep into this, because it is a pretty integral part or how other game elements are implemented.

Was it helpful?

Solution

I'd say use an enter frame listener that will have an internal loop to call a main update function several times. Also you can play with stage.frameRate property if you want to slow down your game pace. Or, you can make a "time delta" property that will be passed into main update function so everything will act as if not a whole frame, but only a part of it has passed, making a realtime global slo-mo effect.

A typical organization of it is as follows:

public var cyclesPerFrame:int;
addEventListener(Event.ENTER_FRAME,mainUpdate);
function mainUpdate(e:Event):void {
    for (var i:int=cyclesPerFrame;i>0;i--) internalUpdate();
    // it's the function that handles all your game ^
    // if you need to update visuals regardless of pause, use this:
    // updateVisuals();
}

This will make internal update several times per frame. Also this will allow you to set cyclesPerFrame to zero, making an effective pause.

OTHER TIPS

I think you'll get the best results by measuring time elapsed between frames and basing your speed calculations on that.

Have an internal speed variable that you change as needed and then update game state on every frame by calculating how many 'ticks' (game speed divided by time elapsed since last frame) passed. That gives you smooth game speed control, and maintains a steady frame rate (which is crucial for impression of smoothness).

Be careful about game pauses though. If you set game speed to 0 no ticks will occur, but all the tweens, timers and similar objects will continue to run so you'll have to manage those separately.

Here is an example of that will move a circle the at the same rate regardless of the frame rate. It uses the display list, but the same technique is applicable with starling:

package

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


    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
        }

    }

}

This is good for making sure your screen updates are appropriate. Some events need to happen more regularly, and not tied to the refresh rate (AI, Physics steps). You can handle those cases using a timer, or iterate the appropriate number of steps based on the deltaTime in the on EnterFrame.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top