Video icon 64
Learning to code? Skill up faster with our practical video courses. Start your free trial today.
Advertisement

The Comprehensive Guide to Preloading a Single SWF File

by

In this tutorial we'll create a SWF that preloads itself, meaning that the preloader and the content is in the same file. We'll go over how to do things the right way and avoid the traps.


Step 1: What is Single SWF Preloading?

The idea of single SWF preloading is that you have a Flash object which preloads itself. That means that the preloader, with its associated functionality and assets, is embedded together in the same SWF file as the whole Flash movie or application.

We'll start off this tutorial with some theory and finish it off with creating an FLA together with a preloader class that you can use in future projects. During the course of the tutorial we'll discuss common pitfalls and important considerations.

Also, now that Activetuts+ has started focusing on document classes and generally keeping things in class files as much as possible, we'll do just that in the practical part of this tutorial. Check out the Quick Tip: How to Use a Document Class in Flash if you need to learn the basics.

Make sure you have an updated version of either Flash CS3 or Flash CS4. I know for certain that a later CS4 update has changed the way classes are loaded and that can make all the difference here!

I'll admit right away that this tutorial is quite lengthy for this narrow subject, but it contains all you need to know, so buckle up and let's get to it!


Step 2: Why Single SWF Preloading?

The idea of a preloader is quite obvious: you want to make sure the user gets visual feedback indicating that the Flash object is loading. Embedding a large Flash file that takes 10 seconds to load could mean the difference between users staying or leaving the website, should it not be for the preloader telling the user to hold on.

The process of creating "self preloading" Flash files presents some issues and problems. There are other preloading techniques that are really easy to put together, such as one SWF file preloading another and adding it to the stage once loaded.

So why bother? Well, there are situations where you have no choice.

For example, you might want to create Flash games which you hope to spread to as many Flash gaming portals as possible. Most of these portals only support games in form of a single SWF file which leaves you with no choice but to make sure that your game preloads nicely from within itself.

Aside from such obvious examples, there's the argument of having a completed product in only one file which makes for easy managing.


Step 3: How SWF files are Loaded

When your browser stumbles upon a Flash object and starts loading it, it starts from the beginning of the timeline. It loads the frames one after another. As soon as the first frame is loaded, it can be displayed.

Our approach here is to put a preloader on the first frame so the user sees something happening, while the browser continues to load the rest of the file. We write code to check the overall progress and when it's completed we continue on to the main content of the file.

The challenge is to keep the size of the first frame to a minimum. If you let code and sounds pile up in the first frame you might have a preloader that's not visible until after you've loaded maybe 60% of the movie.

A great tip when it comes to using a percentage counter that displays numbers is to use a font that is small in byte size. But this only takes you so far. Unfortunately we have to work quite a bit harder to have things our way!

It's been said many times before and it's worth saying again:

Preloaders, the hardest of the simplest tasks in Flash..

Step 4: The Defining Variables

There are a number of things that will affect what will be put in which frame, such as:

  • Where on the timeline you put assets.
  • Which frame you choose as the "class export frame" (see Step 11).
  • Whether you put assets before or after the class export frame.
  • In Flash CS4 - choosing whether or not to export the asset in the class export frame (in the symbol properties dialog).
  • In Flash CS3 - choosing whether or not to export the asset in first frame (in the symbol properties dialog).
  • Whether you use sounds.

Step 5: The Problems

The main problem we face is controlling what ends up on frame one, because, as mentioned above, everything on frame one has to be loaded before the preloader can be displayed.

Other than that, there are differences between how Flash CS3 and CS4 work. In the next step I'll make a number of thoroughly researched statements that you can refer back to if need be. It should be a great resource if you quickly want to troubleshoot your preloading, to figure out why it's not behaving the way you expect.

I'll try to make the statements a bit more tangible by referring to TweenLite, a great tweening library by Jack Doyle over at greensock.com. We'll be using TweenLite in the hands-on part of this tutorial so this will make the most sense.


Step 6: The Statements

