Two ways of preloading in ActionScript 3
Preloader is one of these things that are essential when building a Flash project that will be published on the internet. Firstly, it prevents from playing before all its content is loaded. Without it, animation could start without somactioe of the movie clips on the scene. Secondly, it informs users how long they need to wait before downloading is complete, so they either can close the browser and search for some other content that loads faster (the worst case scenario
) or they can wait few more seconds to experience your great work. There are two ways of preloading your content, you can create "internal" preloader for a movie clip itself (should I call that selfpreloader?) or you can create one swf file - loader that will load another swf file - your main project.
In both approaches you need to access LoaderInfo object either through loaderInfo property when preloading the clip itself or contentLoaderInfo when loading external content using Loader object. The diagram below from Adobe illustrates this:

Self preloading
This method would suite you when you don't want to have any external files, you just want to have one swf file (this is usually the case when creating the Flash games as most of the websites hosting them require just one file). Although you may find many preloader tutorials on the internet, not all of them mention that this way of preloading work correctly only if you won't forget to "tell" Flash to keep your all assets like images, movie clips, sound etc away from the first frame. Also not all of them say about the bug in Internet Explorer that will prevent dispatching COMPLETE event. I will explain that further in a minute.
First, let's create a new project and import some massive bitmap file (in terms of MBs) on the stage. The bigger image then better as it would be easier to test your preloader progress. Save the project and create a new ActionScript file. Save it as a InternalPreloader.as file in the same folder where the fla file is (your main project).
We need to import two types of events: ProgressEvent and Event. The whole thing about the proloading is to add event listeners to the loaderInfo property. ProgressEvent.PROGRESS will be dispatched as soon as the loading starts and will carry on information about number of bytes already loaded and total number of bytes that needs to be loaded. OnLoading function will be continually called during the downloading process. To get percantage loaded we divide current number of bytes loaded and total number of bytes and multiply by 100. Next we use Math.floor to make it integer value and convert to String so it can be printed by the textField. This will update user with the current loading status. Event.COMPLETE will indicate that the process is complete and we now can start the movie and remove preloader textField with event listeners that won't be used anymore.
1 |
package |
Once you save the ActionScript code, go back to the main project and in Properties panel, type the name of your document class "InternalPreloader" to the Class text box, as on the picture below:

