AS3 Avoider Game Tutorial, Part 8: Adding a Preloader

by Michael James Williams on February 24, 2009 · 185 comments

in Avoider Game Base,Tutorial

In the coming parts of this tutorial, we’ll be adding music, sound effects, and multiple levels, possibly with a range of different backgrounds and other images. These assets all make the game larger, meaning it takes longer to load. Therefore, in this part of my AS3 and Flash CS3 conversion of Frozen Haddock’s avoider game tutorial, we’ll create a preloader, to make sure everything is downloaded before the game can be played, and give the user some idea of how long this will take.

It’s a long tutorial, but that’s because I’m going to explain to you how and why everything works, rather than just give you a method to apply. Once you’ve gone through this, though, you’ll be able to use the same techniques to create a preloader for any other Flash game, movie, or application.

As usual, you can click the image below to see what we’ll have by the end of the tutorial — though with the SWF currently coming in at around 10kB, I don’t think you’ll see it load!

screenshot

If you’ve not been following the tutorial, grab the zip file of the game so far here and extract it somewhere. Otherwise, copy the files you’ve been working on so far to a new folder, as usual.

Open the FLA file, and let’s get started.

Things are different in CS4! If you run into trouble preloading your game with any version of Flash, I recommend you read this comprehensive tutorial on Activetuts+. It’s great, and it covers everything.

Why Bother With a Preloader?

Before we take the time to code a preloader, let’s look at what happens if we don’t have one. Now, as I said, my SWF is currently 10KB, a size so small that my connection can download it in under 40 milliseconds. Yours is probably similar, so how can we run any sort of test without cramming in a bunch of huge bitmaps or mp3s or whatever to artificially pad out the size?

Well, fortunately, the standalone Flash player has a way of simulating different download speeds. With your FLA file open, test your game in the usual way (Control > Test Movie), and in the Flash player window that pops up, select View > Download Settings > 14.4 (1.2 KB/s):

screenshot

Now, click View > Simulate Download:

screenshot

The stage will be grey (or whatever colour you’ve set the document’s background to be) for about eight seconds, and then the usual menu screen will appear. So that’s what it’ll look like to anyone browsing the web with a modem from 1992.

Obviously, this isn’t very user-friendly. The user has no idea how long they’re going to have to wait to play, or even if the game is loading at all. There’s also a possibility that the MenuScreen (and thus the Start button) will load before some of the rest of the game (like the background music we’re going to add in Part 9), so the user could begin playing before the game’s even ready, ending up playing in silence or without some of the images appearing. Not good.

A preloader, then, has two main functions:

  1. Stop the user from playing the game before it has completely downloaded
  2. Let the user know that the game is downloading

There is a third, optional, function:

  1. Entertain the user, keeping their attention while they wait

Let’s start with Number One.

Wait For It…

Actually, we’ve already solved #1, in a way. Right-click any of the symbols in the Library and view its Properties:

screenshot

See that box marked “Export in first frame”? It’s checked by default. Flash won’t run any AS3 code until all of the symbols marked “export in first frame” have been downloaded — and since the MenuScreen is added to the stage using code, rather than being dragged there manually by us, it won’t appear until everything has loaded. Great! Well… sort of.

The problem is, this means we can’t run any other code until everything has loaded, which means we can’t write any text to the screen or display a cute animation or anything; we’re stuck with that grey rectangle. Dang.

What we need to do instead is gain control of the code as soon as possible, before all the assets have loaded, and simply wait until everything is ready before we display the MenuScreen. Ideally, we’ll have some sort of “Loading” symbol that is downloaded before everything else which can be displayed from the start.

Unfortunately, this is quite a tedious process. Get ready to be irritated!

Who’s On First?

Like I said, Flash won’t run any code until everything marked “export in first frame” has been downloaded. So, the first thing we need to do is go through every single symbol in the library, open its properties, and uncheck that box, if it’s enabled. Ugh. Sorry. (If anyone knows of an Extension that does this for you, I’d be most grateful to hear of it.)

EDIT: Bert Neyens let me know that, if you’re using Flash CS4, you can hold SHIFT or CTRL (or Command on a Mac, I guess) while clicking items in the library to select several at once. Then if you right click any one of them and select Properties, you can uncheck “export in first frame” and it will apply to all of them. Sadly this doesn’t work in Flash CS3, but this is a real time-saver for anyone running a later version. Thanks Bert :)

As you go through, you may find this error message pops up:

screenshot

That’s my fault (oops). It’s because I told you to put “Counter” as the base class for some of the symbols, which is incorrect. Change it to flash.display.MovieClip and it’ll be fine.

Some of the symbols won’t allow you to click the box, because we won’t have selected “Export for ActionScript”. In that case, don’t worry about it and move on.

Once you’ve gone through all that, try running the game. You’ll get one or more errors saying:

Error 1120: Access of undefined property [something]

What’s happening here is that Flash is being a little too clever for its own good. You see, if you have something in the library but not on the stage, Flash assumes you don’t need it, and doesn’t include it in the SWF when it makes it (though it does include all the AS files). So in the MenuScreen, for example, Flash has all the code regarding startButton, but because the MenuScreen symbol itself is not included in the SWF, and because that’s the only place we tell Flash that startButton is actually a button, Flash gets all confused and says it doesn’t know what startButton is.