These statements hold true for both Flash CS3 and CS4 unless stated otherwise. "Importing TweenLite" basically means "importing and using TweenLite" - the results may differ if you don't actually use the code as the Flash compiler disregards unused imports. Simply typing an import statement does not equal using the code.

  • If you import TweenLite on any frame in the main timeline, TweenLite will be loaded in the first frame of the movie.
  • If you have a MovieClip that imports TweenLite in its internal timeline and place this MovieClip after the class export frame, TweenLite will be loaded in the class export frame.
  • If you have a MovieClip that imports TweenLite in its internal timeline and place this MovieClip before the class export frame, TweenLite will be loaded in the first frame of the movie.

The next three statements refer to the scenario where you have a MovieClip which is exported for ActionScript, using an external class file, which in turn imports TweenLite in the class file.

  • Placing the MovieClip after the class export frame will make TweenLite load on the class export frame. There is no difference whether or not you check the "Export in frame X" ("Export in first frame" for CS3) regarding imported classes such as TweenLite. However, the checkbox affects whether or not the assets (shapes, bitmaps) of the MovieClip will be loaded in the export frame or not. In the case of CS3, you can of course only choose wheter or not to load it in the first frame.
  • In Flash CS4 placing the MovieClip before the class export frame will make TweenLite load on the first frame. There is no difference whether or not you check the "Export in frame X". The non-code assets of the MovieClip will also load on the first frame.
  • In Flash CS3 if you place the MovieClip before the class export frame, then regardless of whether you've checked "Export in first frame", you will get a silent fail! Meaning: the MovieClip you put on stage that should be using an external class file will just appear as a normal MovieClip, not giving you any indication whatsoever. You can still, however, affect whether the shape/bitmap contents of the MovieClip should be loaded in the first frame or not. This doesn't really help though as you are equally screwed with the class loading.

The next three statements refer to the scenario where you have a MovieClip that is exported for ActionScript as "CustomClass", either using an external class file or not, which is instantiated and added to stage from a MovieClip that is placed on the timeline (just like the MovieClip from the previous three statements.) This CustomClass is only instantiated and does not previously exist on the main timeline.

  • In Flash CS4 with the "Export in frame X" box checked, CustomClass is loaded in frame X and will display correctly. With the box unchecked it is still loaded in frame X and is displayed correctly.
  • In Flash CS3 with the "Export in first frame" box checked, CustomClass is loaded in the first frame and will display correctly. With the box unchecked you will get a 1046 Type error, as the class cannot be found.

With all these restrictions, let's at least consider this positive statement:

  • If you place a MovieClip that only contains shapes/bitmaps, it will only load right before the frame it is needed. Unless you choose to export it earlier, that is!

Here's a really interesting one:

  • In Flash CS3 you cannot export a sound on anything other than the first frame. In Flash CS4 you can, on the class export frame.

Yes, you read that right. I guess it's fair to assume that Adobe wants people to upgrade to CS4. So what to do if you're stuck with CS3 and the grass is greener on the other side? I'll tell you in the next step.


Step 7: Loading Assets in Flash CS3

This whole step is just for those of you using Flash CS3.

If you read through all the statements in the previous step then you'll realise the problem of having lots of MovieClips exported for ActionScript. These will all have to be loaded in frame one, or be unavailable. Luckily, those statements were under the assumption that those assets were never placed on the main timeline, which happens to be our solution! (This is also the only way to load sounds other than in frame one..)

This is how it's done:

  1. Go into the properties of all the MovieClip/Sprite/Sound assets you want to export and uncheck "Export in first frame".
  2. In the second frame of the main timeline, create an empty MovieClip called AssetHolder.
  3. In this AssetHolder MovieClip, create an actions layer that has a stop(); call on the first frame.
  4. Still in the AssetHolder, create a layer for each sound you want to use and drag those sounds out to the second frame of its own layer. They do not need to be longer than one frame, luckily. For all other Sprites and MovieClips you can place these in a single layer or multiple for easier organizing. Put these on the second frame as well and leave the first frame empty.

This will make all your assets load in the second frame. The solution is a bit tacky, but it's not as rough as having to go and buy new software for this one particular issue.