Now, how to test the preloading process? You can either upload it on your webserver or even better use Flash Simulating Download feature. When trying this on your webserver, your internet connection may be too fast (unless you have placed 20 MB bitmap on the stage or you're still on the modem). Also your browser (and/or proxy server) may cache your swf file, so you wouldn't be able to test it again until you clean your cache. This is why it's better to test preloader from Flash at the developing phase and finally, when project is done on the webserver. To use Simulated Download feature, test movie as usually, by pressing CTRL + Enter. When player window pops up, select View and Download Settings and DSL - this should be enough for a test. Now hit CTRL + Enter again to see the effect.

Movie starts after a while, but you don't see any progress information, only traced output message "Fully loaded, starting Movie". The reason is that Flash first loads all the assets from the stage and library and then launches the script with the code (and our preloader). To avoid that, go back to your project, go to the timeline and move the image object from the first frame to the second. Now test the movie again. You should see a text field in the middle of the stage indicating loading progress and after that the actual image.
So far so good, let's do another test, this time leaving a timeline empty. Remove the second frame from the timeline and the image, leave the first frame empty. Create new Movie Clip (F8) and drag and drop into it your image from the library. Now you should see new movie clip in the library - containing the image. Right click on it, choose properties, select Export for ActionScript and give it a class name "Image".

Now we are going to add this image on the stage from the ActionScript level. I modified our code by adding a line to create a new variable of type Image and adding it on the stage when the whole movie is loaded
1 |
package |
Now when you test the movie, you will notice that again preloader doesn't show the progress. Although the first frame on the timeline is completely empty, Flash loads all library assets (sprites, movie clips, sound objects, everything what you imported or created there) along with the first frame. So again, you need to let Flash know that you want to import all this things at the second frame. To do that, go to File / Publish Settings, select Flash tab, click on Settings button, next to the Script drop down:

Now change Export classes in frame value from 1 to 2 as on the picture below:

Note that, after you set Flash to export your assets in frame number two, you won't be able to instantiate any of the classes unless you are actually in frame number 2 or further. Flash DOESN'T know about any of the library objects in frame one.
That is why in the code I first move to the second frame and then instantiate the image object. You also need to create the second frame on the timeline (if you still have only one frame), otherwise Flash won't be able to move there.
To ensure that everything is imported in the second frame, you can use Bandwidth profiler that presents the amount of data loaded at each frame. To enable it, press CTRL+B when testing the movie. Screenshot below shows that one MB image is loaded at the second frame (each column represents data on each frame).

There is also another important thing to remember, your movie may not work properly in Internet Explorer 6 if Flash Player 9 is installed (works fine on FF / Safari etc). There is a problem with dispatching Event.COMPLETE event. This bug has been fixed in never versions of Flash Player (>9). But you never know what version may be used by your users, maybe they haven't updated player to the lasted version? What would happen in this case is that the movie will never start, it will finish with percentage loaded 100% and then stop doing nothing else. The workaround is to add an event listener for ENTER_FRAME and check for condition bytes loaded = total bytes (instead of waiting on COMPLETE event).
addEventListener(Event.ENTER_FRAME, waitOnComplete)
Loading external files
This is probably a preferred method for most of the developers as you don't have to worry about headaches like exporting any assets to other frames. In this apporach, two separate Flash projects are required, your actual movie and a preloader. Remember that a preloader needs to be as small as possible, so you shouldn't add any bitmaps or sounds into it (otherwise you will need to create a preloader for your preloader...). The preloader file will load your swf file and once this is complete, will start it. You can use the same method of preloading to load other supported files like JPG, MP3, FLV.
First create a new Flash project, import the same big bitmap on the stage, save it as mainMovie.fla and publish it to SWF file. Next create a new ActionScript file, save as ExternalLoader.as and use the code below. It is quite similar to the code from internal method, this time we use Loader object to get the external content and use currentLoaderInfo to get information about progress (refer to the diagram from beginning of this article).
1 |
package |
Next create the new Flash project again, add ExternalLoader.as as the Document class and save it as externalLoader.fla.

Now test the movie using simulating download feature (as before with internal loader example). Your externalLoader.swf should load mainMovie.swf indicating the progress and at the end it will play it. Happy days.
Sometimes you may need to have more control when the loaded movie starts to play, for example when you load more external files and want to play them all together at the same time (when the last assed is loaded). This may be the case when creating games - you may have external swf file with the game and mp3 file with the background music and you want to hold on with starting your game until the music is loaded. To do that, you can just control their timelines, by using play() from the loader object. You can create movieClip object myLoadedMovieClip (or you can use just myLoader.play()) and then within the onComplete method replace addChild(myLoader) with the lines below. Note that casting is necessary when assigning the reference of loader content to the MovieClip object. And of course you should stop the loaded movieClip (in our case mainMovie.swf) timeline by adding stop() in it's first frame.
//add loaded object
myLoadedMovieClip = MovieClip(myLoader.content);
myLoadedMovieClip.play();
addChild(myLoadedMovieClip);
The other method of controling when loaded movies are played is to listen for the Event.ADDED_TO_STAGE event from the loaded movies side. This event is fired every time when a movie clip is added to the stage. In our example loaded mainMovie.swf will receive that event when the exteralLoader.swf will execute addChild(myLoader.content). This is the code that you use in our mainMovie.swf.
1 |
package |
Improving preloading experience
There are several ways of graphically improving either internal or external preloader. Text field showing just percentage of a movie loaded is informative enough but sure not the sexiest thing you can do. There are many good tutorials with great ideas and examples.
Popular way of representing progress is to use a progress bar. You can do that by creating a movie clip of a rectangle representing 100% load. Instead of passing a progress as a string to a text field, you can scale your rectangle using a line below. Remember to register your movie clip to the left side, otherwise your movie will grow in different directions than right.

progressBar_mc.scaleX = e.bytesLoaded/e.bytesTotal;
You can also use ProgressBar that is one of the Flash components.
The other way, that gives you fancier options, is to create animated movie clip 100 frames long. Every new percentage loaded will be represented by different a frame.
progressBar_mc.gotoAndStop(Math.floor((e.bytesLoaded/e.bytesTotal)*100));
There are much more ways of doing your preloader, imagination is the only limit :). If you lack of the ideas, browse internet as there are many tones of tutorials on how to improve your standard preloader.
Links
There is a nice tutorial by Jeff Fulton on creating preloaders for games on 8bit rocket : http://www.8bitrocket.com/newsdisplay.aspx?newspage=10807


Comments
Thats a great example, just there is one issue. What to do when flash is not getting bytesTotal?
function loadAnotherFile (path:string):v oid
{
myLoader.contentLoaderIn fo.addEventListene r(Event.OPEN, onOpen);
myLoader.contentLoaderIn fo.addEventListene r(ProgressEvent .PROGRESS, onProgress);
myLoader.contentLoaderIn fo.addEventListene r(Event.COMPLETE, onComplete);
myLoader.load(new URLRequest(path ));
}
Then you can call this function as below: loadAnotherFile ("yourExternalFil e.swf");
I just tried your script on "Loading External Files" and all works beautifully except that once my 4-frame main swf is loaded, none of the buttons work. Also, I am a bit unclear how to call the preloader everytime I want to load an external swf into the main swf.
Suggestions?
thanks.