“Export in first frame” tells Flash to treat the symbol as an object that is on the stage in the first frame of the movie. Now that we’ve unchecked it, the objects aren’t getting built in to the SWF. To fix this, we’re going to have to bend the rules I set out way back at the start of Part 1.

The Three Frame Technique

To summarise: we need all of the library objects on the stage, but we can’t have them in the first frame because Flash won’t run any code until they’re all loaded if we do that. Obvious solution? Put them in the second frame!

Just like we did with the buttons in Part 4, and the Clock in Part 5, we need to add a new keyframe to the timeline. This time, however, it’s the timeline of the stage itself we’re dealing with.

In your FLA, make sure you’re not looking at any symbol in particular — there should only be the blank grey rectangle of the stage on the screen. Now, right-click the second frame of the timeline and choose Insert keyframe:

screenshot

This frame is going to hold all of our symbols (and, later, sounds). Since Flash only waits until it’s loaded everything on the first frame before running any code, putting everything on the second frame will let us include all of the assets in the SWF and gain control of the code before everything is done downloading.

We could just drag everything from the library into this frame, but this causes a little problem when it comes to sound files (I’ll go over this when we add music) and is generally messy. Instead, I’m going to introduce a technique I learned from this excellent tutorial by Jeff Fulton of 8bitrocket. (Thanks Jeff!)

It’s simple, really. First, create a new symbol (Insert > New symbol), of type movie clip, called AssetHolder. Don’t bother exporting this for ActionScript, we’ll never reference it in code. Now, edit this AssetHolder (double-click it in the library if it doesn’t open automatically) and just drag everything from the library into this second frame — everything except AssetHolder itself, that is! You can do this quickly by clicking the top item in the library, holding down shift while clicking the bottom item, then dragging the entire list over.

screenshot

Yikes, what a mess. Get back to the main stage by clicking the Scene 1 button. Make sure you’re looking at the second frame, and drag AssetHolder from the library onto the stage.

screenshot

We might as well place it outside of the visible area (dark grey rectangle) to ensure it doesn’t get seen.

If you save the game and run it now, you’ll get the following error message, repeated about a million times:

ArgumentError: Error #1063: Argument count mismatch on Enemy(). Expected 2, got 0.
    at flash.display::Sprite/constructChildren()
    at flash.display::Sprite()
    at flash.display::MovieClip()

What? Flash is playing frame 1, then frame 2, then 1, then 2, over and over again in a loop. Each time it gets to frame 2, it tries to create an Enemy, because there is an Enemy symbol inside the AssetHolder which is on frame 2. But Enemy objects require two parameters to let them know where to start, and Flash doesn’t know to provide these! Thus, we get this error.

Solving it is easy. We just stop Flash from looping through frames 1 and 2. Sadly we have to break another of the rules from Part 1.

Right-click the first frame of the main timeline and select Actions.

screenshot

The Actions Panel appears. This lets you write code that is run when a specific frame is reached. A lot of AS2 games were written by coding entirely within the Actions panel (in AS2, symbols have their own Actions Panel, kind of like how in AS3 they can have their own class file). We just want Flash to stop at this frame and not go onto frame 2. The code for this is ridiculously simple:

screenshot

Close the Actions Panel, save the game, and try to run it. We get an error message, but it’s a good sign!

TypeError: Error #1009: Cannot access a property or method of a null object reference.
    at MenuScreen()
    at DocumentClass()

Open up DocumentClass.as (can you believe we haven’t written anything in the class files so far?) and the cause is obvious — just take a look at the constructor:

?View Code ACTIONSCRIPT3
13
14
15
16
17
18
19
20
public function DocumentClass() 
{
	menuScreen = new MenuScreen();
	menuScreen.addEventListener( NavigationEvent.START, onRequestStart );
	menuScreen.x = 0;
	menuScreen.y = 0;
	addChild( menuScreen );
}

The very first line creates a new MenuScreen, and the error is regarding the MenuScreen. It’s no coincidence. This shows us that Flash is running the code before having loaded everything, which is exactly what we wanted. Let’s get rid of that error by moving that MenuScreen-related code out of the constructor:

?View Code ACTIONSCRIPT3
13
14
15
16
17
18
19
20
21
22
23
24
25
public function DocumentClass() 
{
 
}
 
public function showMenuScreen():void
{
	menuScreen = new MenuScreen();
	menuScreen.addEventListener( NavigationEvent.START, onRequestStart );
	menuScreen.x = 0;
	menuScreen.y = 0;
	addChild( menuScreen );			
}

If you save it and run it now, you’ll get no error messages! Sadly, you’ll get no game either. We should probably fix that.

Are We There Yet?

At the most basic level, we just need the preloader to detect when the SWF has completely finished downloading, and then display the MenuScreen. Guess what? Time for another event listener!

?View Code ACTIONSCRIPT3
13
14
15
16
public function DocumentClass() 
{
	loaderInfo.addEventListener( Event.COMPLETE, onCompletelyDownloaded );
}
  • loaderInfo is a built-in object that holds information about, well, how much has loaded.
  • Event.COMPLETE is dispatched by loaderInfo when the entire SWF has downloaded.