(Kudos to 8bitrocket for this trick!)


Step 8: Bandwidth Profiler & Size Report

One thing I should mention before we start working is the bandwidth profiler. This is an essential tool in sorting out your preloading problems. When you preview a movie you can go up to view, then choose bandwidth profiler. Or just hit Ctrl+B.

Here you can switch between frame-by-frame graphs and streaming graphs. You can also simulate downloading the movie at a connection speed of your choice by either choosing it from the View menu or hitting Ctrl+Enter once again (change the simulated download speed using the View > Download Settings sub-menu). This is essential in finding out how your preloader will look, without going through the hassle of uploading it and capping your bandwidth. For that specific case though, I can recommend Firefox Throttle.

Besides the very useful tool that is the bandwidth profiler there is the option to generate a size report. Hit Ctrl+Shift+F12 to open up the Publish Settings dialog box.

Go to the Flash tab, and in the Advanced section there is a checkbox labeled "Generate size report". When this box is checked, previewing or publishing your movie will generate a text file in the same folder as your FLA file that contains useful information on what parts that make up the total size of the movie.


Step 9: End of Theory

Finally we can start making a Flash movie with a nice self-contained preloader!

We'll be employing a "three frame preloading" technique. On the first frame we'll put a preloader MovieClip that has its own class "Preloader". On the second frame we load all the classes and on the third frame we load and display the content. We'll put the content in a MovieClip named Application with an associated class "Application". This is where the meat of the application goes.


Step 10: Create New Document

Start by creating a new AS3 document. I'm making it 600x400px, dark gray background, 24 FPS. These settings don't matter though.

Set the document class to Main and hit OK.


Step 11: Set the Class Export Frame

Go to File > Publish Settings, the Flash tab, then the ActionScript 3.0 settings. Type in "frame 2" in the "Export classes in frame" field.


Step 12: Design a Preloader

Obviously the design of a preloader won't affect the function. I'll give step by step instructions, but feel free to skip these parts and take your own approach if you so wish. Just make sure you note what parts I refer to in the code later on.

Draw a rectangle with rounded corners and give it a blue gradient. Then turn it into a MovieClip symbol, call it Preloader. Choose to export it for ActionScript and call the class Preloader.

Within this new MovieClip, draw a new rounded corner rectangle with a gray gradient, turn it into another MovieClip and give it an instance name of progressArea.

Go ahead and match up the layer layout I've got going on in the picture above. Next, make a duplicate of the last shape and place it in the Progress bar layer on top of the Progress area one. Give it a light blue gradient, turn it into a MovieClip and give it an instance name of progressBar. Enable guides for 9-slice scaling and make sure you keep the left and right round edges outside.

Lastly, make a dynamic text field with an instance name of percentageText. Make the text right-aligned. That way, the percentage sign will never move, only the numbers (which change anyway). Go into character embedding and make sure you embed numerals and the percentage sign (%). To make a really small preloader I'm using a small pixelfont called Pixel Mix from dafont.com. I'm also giving it a blue glow just because I can.


Step 13: Back to the Stage

Make sure the whole preloader MovieClip is placed in the first frame and given an instance name of preloader. Create a new layer called "AS" and put a stop(); in the first frame. Keep the preloader in its own layer, "Preloader". Make another layer called "Application". This is where we will keep the main content in the end.


Step 14: Create the Main Class

Create a new ActionScript file and save it in the same directory as your FLA file. Name it Main.as:

package
{
	import flash.display.MovieClip;
	import flash.events.Event;
	
	public class Main extends MovieClip
	{
		public function Main()
		{
			preloader.addEventListener(Event.COMPLETE, onPreloaderComplete);
			preloader.setLoaderInfo(loaderInfo);
		}
		
		private function onPreloaderComplete(e:Event):void
		{
			gotoAndStop(3);
		}
	}
}

Step 15: Create the Preloader Class

Create a new ActionScript file and save it in the same directory as Preloader.as:

