How to Create a Self-Contained AS3 Loader
Posted by: Sam Horton on Apr 11, 2008 at 12:02 PMEver since making the switch to AS3, like many others, I have had to re-learn several routine tasks such as making pre-loaders for my games. After hunting through the Flash CS3 docs and coming to the realization that all of the examples were focused on loading external files, I turned to the mighty Google in an attempt to shed some light on creating a self-contained loader. Most examples just parrot the help files, but after a long search, I've got something that seems to be working exactly like the good old days of sloppy AS2!
If you can get away with loading external swf files, then I have to admit, it is a much more straight forward process, but in the Flash Games Business, it is very important to have everything packaged in one tidy swf file. Many portals will not accept games with multiple files, since they may not work within their existing infrastructure. We don't want to do anything that will prevent our games from spreading virally, so a single swf is best!
First I'll toss the code out there for the folks who want to get right to it. This script goes on frame one of the main timeline, which normally contains some type of loader bar and text display to show the loader's progress.
/*
"myloader" is a movieclip on the timeline
that contains the loader-bar and a text field
*/
this.stop();
import flash.events.ProgressEvent;
import flash.events.Event;
import flash.display.*;
loaderInfo.addEventListener(ProgressEvent.PROGRESS, loadProgress);
loaderInfo.addEventListener(Event.COMPLETE, loadComplete);
function loadProgress(e:ProgressEvent):void {
var pct:Number = loaderInfo.bytesLoaded/loaderInfo.bytesTotal;
myloader.l_txt.text=int(pct*100)+"%";
myloader.l_bar.width=pct*186;
}
function loadComplete(e:Event):void {
this.gotoAndStop("menu");
}
Nice and simple, but just like a free vacation, there are a few catches. When you want to dynamically create an instance of a Sprite or MovieClip in AS3, you need to give it a linkage identifier just like in AS2. The difference now is that Flash automatically associates a class with this asset; which you can either provide or choose to not worry about, depending on what capabilities you want for that particular asset. You also have the option to export this asset in the first frame, which will cause it to load before our preloader.
In the image above, I have an asset called "Eye" which has "Export for Actionscript" checked, as well as "Export in first frame". If I wanted to create an instance of the Eye, I would just write something like this:
var myEye:Eye = new Eye();
myeEye.x=100;
myEye.y=100;
someMC.addChild(myEye);
//etc...
...which is much nicer than the old attachMovie() from the AS2 days!
In many cases choosing "Export in first frame" is fine, but do this with enough assets, especially if they are large, and you will wind up staring at a blank screen while these assets load (before your preloader). To remedy this, I always try to un-check "Export in first frame", and never associate classes directly with my library assets from the linkage menu. Instead, I write custom classes that instantiate any Sprites or MovieClips I need; and in all reality, this allows for more flexible coding. I like to think of these as wrapper classes. For instance, say you are writing a particle engine class that needs to utilize many different Sprites. It wouldn't make sense to have the class directly associated with only one particular Sprite. It's best to think of these display objects as just a visual representation on screen, and not as the object that is containing and managing the code.
If you un-check "Export in first frame" then you will need to manually place these assets somewhere on screen, otherwise they will not be included along with your published swf file. The work around for this is the same as what we have already been doing for years. Just create a MovieClip with these assets inside it, and place it off screen. For sounds, make sure to create an extra frame that the playback head will never reach,(unless you enjoy hearing all of your sounds play simultaneously) then use the property window to add them to the timeline with start as the sync setting. See the image below for details:
So far this has worked like a charm, and I've done quite a bit of testing during the development of my new AS3 titles.
And just because we need something fun in this post, here is the source for the movie below, which demonstrates everything we've talked about. If you want to use the explosion animation in your games, then by all means, have at it. It was created in Lightwave, and I've been using it for years!
download source
Labels: AS3, AS3 Loader, AS3 Tutorials, Flash
There are 6 comments so far
Your tip on un-checking the "Export in frame 1" box alone has saved me countless bruises on the forehead, where it would have otherwise come into hard contact with a wall, or other heavy inanimate object. Thank you.
Glad to be of service Shawn!
I posted an update to this topic (for anyone who's interested) about a small glitch in IE that kept popping up when using Flash's built-in loader events:
AS3 Loader Update
It works!! thanks alot mate!!
It sounds good, but i have some trouble with sounds.
If i jump over the frame where sound is exported (2-nd in your example), or program is not reaching this frame, then class is initialized, but i get "invalid sound"-error, and my sound variable is null (.
I get results only if i really play sounds before calling them.
I have tryed to call this sounds with "stop" sync, instead of "start", but results were the same...
As i guess, my problem is like that: class is initialized, but sound data is omited during compilaion, because it "never used in my file".
It's definitely important that the timeline's playback head actually lands on the frame where the movieclip containing all of your sounds is located. As long as the sounds are situated on frame 2(you wouldn't want them to all play at once:) of this movieclip, and their sync setting is "start", they will load.
I'm using the Flash CS3 IDE, so your mileage may vary depending on what dev environment you are using.
Hope this helps!
Great thanks for explanation. Now it really works!!!