Even though this is such an important event that it’s part of the base Event class, rather than DownloadClass or whatever, we still have to import it:

?View Code ACTIONSCRIPT3
6
7
import flash.display.MovieClip;
import flash.events.Event;

And of course we need to write an event handler:

?View Code ACTIONSCRIPT3
19
20
21
22
public function onCompletelyDownloaded( event:Event ):void
{
	showMenuScreen();
}

I’ve gone ahead and made it run the MenuScreen code that was originally in the constructor, here.

Logically, this all makes sense, right? It should work now. It doesn’t, of course. There’s one more hoop we have to jump through.

See, even though all the library assets are in the SWF, Flash can’t access them until it reaches the frame of the movie that they’re on, i.e. frame 2. (Just– just go with it, OK? We’re all in this together.) Before we can use anything, then, we have to get to frame 2. But we already saw what happens when we try to run frame 2; we get an error because of the Enemy’s constructor function. This means, then, that we need to add a third frame where the actual gameplay can take place.

Back in the FLA, right click frame 3 in the timeline and Insert Blank Keyframe.

(Make sure it’s a blank keyframe!)

In DocumentClass.as again, alter your onCompletelyDownloaded() function:

?View Code ACTIONSCRIPT3
19
20
21
22
23
public function onCompletelyDownloaded( event:Event ):void
{
	gotoAndStop(3);
	showMenuScreen();
}

gotoAndStop(3) makes the Flash move directly to frame 3 without passing through frame 2 (or collecting £200).

Save it, cross your fingers, hold your breath, and run it…

screenshot

Ahhhhh. Congratulations, that’s one of the most irritating things in Flash game development and you’ve done it. Try simulating the download again — you’ll get the grey screen for a few seconds and then the MenuScreen will suddenly appear, just as when we tried it at the start, 2,000 words ago. This time, however, we have control of the code.

Showing Progress

This is all well and good, but what about the second function of a preloader, “Let the user know that the game is downloading”? Don’t worry, that’s much easier. The loaderInfo object contains two important properties:

  • bytesLoaded, the number of bytes of the SWF that have been downloaded so far.
  • bytesTotal, the total size of the entire SWF, in bytes.

It also dispatches another event: a ProgressEvent of type ProgressEvent.PROGRESS, which fires off every time a little bit more of the SWF is downloaded. Naturally we can use these in combination.

Add another event listener to the constructor of your document class:

?View Code ACTIONSCRIPT3
14
15
16
17
18
public function DocumentClass() 
{
	loaderInfo.addEventListener( Event.COMPLETE, onCompletelyDownloaded );
	loaderInfo.addEventListener( ProgressEvent.PROGRESS, onProgressMade );
}

Import ProgressEvent:

?View Code ACTIONSCRIPT3
6
7
8
import flash.display.MovieClip;
import flash.events.Event;
import flash.events.ProgressEvent;

And create an event handler:

?View Code ACTIONSCRIPT3
27
28
29
30
public function onProgressMade( progressEvent:ProgressEvent ):void
{
 
}

In Part 6 I introduced you to comments. Now I’m going to introduce another important tool for development: the trace() function. This is used for looking at data inside the SWF while it’s running; anything inside the brackets of trace() will be output to a window called, appropriately, the Output Window (make sure Window > Output is checked if you can’t see it).

Let’s try this out. Add this line to your new event handler:

?View Code ACTIONSCRIPT3
27
28
29
30
public function onProgressMade( progressEvent:ProgressEvent ):void
{
	trace( loaderInfo.bytesLoaded, loaderInfo.bytesTotal );
}

As you can see, trace() accepts multiple parameters. If you save and run the game, and simulate a download, you’ll see the Output window slowly fill up with numbers:

screenshot

As you can tell from the code, the first number is how many bytes have “downloaded”, and the second is the size of the SWF. When the two numbers match, loaderInfo fires off the COMPLETE event, and the MenuScreen appears.

We can show the percentage loaded with a little arithmetic:

?View Code ACTIONSCRIPT3
27
28
29
30
public function onProgressMade( progressEvent:ProgressEvent ):void
{
	trace( Math.floor( 100 * loaderInfo.bytesLoaded / loaderInfo.bytesTotal ) );
}

Dividing the one by the other gives us a fraction, multiplying this by 100 gives us a percentage, and Math.floor() removes everything after the decimal point.

All we need to do now is display this information to the user. Ah, if only we had a class designed for taking numerical data and displaying it in a graphical way. Oh wait! That’d be the Counter class we made back in Part 5.

Now I already explained back then how to make a symbol based on the Counter class, and I’m not going to repeat myself here. It doesn’t matter what you want your preloader to look like — a spinning thing, a progress bar, a simple piece of text saying “loading…”, whatever — just make it simple, because it has to download quickly. Personally I’m just going to go with this:

screenshot

That’s a movie clip called LoadingProgress, exported for ActionScript, and also exported in the first frame. (It needs to be exported in the first frame because it has to load before the code that’ll update it is run.) The dynamic text field holding the number has an instance name of percentDisplay.

