# Controlling movie clip playback

Flash uses the metaphor of a timeline to convey animation or a change in state.
Any visual element that employs a timeline must be either a MovieClip object or
extend from the MovieClip class. While ActionScript can direct any movie clip to
stop, play, or go to another point on the timeline, it cannot be used to
dynamically create a timeline or add content at specific frames; this is only
possible using the Flash authoring tool.

When a MovieClip is playing, it progresses along its timeline at a speed
dictated by the frame rate of the SWF file. Alternatively, you can override this
setting by setting the `Stage.frameRate` property in ActionScript.

## Playing movie clips and stopping playback

The `play()` and `stop()` methods allow basic control of a movie clip across its
timeline. For example, suppose you have a movie clip symbol on the Stage which
contains an animation of a bicycle moving across the screen, with its instance
name set to `bicycle`. If the following code is attached to a keyframe on the
main timeline,

    bicycle.stop();

the bicycle will not move (its animation will not play). The bicycle's movement
could start through some other user interaction. For example, if you had a
button named `startButton`, the following code on a keyframe on the main
timeline would make it so that clicking the button causes the animation to play:

    // This function will be called when the button is clicked. It causes the
    // bicycle animation to play.
    function playAnimation(event:MouseEvent):void
    {
        bicycle.play();
    }
    // Register the function as a listener with the button.
    startButton.addEventListener(MouseEvent.CLICK, playAnimation);

## Fast-forwarding and rewinding

The `play()` and `stop()` methods are not the only way of controlling playback
in a movie clip. You can also move the playhead forward or backward along the
timeline manually by using the `nextFrame()` and `prevFrame()` methods. Calling
either of these methods stops playback and moves the playhead one frame forward
or backward, respectively.

Using the `play()` method is analogous to calling `nextFrame()` every time the
movie clip object's `enterFrame` event is triggered. Along these lines, you
could make the `bicycle` movie clip play backwards by creating an event listener
for the `enterFrame` event and telling `bicycle` to go to its previous frame in
the listener function, as follows:

    // This function is called when the enterFrame event is triggered, meaning
    // it's called once per frame.
    function everyFrame(event:Event):void
    {
        if (bicycle.currentFrame == 1)
        {
            bicycle.gotoAndStop(bicycle.totalFrames);
        }
        else
        {
            bicycle.prevFrame();
        }
    }
    bicycle.addEventListener(Event.ENTER_FRAME, everyFrame);

In normal playback, if a movie clip contains more than a single frame, it will
loop indefinitely when playing; that is, it will return to Frame 1 if it
progresses past its final frame. When you use `prevFrame()` or `nextFrame()`,
this behavior does not happen automatically (calling `prevFrame()` when the
playhead is on Frame 1 doesn't move the playhead to the last frame). The `if`
condition in the example above checks to see if the playhead has progressed
backwards to the first frame, and sets the playhead ahead to its final frame,
effectively creating a continuous loop of the movie clip playing backwards.

## Jumping to a different frame and using frame labels

Sending a movie clip to a new frame is a simple affair. Calling either
`gotoAndPlay()` or `gotoAndStop()` will jump the movie clip to the frame number
specified as a parameter. Alternatively, you can pass a string that matches the
name of a frame label. Any frame on the timeline can be assigned a label. To do
this, select a frame on the timeline and then enter a name in the Frame Label
field on the Property inspector.

The advantages of using frame labels instead of numbers are particularly evident
when creating a complex movie clip. When the number of frames, layers, and
tweens in an animation becomes large, consider labeling important frames with
explanatory descriptions that represent shifts in the behavior of the movie clip
(for example, "off," "walking," or "running"). This improves code readability
and also provides flexibility, since ActionScript calls that go to a labeled
frame are pointers to a single reference—the label—rather than a specific frame
number. If later on you decide to move a particular segment of the animation to
a different frame, you will not need to change your ActionScript code as long as
you keep the same label for the frames in the new location.

To represent frame labels in code, ActionScript 3.0 includes the FrameLabel
class. Each instance of this class represents a single frame label, and has a
`name` property representing the name of the frame label as specified in the
Property inspector, and a `frame` property representing the frame number of the
frame where the label is placed on the timeline.

In order to get access to the FrameLabel instances associated with a movie clip
instance, the MovieClip class includes two properties that directly return
FrameLabel objects. The `currentLabels` property returns an array that consists
of all FrameLabel objects across the entire timeline of a movie clip. The
`currentLabel` property returns a string containing the name of the frame label
encountered most recently along the timeline.

Suppose you were creating a movie clip named `robot` and had labeled the various
states of its animation. You could set up a condition that checks the
`currentLabel` property to access the current state of `robot`, as in the
following code:

    if (robot.currentLabel == "walking")
    {
        // do something
    }

Flash Player 11.3 and AIR 3.3 added the `frameLabel` event to the FrameLabel
class. You can assign an event handler to the FrameLabel instance that
represents a frame label. The event is dispatched when the playhead enters the
frame.

The following example creates a FrameLabel instance for the second frame label
in the Array of frame labels for the MovieClip. It then registers an event
handler for the `frameLabel` event:

    var myFrameLabel:FrameLabel = robot.currentLabels[1];
    myFrameLabel.addEventListener(Event.FRAME_LABEL, onFrameLabel);

    function onFrameLabel(e:Event):void {
        // do something
    }

## Working with scenes

In the Flash authoring environment, you can use scenes to demarcate a series of
timelines that a SWF file will progress through. Using the second parameter of
the `gotoAndPlay()` or `gotoAndStop()` methods, you can specify a scene to send
the playhead to. All FLA files start with only the initial scene, but you can
create new scenes.

Using scenes is not always the best approach because scenes have a number of
drawbacks. A Flash document that contains multiple scenes can be difficult to
maintain, particularly in multiauthor environments. Multiple scenes can also be
inefficient in bandwidth, because the publishing process merges all scenes into
a single timeline. This causes a progressive download of all scenes, even if
they are never played. For these reasons, use of multiple scenes is often
discouraged except for organizing lengthy multiple timeline-based animations.

The `scenes` property of the MovieClip class returns an array of Scene objects
representing all the scenes in the SWF file. The `currentScene` property returns
a Scene object that represents the scene that is currently playing.

The Scene class has several properties that give information about a scene. The
`labels` property returns an array of FrameLabel objects representing the frame
labels in that scene. The `name` property returns the scene's name as a string.
The `numFrames` property returns an int representing the total number of frames
in the scene.