package
{
	import flash.display.LoaderInfo;
	import flash.display.MovieClip;
	import flash.events.Event;
	import flash.events.ProgressEvent;
	
	public class Preloader extends MovieClip
	{
		public function Preloader()
		{
		}
		
		public function setLoaderInfo(ldrInf:LoaderInfo):void
		{
			ldrInf.addEventListener(ProgressEvent.PROGRESS, onProgress);
			ldrInf.addEventListener(Event.COMPLETE, onComplete);
		}
		
		private function onProgress(e:ProgressEvent):void
		{
			var percent:int = Math.round(e.bytesLoaded / e.bytesTotal * 100);
			progressBar.width = percent / 100 * progressArea.width;
			percentageText.text = percent + "%";
		}
		
		private function onComplete(e:Event):void
		{
			dispatchEvent(e);
		}
	}
}

Step 16: Grasping Main and Preloader

So what do these two classes do?

In Main's constructor, we call the custom setLoaderInfo() method of our preloader and pass along the LoaderInfo object that is associated with Main.

Preloader receives this object and adds two event listeners to it. The ProgressEvent triggers the onProgress function, in which we calculate the percentage of the bytes loaded compared to the total bytes to be loaded. The percentage is used to set the width of the progress bar and the text of our text field.

The complete event is simply dispatched back down to Main which in turn jumps the main timeline to frame three when receiving the event.


Step 17: Adding Some Content

To have something to clearly show the preloader working, I'm adding a nice macro photo of a cat called Runa taken by a friend of mine. You can find the image in the source files provided with this tutorial. I've imported the bitmap and I turn it into a MovieClip called "Cat".

Feel free to use whatever image you find suitable. Give the clip an instance name of "cat".


Step 18: Creating the Application MovieClip

As you can see on the screenshot above I've placed the Cat MovieClip on frame three in the Application layer. Take whatever MovieClip you made, cat or no cat, and hit F8 once again to nest it inside a new MovieClip which you call Application. Export this for ActionScript as Application.


Step 19: The Application Class

Create the Application class by starting a new AS file and saving it as "Application.as". Have the Application class look like this:

package
{
	import com.greensock.TweenLite;
	import com.greensock.easing.Sine;
	import flash.display.MovieClip;
	
	public class Application extends MovieClip
	{
		
		public function Application()
		{
			TweenLite.to(cat, 7, {
						 scaleX:4,
						 scaleY:4,
						 onComplete:tweenBack,
						 ease:Sine.easeInOut});
		}
		
		private function tweenBack():void
		{
			TweenLite.to(cat, 3, {
						 scaleX:1,
						 scaleY:1,
						 onComplete:reTween,
						 ease:Sine.easeInOut } );
		}
		private function reTween():void
		{
			TweenLite.to(cat, 7, {
						 scaleX:4,
						 scaleY:4,
						 onComplete:tweenBack,
						 ease:Sine.easeInOut } );
		}
	}
}

This will animate the cat in and out indefinitely so you will forever remember the detail of her nose fur. How this class works isn't important, what is important is that we're importing TweenLite and using it, thereby making sure that it will be a part of the SWF file once exported.


Step 20: CS3 and CS4 Issues

Let's go back to the school bench again for just a minute.

This movie compiles fine in CS4. The Application MovieClip is set to export on frame 2 unless you've changed it. If you've changed it you might notice something strange. More on this in the next step.

If you're on CS3 this setting really matters. You'll have to go and make sure you uncheck the "Export in first frame" checkbox in the Properties of the Application MovieClip, otherwise it will all load in the first frame!

That's not the only problem. If you try to compile you will get a 1046 Type error, saying that you don't have the type TextField available. So as you can guess, CS3 does things a bit different. What's happening? Well, you are trying to use a TextField inside the Preloader MovieClip but you don't have it imported. In CS4 this is handled automatically for you, but not in CS3.

Fortunately the solution is simple, just add:

import flash.text.TextField;

to your Preloader class, and you're all set.

Some of you might have thought already that I should've extended Sprite for my Preloader class instead of MovieClip. Well, this is the reason I didn't do that; I wanted to wait until this point to bring it up. Since the Preloader symbol contains both the "ProgressArea" and "ProgressBar", which both are MovieClips, you would've gotten the same 1046 Type error.