It needs a class file, so create one called LoadingProgress.as and save it in the Classes folder. Here’s the code to go in it:

?View Code ACTIONSCRIPT3
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package
{
	import flash.text.TextField;
	public class LoadingProgress extends Counter
	{
		public function LoadingProgress()
		{
			super();
		}
 
		override public function updateDisplay():void
		{
			super.updateDisplay();
			percentDisplay.text = currentValue.toString();
		}
	}
}

This is almost identical to the class for the Score. Alter it to match your own loading display (see Part 5 for more help).

There is one difference I’d like to make. Counter and LoadingProgress only allow their internal values to be updated through the addToValue() function. This is inconvenient, since we don’t know how much to add at any given point, only what the value should be. Let’s create a new function for setting that:

?View Code ACTIONSCRIPT3
19
20
21
22
23
public function setValue( amount:Number ):void
{
	currentValue = amount;
	updateDisplay();
}

You could add this function to LoadingProgress, but I’m actually going to add it to Counter, since we might need to use it in something else later. Of course, LoadingProgress will gain the use of this function, since it extends Counter.

Nearly there! Head back to the document class and set up the loadingProgress object:

?View Code ACTIONSCRIPT3
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
	public class DocumentClass extends MovieClip 
	{
		public var menuScreen:MenuScreen;
		public var playScreen:AvoiderGame;
		public var gameOverScreen:GameOverScreen;
		public var loadingProgress:LoadingProgress;
 
		public function DocumentClass() 
		{
			loadingProgress = new LoadingProgress();
			loadingProgress.x = 200;
			loadingProgress.y = 150;
			addChild( loadingProgress );
			loaderInfo.addEventListener( Event.COMPLETE, onCompletelyDownloaded );
			loaderInfo.addEventListener( ProgressEvent.PROGRESS, onProgressMade );
		}

Note that we’ve put it in the constructor function. This is fine! Don’t worry. It’ll work, because we’ve exported it in the first frame — meaning it’ll load before the code referring to it is run.

If you save it, run it, and simulate a slow download, you’ll see it:

screenshot

It’s stuck at zero, of course, because we haven’t written any code to update it. Naturally that goes in the onProgressMade() function. I’m going to replace the trace() statement with it:

?View Code ACTIONSCRIPT3
32
33
34
35
public function onProgressMade( progressEvent:ProgressEvent ):void
{
	loadingProgress.setValue( Math.floor( 100 * loaderInfo.bytesLoaded / loaderInfo.bytesTotal ) );
}

Save it, run it, and simulate another download:

screenshot

Awesome!

Wrapping Up

There’s one more thing we need to make sure gets included in the SWF: fonts. For static text, there’s no problem; the font is automatically included. But for dynamic text, this isn’t the case; if the player does not have the font installed on his own PC, he’ll just see one of his computer’s default fonts, like Times New Roman.

Fortunately, it’s very simple to embed these fonts into the SWF. Just select the dynamic text field in question, click the Embed… button in the Properties panel, and select all of the characters you’re going to need. Don’t select All characters — I did this once, and it added 10MB to the size of my SWF! Just select the essentials — uppercase and lowercase letters, numerals, punctuation, and basic Latin are usually enough. Oh, and if you use the same font for several different dynamic text fields, you only need to embed it for one of them.

By the way, you might find that your progress meter starts at some high number (mine starts at 60%!). This is because we’re dealing with such a small file that a large proportion of the SWF is taken up by code and the preloader itself. As we add sounds and images, this problem will go away.

Just to be clear, from now on when you add anything new to the library, you shouldn’t export it in frame one (unless it’s part of the preloader), and you should add it to the AssetHolder object. Otherwise the game won’t load properly.

If you’re looking for a challenge this week, try doing something related to the third function of a preloader, “Entertain the user, keeping their attention while they wait”. What can you do without using so much code and graphics that the preloader takes ages to load? If you’re looking for inspiration, try the 25-Line ActionScript Contest, TweetCoding, and the 4k Competition ;)

Big thanks to Jeff Fulton for letting me borrow his work on preloaders in AS3 & CS3. His blog post is the best I’ve ever come across on the subject, so check it out if you want more detailed information. Heck, check his blog out regardless, it’s always good :)

As always, you can download a zip with all the files relating to this part of the tutorial here.

Next week we’ll add music and sound effects (partly to justify the work of writing a preloader). If you’ve got any music of your own you want to use, now’s the time to find it :)

{ 182 comments… read them below or add one }

default0[LoggedOut] December 7, 2009 at 4:56 pm

Im rusty in german, too, even though its my mother tongue ^.^
Maybe I could try to google this behaviour of flash, just have no idea what to type in the search engine…

Best regards

Craig Lynch December 7, 2009 at 8:45 pm

Hey, great tutorial, as always!

I’m having a problem though… first, I should say that although the game I am working with IS an avoider game, I am working with an artist, and a LOT of things differ quite substantially from this tutorial. So I tried to just follow the guidelines for making the preloader.

