Steven
Steven

Reputation: 11

How to Play/Pause All for Adobe Air Application using AS3 in Flash CS4

I am new to Flash and I'm creating an educational application in AS3 in Flash CS4 for Adobe Air. I want to use buttons to play and pause all content (movieclips AND sound).

I have created play and pause buttons that worked by switching the frame rate between 0 and 20, unfortunately I've realized that it's never really 0 fps, but rather 0.01 fps, and so it continues playing, albeit very very slowly. Also this doesn't affect the audio; I have set sound files to Stream which are synced to movieclips on their timelines, but even when the application is set to 0 fps the audio continues.

Since I have various levels with numerous movieclips each with synced audio, what i'd like is to be able to do is pause absolutely everything within each movieclip with one button and to be able to resume from the same place using another button. Is this possible? If not, is there a global function to pause/resume the entire application/program?

Upvotes: 1

Views: 1136

Answers (3)

asannov
asannov

Reputation: 189

My solution

private var pausedArr:Array = [];

// recursive function to store all MovieClip children and their currentFrame values
public function pause(mc:*, rootObj:Boolean = false):void
{
    if (!mc is MovieClip) return;

    if (rootObj) {
        pausedArr = [];
        mc.addEventListener(Event.ENTER_FRAME, stepOneFrame);
    }

    pausedArr.push( { mc:mc, frame:mc.currentFrame, paused: false } );

    if (mc.numChildren > 0) {
        for (var i:int = mc.numChildren - 1; i >= 0; i--) {
            if (mc.getChildAt(i) is MovieClip) pause(mc.getChildAt(i));
        }
    }
}

// resume only paused MovieClips
public function resume():void 
{
    for (var i:int = 0; i < pausedArr.length; i++) {
        if (pausedArr[i].mc && pausedArr[i].paused) pausedArr[i].mc.play();
    }

    pausedArr = [];
}

// see if MovieClips' frame changed, this is to avoid resuming stopped MovieClips before pause
private function stepOneFrame(e:Event):void 
{
    pausedArr[0].removeEventListener(Event.ENTER_FRAME, stepOneFrame);
    for (var i:int = 0; i < pausedArr.length; i++) {
        if (pausedArr[i].mc.currentFrame != pausedArr[i].frame) {
            pausedArr[i].mc.stop();
            pausedArr[i].paused = true;
        }
    }
}

Use com.reintroducing.sound.SoundManager to play/pause sounds. Use com.greensock.TweenMax for timers and tweens, it can pause/resume both.

Upvotes: 0

Marcela
Marcela

Reputation: 3728

An alternative solution to adding listeners to all of your MovieClip instances is to employ recursion to pause and resume a MovieClip and all of its children (and children's children, and so on):

/**
 * Recursively pause a display object and all contained display objects
 * @param   clip    
 * @param   rewind  whether to go to the first frame
 */
public function recursivePause(clip:DisplayObject, rewind:Boolean = false):void 
{
    if (clip is MovieClip)
    {
        if (rewind) 
        {
            (clip as MovieClip).gotoAndStop(1);
        }
        else
        {
            (clip as MovieClip).stop();
        }
    }

    if (clip is DisplayObjectContainer)
    {
        for (var i:uint = 0; i < (clip as DisplayObjectContainer).numChildren; i++) 
        {
            recursivePause((clip as DisplayObjectContainer).getChildAt(i), rewind);
        }
    }
}

/**
 * Recursively play a display object and all contained display objects
 * @param   clip
 * @param   rewind  whether to go to the first frame
 */
public function recursivePlay(clip:DisplayObject, rewind:Boolean = false):void
{
    if (clip is MovieClip)
    {
        if (rewind)
        {
            (clip as MovieClip).gotoAndPlay(1);
        }
        else
        {
            (clip as MovieClip).play();
        }
    }

    if (clip is DisplayObjectContainer)
    {
        for (var i:uint = 0; i < (clip as DisplayObjectContainer).numChildren; i++) 
        {
            recursivePlay((clip as DisplayObjectContainer).getChildAt(i), rewind);
        }
    }
}

Usage: recursivePause(stage) or recursivePause(myMainMovieClip)

This is slightly more convenient than the event method, as it will work "out of the box" if/when you add a new MovieClip to the mix.

Upvotes: 2

Marijn
Marijn

Reputation: 810

Setting the framerate to 0 does not stop all movieclips. The only way to do this is to stop each individual movieclip and sound. One way to do it is with a custom event system:

First, dispatch a custom event when the stop/start button is clicked (dispatched from the stage, to make it easy accesible. (the sounds on the timeline of the stopped movieclips will be stopped aswell. If you play the sounds from script (SoundChannel), then you should stop them aswell.

btnStop.addEventListener(MouseEvent.CLICK, onClick_stop);
function onClick_stop(e:MouseEvent):void {
    stage.dispatchEvent(new Event("STOP_EVERYTHING"));
}

btnStart.addEventListener(MouseEvent.CLICK, onClick_start);
function onClick_start(e:MouseEvent):void {
    stage.dispatchEvent(new Event("START_EVERYTHING"));
}

then, on each movieclip you want to stop, listen to the events:

stage.addEventListener("START_EVERYTHING", onStart_everything);
function onStart_everything(e:Event):void {
    //play this movieclip
    play();
}

stage.addEventListener("STOP_EVERYTHING", onStop_everything);
function onStop_everything(e:Event):void {
    //stop this movieclip
    stop();
}

Upvotes: 0

Related Questions