The same solution is possible here too of course. In fact, you should now change the Preloader to extend Sprite instead of MovieClip, and if you're using CS3 make sure you import the Sprite class inside the Preloader class as well.


Step 21: Yet Another Issue

I mentioned a strange occurrence in the last step. If you uncheck the "Export in frame 2" of Application and run a simulated download, you'll see the preloader disappear, unless you've extended the preloader's keyframe to cover the second frame as well.

So what's really happening? Simply put, the first stop(); statement doesn't count. How's that for obvious work flow planning? Note that if you put a trace statement in the first frame after the stop(); call, it does trace out. Important: note that this problem only shows itself when we're simulating download!

The lesson learned here is don't trust the simulated download! It won't show you accurately how things will load and function. You can just keep the stop(); and preloader in the first frame and you'll be fine when it comes to deployment. However it can be a pain to preview unless you have Application set to export on frame 2. And that's just for this specific scenario.

In CS3 you have to uncheck the export box on the Application MovieClip otherwise you'll end up with it loading in the first frame. But if you do that, you'll run into this issue. So go ahead and extend the preloader to the second frame.


Step 22: Test the Movie

Go ahead and preview the movie. Run a simulated download on a low speed and enjoy the masterfully* crafted preloader (*masterfully only applies if you've followed my instructions to the letter).

If you look at the frame-by-frame graph, or a generated size report, you'll see that the code is loaded in the second frame. The first frame is only 4kb and consists of the Preloader class and the embedded font glyphs. Now, 4kb is quite affordable as far as wait time before seeing the preloader is concerned, don't you think?

You might see different sizes on CS3 and you will definitely see different sizes with different fonts. Or cats.


Step 23: Tweening the Preloader

You might have the idea that you would like to use TweenLite to fade away the preloader by tweening the alpha to 0 - but you don't want to load TweenLite in the first frame since that adds another 8kb to the initial download.

There are several ways to accomplish this and we will solve it by having a MovieClip on the third frame that catches the preloader and tweens it. When completed, it will advance to the fourth frame, which we'll have moved Application to.

The reason for putting it in the third frame is that we can't put it in the second frame without having TweenLite being loaded in the first frame.

Now we're moving away from the standard three frame preloading technique.


Step 24: Add a Layer and Stop(); Calls

Add a new layer called "Preloader catcher". Make sure you put stop(); calls on frames one, two and three. This is to prevent messed up previewing when simulating a download, as mentioned earlier.

Go ahead and move Application to the fourth frame as well as extending Preloader to the third frame.


Step 25: Create the Catcher

Make sure you have a keyframe on the third frame of the Preloader catcher layer. Go to this frame, draw a small shape and have the alpha of the fill color set to 0%. This is supposed to be an invisible MovieClip. Turn it into a MovieClip symbol called PreloaderCatcher or something similar.

Export the MovieClip as PreloaderCatcher. If you're using CS4 it doesn't matter if you export it for frame 2 or not, since it will be loaded in that frame no matter what. Well, it does change one thing, remember? Whether or not the shape is loaded on frame 2. In essence it doesn't matter considering the near non-existent file size for this shape. You might as well uncheck it for good habit though.


Step 26: The PreloaderCatcher Class

Make a new class file called PreloaderCatcher.as:

package
{
	import com.greensock.TweenLite;
	import flash.display.MovieClip;
	import flash.display.Sprite;
	import flash.events.Event;
	import Preloader;
	
	public class PreloaderCatcher extends Sprite
	{
		public function PreloaderCatcher()
		{
			addEventListener(Event.ADDED_TO_STAGE, onAdded);
		}
		
		private function onAdded(e:Event):void
		{
			removeEventListener(Event.ADDED_TO_STAGE, onAdded);
			
			var preloader:Sprite = MovieClip(parent).getChildByName("preloader") as Sprite;
			
			TweenLite.to(preloader, 0.5, {
										alpha:0,
										onComplete:function():void
											{
												MovieClip(parent).nextFrame();
											}
										} );
		}
	}

As you can see, this class works by first obtaining the preloader by casting the parent as a Sprite and calling getChildByName("preloader"), where preloader is the instance name. The preloader is cast a Sprite as well, then TweenLite is used to fade it out.

When the tweening is complete, the onComplete function in TweenLite casts the parent as a MovieClip so it's possible to call the nextFrame method.


Step 27: Why the Four Frames?

As I said before, we've now moved away from the three frame preloading technique. That in itself isn't exactly blasphemy, but I'm sure some of you wonder why we did that. Instead, we could've handled the preloader tweening inside the Application clip..

In that case, you are perfectly right! The reason I used four frames here was to show you how to do it while keeping things separated. Tweening away the preloader; does that belong to the preloader part, or the Application part? Preloader definitely, but in this case we didn't want it to load in the first frame. Therefore, we end up with this extra "catcher" class.

Just remember that this is all optional. Once you know how to do everything you can easily decide whatever your situation requires.


Step 28: Sounds and Extra Assets

In Step 7 I told you about the asset loading problems in CS3. Since this tutorial is aimed towards both users of CS3 and CS4 we will go with the lowest common denominator and use the AssetHolder approach. If you're using CS4 you can perform the next steps the same way and it will work just the same, or you can skip the AssetHolder approach.

Start by importing the "music.wav" sound from the source files into your FLA.

Go in and export it for ActionScript and make sure you uncheck the "Export in first frame" box in CS3. For CS4 this won't make much of a difference. I'm using Flash CS4 which you've probably figured out by now, so the screenshots show the CS4 dialog box. If you want to you can switch from the default MP3 compression to something more pleasing. That way it won't sound terrible.

Let's go through a couple more steps, adding some text to the movie and putting it all in an AssetHolder MovieClip!


Step 29: Create Some Text

Hit Ctrl+F8 to create a new MovieClip symbol. Name it TextHolder and export it for ActionScript, once again (in CS3) making sure the "Export in first frame" box is unchecked.

When creating, you will be "inside" this MovieClip. Type some static text and give it a white color. I'm using the same PixelMix font as before. To create a simulated stroke color, I give it a glow filter effect with the settings seen below.


Step 30: Create the AssetHolder

Create a new layer called AssetHolder. Make a keyframe on the second frame, hit Ctrl+F8 to create a new MovieClip and name it AssetHolder. Do not export this for ActionScript.

In the AssetHolder MovieClip, create three layers called AS, music and Assets. Since "music" is the name of the sound object we're using, that's what I'm naming the layer. Now you must put a stop(); call on the first frame of the AS layer.

Next, make a keyframe on the second frame of both the music and Assets layer. Drag the music sound onto the stage when you're standing on the second keyframe in the music layer. Then do the same with the TextHolder MovieClip onto the Assets layer.

Exit out of the AssetHolder MovieClip and make sure you place it on the second keyframe of the AssetHolder layer on the main timeline. As you'll notice, the MovieClip is not visible, but it is placable, which is quite cool!


Step 31: Changing the Application Class

Alright, now we just want to make sure we play the sound and show the TextHolder MovieClip. Add this to the Application class's constructor:

var s:Music = new Music();
s.play();

var textHolder:TextHolder = new TextHolder();
textHolder.x = 120;
textHolder.y = 20;
addChild(textHolder);

Step 32: Preview the Movie

Go ahead and preview the movie. You should now, regardless of whether you're on CS3 or CS4, be able to simulate a download of this movie and see it preload beautifully starting from 1 percent! Note that it isn't starting at 0 percent. Had our contents been larger and the preloader smaller then that could have been possible.

Now, you might wonder why you're staring at this orange cat paired with a short gameshow-esque music tag. This is normal to ask yourself.


Conclusion

Hopefully now you should have all the knowledge you need to preload things the way you want, in a single SWF file! To see the final version of all the class files just download the source files for this tutorial and check them out.

I'm unhealthily obsessed with this subject so I'll gladly enter into discussion in the comments. Please join in if you have questions or ideas!

Advertisement