It works, and does what I generally need it to… but the preloader doesn’t show up until the game is 32% loaded already. It’s a fairly large game because of the graphics and music (about 8 mb). I have made sure that nothing is exported in the first frame, but I am wondering if the artwork(GIF), or the movieclips (set to be synchronized with timeline) load up before or at the same time as the first frame? Are there any settings that I might need to check to get the preloader to load by itself, and before everything else?

Michael Williams December 8, 2009 at 3:20 pm

@default0: Could you make a reeeal simple project that just has maybe a couple of classes and the FLA to demonstrate this behaviour? Still not sure I understand it, and I’m curious. I’ll take a look if you’ll do that :)

@Craig: Thanks!

Good question. It’s difficult to say from here, but one thing you can do to investigate this is to use a size report.

Click File > Publish Settings, tick Flash (you can untick the others), and go to the Flash tab. Now, tick Generate size report and click Publish.

In the Output panel you’ll see a summary of everything in your game, and the size of each frame. (It’s a good idea to copy and paste this into Notepad or something, just to make it easier to read.) Unfortunately this does not tell you exactly which assets are on which frames, but it can help you get a good idea.

There’s more info on the size report here.

Hope that helps :)

default0[LoggedOut] December 8, 2009 at 4:28 pm

About the reeeeeeeeal simple project, I try to limit it on 300 lines in total, lets see what I can do with that, gotta get a small challenge beneath all the AS trouble.

Guess this will be some fun :)

Best regards

Woohoo, its Bruce December 13, 2009 at 6:32 am

hey Michael, In my game I made my avatar do a jumping animation when you hit the spacebar. It worked, and I am happy with it, except for one thing; you are able to restart the jump in mid-jump. How can I set the jump to only occur if the avatar is in its walking animation? Its walking animation is frames 1-12 (with a repeat), and the jump is frames 13-48 (its 36fps).

To get the jump, I tell the avatar to gotoAndPlay at frame 13, how can I tell the code to NOT do this if the frame number is more than 12?

If you have a better way to make it work, let me know!

Bruce, creator of all things odd. ( well, not ALL, but most. )

Michael Williams December 20, 2009 at 4:04 am

@default0: Cool, how’s that going?

@Bruce: I posted a couple of tutorials on animations starting here that you might be interested in — though neither of them answer your question directly.

You should be able to write:

if ( avatar.currentFrame <= 12 )
{
    avatar.gotoAndPlay( 13 );
}
else
{
    //don't do anything
}

…and put that inside the code that’s run when the player hits space.

How’s your game coming along?

default0[LoggedOut] December 20, 2009 at 8:18 pm

Ugh, about that…

Darn, I finally have that many projects running that I dont even find the time to do something that simple (got a Jumpn-Run and BaseInvaders [For more info, you can ask me] in addition to the other 8 projects T_T)…

Im really sorry, but thats how it is.
I didnt wrote a single line till now.
But what I did, was to check that youre actually right.
I checked your suggestion and proofed it.

Once somethin is added to the stage, it HAS a parent, but that wont save you the trouble if you want to do something in the constructor-function.
Though, in most cases you can simply declare an event listener that listens if its been added and put the code thats used to be executed once on creation there, but I dont like that way + Im far too lazy to always do this.
In addition to this, if you use layers, like I do, you still cannot access the document class, since “parent.parent” wont work (yes, I tried it).
using

public class MyClass extends DocumentClass

Wont work either for some reason I couldnt figure… (and usually Im pretty good at this, f.e. I figured flashs coordinate system by myself and THEN read your tutorial and found my thoughts in it lol).

Oh well, thats been enough of typing, gotta go back to my projects.

Best regards, default

Michael Williams December 20, 2009 at 8:56 pm

Hey default0,

Oh, sorry! I didn’t mean to pile on to your workload :) I was just interested. Thanks for checking it out.

Hey, I’m working on a jump-and-run platform at the mo. What’s BaseInvaders? Something like Space Invaders?

Aha, I see what you mean now. Yeah, it won’t have a parent until the Event.ADDED_TO_STAGE is triggered.

What you could do, is create a new class like this:

package
{
    import flash.display.MovieClip;
    import flash.events.Event;
    public class ParentableMC extends MovieClip
    {
        public function ParentableMC()
        {
             addEventListener( Event.ADDED_TO_STAGE, onAddToStage );
        }

    public function onAddToStage( evt:Event ):void
    {
         gotParent();
    }

    public function gotParent():void
    {
        //nothing here; "abstract" class
    }
}

}

Now, you can create new classes like this:

package
{
    public class MenuScreen extends ParentableMC
    {
        public function MenuScreen()
        {
            //leave this blank
        }

    override public function gotParent():void
    {
        //this will be run when the object gets a parent
        //so, you can put all your constructor code HERE instead
        //and you will be able to access parent!
    }
}

}

How’s that?

default0[LoggedOut] December 20, 2009 at 11:31 pm

Hi,

Oh well, I (probably) wont use it for this, but I think that this little hint here with the abstract stuff might become REALLY useful in da feature (it is like “virtual” in C++, huh?) :)

