Problem
The original "Sleeper" demo displays a fairly obvious delivery problem: the animation hangs up, usually before displaying its final frame, while the movie containing the character overlay loads in from the server. Once the load process is finished, the movie jumps awkwardly to that last frame.
Note that this problem was not evident in development. It only became apparent once the files had been loaded to the server. This is fairly typical for large-bandwidth Flash projects, and should serve as a reminder always to test on-line.
Here's how I came up with a solution for the problem--certainly not the most elegant and perhaps not the best, but at least effective.
Analysis
My first thought was to deploy all the character animations in a single movie which could be loaded immediately after the main movie was loaded. Particular dissolve-in sequences could be accessed either as scenes in this movie or (my preferred choice) as segments of a single timeline, punctuated by stop() frame actions.
This concept does work; but there are some interesting complications along the way.
Remember that there must be two distinct levels in this project in order to separate the timeline of the main animation, which pauses, from the animation of the character fade-in. Remember also that the main animation comes in the form of a QuickTime movie, which requires the entire project to be delivered via the QuickTime plug-in, not the Shockwave Flash plug-in.
These two requirements create a fatal problem. In order to access scenes or timeline segments from a single movie, I need to use the gotoAndPlay() command across levels, using code like this:
_level1.gotoAndPlay(X);
where "X" is some scene or frame in the fade-in movie. This procedure works just fine in a Shockwave object movie (.swf), but it will not work with a QuickTime movie (.mov). QuickTime does not implement enough of the Flash data structure to make cross-level commands work.
So I had to discard QuickTime and create a new version of the project whose object file could be delivered as Shockwave, thus having full access to ActionScript effects.
Solution
Fortunately, it's relatively easy to convert a QuickTime video source to a sequence of still images. I set up a new movie, imported my QuickTime source into it, invoked Export Movie, and exported a JPEG sequence. To keep file size small, I knocked image quality down to 75%. Since my images were fairly crude to start with, there was no appreciable degradation.
The result was 85 individual images, one for each frame in the original video. Then I returned to my "Sleeper" project file, deleted the layer containing the QuickTime element, and put a new layer in its place. In the first frame of this layer I imported the first JPEG in the image sequence. Because the images were automatically given serial names (e.g., "jpeg0001.jpg", "jpeg0002.jpg", etc.) during the QuickTime-to-JPEG conversion, the Import action in Flash asked me if I wanted to import the entire sequence. I answered yes and ended up with 85 keyframes, each containing one of my images. This layer of keyframes is functionally identical to the QuickTime element.
My next task was to create a composite Flash movie by stitching together the seven individual character movies used in the first version of the project. I named the resulting movie "figures.fla" and exported a Shockwave version called "figures.swf". Then I added an action on the first frame of the "Sleeper" movie to load "figures.swf" into Level 1.
The next task was to change the keyframe scripts which in the original version loaded one of the seven character animations into Level 1. Instead of using loadMovie(), I substituted the gotoAndPlay() code discussed above. Each character fade-in comprises a run of frames in which the final frame has a stop() action.
Having done all this, I exported my revised "Sleeper" movie as a Shockwave (.swf) file and re-published its associated Web page.
Preloading
The result of this process was an object movie about 1.5 megabytes in size--far too large to be delivered in one quick download. Since the viewer/player can move through the movie very rapidly if she chooses, 100% of the content must be available at the start of interaction. Thus it was necessary to add a preloading stage.
I added a second scene to the main "Sleeper" movie, renamed the original Scene 1 as "Scene X", named the new scene "Scene 1", renamed "Scene X" as "Scene 2", and reversed their order in the Scenes panel. The new Scene 1 (the scene I added) provided the place to do my preloading work.
I created two frames in the Scene 1 timeline and placed the following script on the second frame:
if(_framesLoaded >= _totalFrames){
gotoAndPlay("Scene 2", 1);
{
else{
_root.firstView._alpha = (_totalFrames/_framesLoaded)*100;
gotoAndPlay(1);
}
This frame action script (note the absence of a handler) refers to two properties of the present movie: _totalFrames, which indicates the total number of frames in the movie, and _framesLoaded, which indicates how many frames are currently stored in memory. Yes, Flash knows how many frames a movie contains even before it loads them all. Comparing the two values allows us to hold off full interactive engagement until all the content is in place.
When fewer than the total number of frames have been loaded, the script does two things. First it sets the alpha of a Movie Clip named "firstView" to the percentage of frames that have been loaded. "Firstview" contains the graphic from the first frame of the main animation. As more of the movie loads, this graphic becomes more opaque. Once this alpha adjustment has been made, the script loops back to frame 1 of the present scene (Scene 1), which in turn succeeds to frame 2, re-running the script. I'm not sure it's necessary to use two frames here, but it seems safer to do so.
In the actual version of the project you'll also see a pair of rotating gears meant to suggest some sort of machine, for instance a film projector. These are added as a second visual index of the loading process.
So why bother with QuickTime?
In some cases--for instance, the Turismo project--video effects and Flash effects work together just fine. If you need to do more ambitious things with ActionScript, however, you may need to consider converting the video content to some more Flash-friendly format. It's good to have both approaches in your repertoire.
Source file
The source file for the improved "Sleeper" project is called sleeperPreload.fla. It can be found in MMShare/sleeper/ on Crow.