And about BaseInvaders (Short: BI), this one will become really cool.
It is a multiplayer game using the Nonoba Multiplayer API (just like SunBattle, another one of my millions of projects >.>).
One Player has a base to defend.
He has subordinates, can place traps and he has a map of the whole base informing him/her about the progress of the “attackers”.
The “defender” (the base controlling player) can move his minions (or subordinates), recruit new ones, activate traps and use special abilities in order to stop those “attackers”.
The “attackers” are the ones that try to invade the “defenders” base.
They must find the room in which the “defender” hides.
Once they find this room, they won, so the “defender” should take care that they wont do this!

I guess this will be pretty fun, you can decide if you either want to invade others bases, or if you’d like to defend your own.

I think this will be pretty extensive and with that eat up a lot of time, but its some damn fun to work on this :)

Best regards, default

Michael Williams December 23, 2009 at 3:09 am

Like “virtual” — yeah, that’s right!

BaseInvaders sounds like an awesome idea. How far along is it? I’ll bet that is a fun project :)

default0[LoggedOut] December 23, 2009 at 1:14 pm

Yeah its always like this for me:

I get a game (idea) – then work on it. Then jump to another game for a while, so I cannot say “stay tuned” as it will take a probably huge while till I can release it :/

Best regards

Michael Williams December 24, 2009 at 2:56 pm

I know what you mean. I’d recommend getting something finished, though, even if that means not completing it to the extent you’d planned. Finishing is itself a skill. And you can always make a sequel ;)

default0[LoggedOut] December 24, 2009 at 5:26 pm

I hate sequels…

Oh well, and for any game Im doing so far, they all have (to be honest) very bad graphics.
I wanna change that before I can say that any of them is “finished”.
I do what I want and thats it for me =D

Best regards

Michael Williams December 29, 2009 at 12:33 am

Fair enough :)

Alex December 29, 2009 at 7:06 pm

Hi Michael! Thanks for your amazing game tutorial. Your blog is a goldmine for all AS3 beginners. Very useful.

Michael Williams January 1, 2010 at 6:51 pm

Wow, thanks Alex :)

Cool site intro — when’s it opening?

kustrle January 14, 2010 at 4:22 pm

Thank you so much. I couldn’t belive I handled it out :D I always taught it’s hard to make a prealoader xD Just dreamed about it…

Michael Williams January 14, 2010 at 8:12 pm

Cheers kustrle :)

Savitri February 11, 2010 at 8:14 pm

Hi,
Your example is simply superb.. I learnt so many concepts from this game.
Well everything went good till now, my preloader is working too, but the problem is my preloader is also taking a few seconds to laod.. so practically i have a blank screen for few seconds.. can you help me what would have went wrong.

Thanks,
Savitri..

Michael Williams February 13, 2010 at 2:29 am

Thanks Savitri!

It’s possible that your game is just very small, with most of the space taken up by code and the preloader graphics. In this case, much of the preload time would be spent loading this stuff. Does that sound likely?

ST February 14, 2010 at 6:22 pm

I have difficulties understanding the trick of “gotoAndStop(3);”

If we need to get to frame 2 in order to use classes in that frame, why not simply use

gotoAndStop(2);
instead of
gotoAndStop(3); ???

thank you,

Michael Williams February 17, 2010 at 11:20 am

Good question, ST. It’s because there are a lot of objects on the second frame (inside the asset holder). If we move to the second frame, all these objects will be created, which is a problem because it means the sounds will play and the enemies will give off errors because you haven’t passed any parameters to them and stuff like that.

Frame 3 is blank; nothing there to cause such problems. But because we have to move past frame 2 to get to frame 3, all the assets on frame 2 will be loaded, ready for us to use.

Epic428 March 3, 2010 at 5:40 pm

Hey just wanted to say that In Flash CS4 I was getting an error after i added the 3rd frame and gotoAndStop(3); code. It was an enemy argument error similar to the first one we got. i realized that Flash CS4 will duplicate the keyframe that is currently selected when inserting a new one. therefore it was necessary to delete the symbol on the 3rd frame to resolve the issue. In case anyone else has a similar issue check for this.

.-= Epic428´s last blog: School Gone Too Far – Spies on Students Through Webcams =-.

Michael Williams March 20, 2010 at 11:15 am

Good call, Epic428, thanks for posting.

Mike May 12, 2010 at 7:42 pm

Hi michael, I’m at the part where we use trace to see how many bytes have loaded in the output window after clicking simulate download, and, not only is trace not outputting anything, but I keep getting this error:

loaderInfo.addEventListener( ProgressEvent.PROGRESS, onProgressMade );

Any help you can give would be greatly appreciated,
Thanks very much : )

Mike May 12, 2010 at 7:44 pm

Oops…my mistake the error is:

1120: Access of undefined property onProgressMade.

Mike May 13, 2010 at 10:51 pm

I wonder if it has anything to do with the fact that I’m using Flash CS4, you know, with that whole “Export Class on Frame 2″ thing”?

Michael Williams May 16, 2010 at 1:50 pm

Hey Mike,

Actually, what that error means is, Flash can’t find a function called onProgressMade() in your AS file. Is it definitely there?

Mike May 17, 2010 at 4:17 pm

Yeesh…must’ve looked at the screen too long, either that or need to get the old eyes checked…spelled onProgressMade wrong. I had spelled it “onProgessMade”.

Thanks again Michael!

Mike May 27, 2010 at 11:47 pm

Michael,

hello me again. Just wondered if [b].setValue[/b] was an actionscript event or is that a function you set somewhere in the tutorial? I cant see where you reference it?

Thanks Michael.
-Mike.

Mike May 27, 2010 at 11:49 pm

Well, I see that the BBCode didnt work! Haha [b].setValue[/b] : P

Michael Williams May 29, 2010 at 12:19 am

Ahh, spelling mistakes: the most annoying cause of bugs. In Part 12 you’ll learn how to set the game up for FlashDevelop, which will help find those kind of bugs for you.

setValue() is added in the “Showing Progress” section, after this paragraph:

There is one difference I’d like to make. Counter and LoadingProgress only allow their internal values to be updated through the addToValue() function. This is inconvenient, since we don’t know how much to add at any given point, only what the value should be. Let’s create a new function for setting that:

Brandon June 6, 2010 at 9:34 am

First off I would like to say, I really like your tutorials (I have learned lots).

Anyway, the problem I have is that when I go to simulate download it takes quite a while to start. After some research I found out it was due to the document class having to load so much data before it goes to the preloader. By the way my project is more complex then yours, but has the same document class. When I go to generate size report i see that frame 1 has 31863 bytes and frame 2 (which has all my class symbols and each exported class’s export to frame one is checked off) is at 23553 bytes.

From my understanding anything that is in the document class including all symbols, classes, functions, and variables that are linked to it must be loaded first before any code in the document class can execute (basically defeating the purpose of the preloader).

I went ahead and downloaded your final project and checked your size report and the result was frame 1 with 24183 bytes and frame 2 with 6841 bytes resulting in the loader displaying at around 80% before its seen.

Sorry if this post is a little long, and thank you for your time.

Zalytunz June 6, 2010 at 7:30 pm

Using CS5…
I’ve tried using this tutorial for a preloader, doing everything you say, even downloading your files, comparing and fixing like that, doesn’t help. So I turned to the CS4 link, didn’t work either. Googled for ages, looking for a CS5 tutorial, couldn’t find any.
- Any clues to where I can find a CS5 tutorial or just something that works with CS5?

Zalytunz June 7, 2010 at 3:25 pm

So I asked on Adobe Forums, after some tracing a guy told me:
“you have code in frame 2 (or beyond) that’s directing your timeline back to frame 1.”

We haven’t made code that does that, have we?

Epic428 June 7, 2010 at 4:42 pm

CS5 Should not matter. I have it and there aren’t any differences that I can see between CS4 and CS5 that would make your preloader not work, Besides AS3 Is the biggest contributor to the preloader as that is the language being used. Anyway, it would be best for you to provide relevant code, and errors/problems occurring when trying to run the game. With that information we can provide you with a more accurate answer as to the problem you are having and how to fix it. :)

.-= Epic428´s last blog ..Simple Windows Keyboard Shortcuts =-.

Zalytunz June 7, 2010 at 5:06 pm

When I simulate download a white screen can be seen shortly (at very load speed), followed by a grey screen with 5 dots, going from 1-5 then restarting. After a while here, it goes right to the game’s menuscreen.

stop();

trace(this.currentFrame,this);

import flash.events.ProgressEvent;
import flash.events.Event;

this.loaderInfo.addEventListener(ProgressEvent.PROGRESS, onLoading);
this.loaderInfo.addEventListener(Event.COMPLETE, onComplete);

function onLoading(evt:ProgressEvent):void {
var loaded:Number = evt.bytesLoaded / evt.bytesTotal;
loadbarText.text = "LOADING: " + (loaded*100).toFixed(0) + "%";

trace(loadbarText.text);
};

function onComplete(event:Event):void {
this.loaderInfo.removeEventListener(ProgressEvent.PROGRESS, onLoading);
this.loaderInfo.removeEventListener(Event.COMPLETE, onComplete);
loadbarText.visible = false;
gotoAndPlay(2);
trace(loadbarText)
};

That is the code inside the first frame.
trace(this.currentFrame,this); returns:
1 [object DocumentClass]
1 [object DocumentClass]

trace(loadbarText.text); doesn’t return anything.

trace(loadbarText) returns:
null

Zalytunz June 7, 2010 at 5:22 pm

Uhm..
(at very LOW speed)*
Didn’t make any sense before, an edit function would be good ;P

Michael Williams June 12, 2010 at 1:51 pm

@Brandon: Thanks :)

Yeah, I think I screwed the preloader up on this. I’ve given up trying to fix it by now, and I recommend checking out this excellent tutorial over at Activetuts+.

(I don’t usually use Flash Pro to make preloaders any more; instead, I use FlashDevelop, and its premade preloader template.)

@Zalytunz: As far as I’m aware there shouldn’t be a difference between CS4 and CS5 that would affect this (like Epic428 said). I can’t think of any code that directs the timeline back to frame 1, but.. maybe? Again, I recommend the tutorial I mentioned to Brandon.

My edit function broke :(

Oh wait.. you’re right, CS5 does do something different. It has those animated dots. And I have yet to figure out what they mean :S

Looking at your code, shouldn’t that be gotoAndPlay(3), to get past the frame with the AssetHolder? Also, are all your objects (other than the preloader itself) set to export in frame 2?

Zalytunz June 16, 2010 at 7:54 pm

Sad about the edit functino :(
I’ve followed that tutorial, but I still get that error that’s caused by something directing the timeline back to frame 1.

Forgot about the AssetHolder, but I get the exact same errors when I fixed that and the gotoAndPlay(3).. Sent you a mail though, check it! :D

Michael Williams June 22, 2010 at 3:29 pm

Hey Zalytunz,

Not sure what this is. I’ll check my mail…

Mike June 25, 2010 at 6:33 pm

I got mine to work in CS4. With these settings:

  • Publish Settings set to Export classes in frame 1
  • LoadingProgress MovieClip Export in Frame 1 unchecked
  • LoadingProgress MovieClip with no Base Class
  • Actually, none of the Avatar, Enemy, Score, etc. MovieClips have a base class
  • All of the Avatar, Enemy, Score, etc. MovieClips have Export in frame 1 unchecked
  • LoadingProgress MovieClip has a dynamic text box w/instance name:percentDisplay

@Zalytunz: Try not using the “this” method

Tx, Mike

joel June 29, 2010 at 7:53 pm

Great tutorial. One thing though. You should really call attention to your step “Insert Blank Keyframe”. I missed the “blank” part and it took a while to figure out why I was getting some weird results.

Thanks!

Michael Williams July 5, 2010 at 7:25 pm

@Mike: Cheers for the tips!

@joel: Thanks for the tip, too! I’ve made it more obvious that you should use a blank keyframe.

Colin July 12, 2010 at 7:47 pm

Im using flash CS5 and this pre loading stuff isn’t working for me. The trace( loaderInfo.bytesLoaded, loaderInfo.bytesTotal ); doesn’t send output. so now ive done exactly what you said and the game is seemingly exactly the same as it was in the beggining. ?

Michael Williams July 23, 2010 at 11:38 am

@Colin: Sorry, I’ve essentially given up messing about with CS5 preloaders. There seem to be a lot of problems with it and I don’t know why. Have you tried the Comprehensive Guide?

Michael Williams July 23, 2010 at 11:59 am

Hey all, Zach Zurn of TechAssist sent in this comment, which my overprotective spam system is keeping out. I think it’ll be helpful. Thanks, Zach!

=====

I was having a problem with the preloader only starting at 50%. It makes sense that the preloader would start at 50%, because the file is so small that 50% of it is downloaded by the time the basic files are downloaded.

At this point it’s a presentation issue, we want the preloader to properly display the percentage of loading left to go. I handled this by having 2 additional variables and some if statements.

The Variables are these:

private var loadedFirst:Boolean;
private var loadedFirstNum:Number;

I initialize those in the constructor function:

loadedFirst = false;
loadedFirstNum = 0;

And then in the onProgressMade looks like this:

public function onProgressMade (progressEvent:ProgressEvent):void
               {
                       if (loaderInfo.bytesLoaded == loaderInfo.bytesTotal) //If the first progress event is, set the progress to 100%
                       {
                               loadingProgress.setValue(100);
                       }
                       else if (loadedFirst == true) //Otherwise check if the loadedFirst variable has been set and use that to show a correct percentage
                       {
                               loadingProgress.setValue(Math.floor( 100 * (loaderInfo.bytesLoaded - loadedFirstNum) / (loaderInfo.bytesTotal - loadedFirstNum)));
                       }
                       else //If this is the first progress event, set the prebytes so we can take those out of the equation
                       {
                               loadedFirstNum = loaderInfo.bytesLoaded;

                           trace("Set Prebytes: " + loadedFirstNum);
                           trace("Total Bytes: " + loaderInfo.bytesTotal);

                       loadedFirst = true;
                       loadingProgress.setValue(Math.floor( 100 * (loaderInfo.bytesLoaded - loadedFirstNum) / (loaderInfo.bytesTotal - loadedFirstNum)));
               }
       }

I hope this helps, I was kind of stumped for a bit on how to fix this.

Kevin Neal September 6, 2010 at 10:05 pm

Now all we need is a tutorial on adding a sponsors preloader :) I’m not sure how many people have gotten that far, but its a slightly different ball park. Trying to add an swf preloader, any suggestions?

wp September 10, 2010 at 12:42 am

What is the point of the AssetHolder? Can’t we just drag everything into the 2nd frame if we’re not even using it? I see that in part 9 you do that with the sounds.

Pirill September 11, 2010 at 9:39 am

Hello! I just wanted to say that your preloader instructions worked flawlessly in Flash CS5, so I don’t really see why it would be any different from the other versions of Flash. If need be, I can post my game here, but there’s nothing really different from what you’ve done.

Leave a Comment

Writing code? Write <pre> at the start and </pre> at the end to keep it looking neat.

Anti-Spam Protection by WP-SpamFree

{ 3 trackbacks }

Previous post:

Next post: