AS3 Avoider Game Tutorial, Part 3: Game Over

by Michael James Williams on October 9, 2008 · 223 comments

in Avoider Game Base,Tutorial

(This tutorial is also available in Spanish)

Introduction

In this part of my AS3 conversion of Frozen Haddock‘s avoiding game tutorial, I’ll show you how to add a game over screen. Click the image below to see how the game will play by the end of this post.

screenshot

Now, I already said in the first part of this tutorial that we’d be using just one frame of the timeline. This means that we can’t just stick a sign saying “game over” on frame 2 and then run a nextFrame() command when our character dies, so what can we do?

The answer’s pretty simple: we just slap a big “Game Over” sign on top of everything else when we need it, like pulling a curtain down at the end of a play.

Making an Overlay

Let’s get started. If you’ve been following the earlier parts of the tutorial, make a copy of your game folder and open the FLA in this new copy. Otherwise, download the zip file from Part 2, extract it somewhere, and open AvoiderGame-MJW.fla.

Create a new Movie Clip (Insert > New Symbol) called GameOverText, and draw something that will indicate to the player that their game is indeed over. Here’s mine:

screenshot

That font is Arial Black, and I’ve coloured it a dark red to make it stand out against the grey background. Note that I’ve centred the text around the registration point — see Part 1 for a reminder on how to do this.

If you’re using text, Flash might decide that it should be dynamic — that is, that it can be changed using code. Until we add scores, we don’t need this functionality, so click on your text and in the Properties panel, make sure to change the drop-down list from Dynamic Text or Input Text to Static Text. Otherwise, you’ll get an error:

1046: Type was not found or was not a compile-time constant: TextField.

Next we need to make this symbol available to our code. Find it in the Library, right-click it, and select Properties. In the Linkage panel, check the Export for ActionScript box, make a note of the class name (should be GameOverText) and click OK.

Open your document class file, either by directly opening the AS file in the Classes folder (mine’s called AvoiderGame.as), or by finding the document properties (click on an empty space, and selectWindow > Properties if you can’t see them) and clicking the little pencil icon next to the Document class text box. Find the onTick function, and then the piece of code that determines what happens if an enemy hits the player’s avatar:

?View Code ACTIONSCRIPT3
46
47
48
49
if ( avatar.hitTestObject( enemy ) ) 
{
	gameTimer.stop();
}

So at the minute, this just stops the whole game if the avatar collides with an enemy. Nothing wrong with that, but it looks like the game has just crashed. Let’s make our Game Over text appear as well:

?View Code ACTIONSCRIPT3
46
47
48
49
50
51
52
53
if ( avatar.hitTestObject( enemy ) ) 
{
	gameTimer.stop();
	var gameOverText:GameOverText = new GameOverText();
	gameOverText.x = 200;
	gameOverText.y = 150;
	addChild( gameOverText );
}

This code should be pretty familiar to you after reading Parts 1 and 2. Remember you can change the values 200 and 150 to alter where on the screen the Game Over text will appear.

Save everything and run it (Control > Test Movie) and when you hit an enemy, you should get something like this:

screenshot

Excellent.

Really Rubbing It In

An “overlay” game over notice like this is fine — it worked for Sonic — but what about a whole game over screen, like in Frozen Haddock’s game?

We can start by doing the same thing that we’re doing now, but making the symbol fill the whole game screen. Create another new Movie Clip, this time called GameOverScreen, and draw a big black rectangle, of any size. Click the rectangle, and change its size to match the dimensions of your stage. (You can change the size of the rectangle by altering its W and H — Width and Height — values in its Properties or Info panel, and you can see the dimensions of the stage by clicking Modify > Document.)

This time, we want the registration point of the symbol to be in the top-left corner. Why? Because then we can align it to the stage by setting its location to (0, 0), rather than having to worry about where the centre of the stage is. You can change the registration point by using the Align panel again:

screenshot

Alternatively, you can change the X and Y properties of the rectangle to 0.0, just as you changed the Width and Height.

Let’s add some text:

screenshot

That’ll do. You can pretty it up if you like. When you’re ready, Export GameOverScreen for ActionScript, just as we did with GameOverText.

Open the document class again, and find the code we modified before:

?View Code ACTIONSCRIPT3
46
47
48
49
50
51
52
53
if ( avatar.hitTestObject( enemy ) ) 
{
	gameTimer.stop();
	var gameOverText:GameOverText = new GameOverText();
	gameOverText.x = 200;
	gameOverText.y = 150;
	addChild( gameOverText );
}

It’s pretty simple to make this work with our new screen. Have a go yourself if you like. My code’s here:

?View Code ACTIONSCRIPT3
46
47
48
49
50
51
52
53
if ( avatar.hitTestObject( enemy ) ) 
{
	gameTimer.stop();
	var gameOverScreen:GameOverScreen = new GameOverScreen();
	gameOverScreen.x = 0;
	gameOverScreen.y = 0;
	addChild( gameOverScreen );
}

Note that I changed the x and y coordinates to zero. If you save and run the game and hit an enemy, you’ll see something like the following:

screenshot

But we can go further with this. We can put the actual game inside its own symbol. This way, rather than dropping a curtain down in front of the stage and leaving all the actors standing around behind it, we can have all the actors in their own glass box, and remove this box from the stage when we drop the game over curtain. This makes the stage much less cluttered, and the actors easier to manage. The only question is, have I gone too far with this analogy?

Adding a Game Screen

Let me clarify this a little. At the minute, our game is set out like this:

screenshot

The document class is controlling pretty much everything. If we continue making it do so, then if we want to add a title screen, a menu screen, a few more levels, a character selection screen, and so on, then the document class is going to get very very bloated.

Let’s separate things a little bit. Here’s what I’m proposing:

screenshot

Much neater! The document class duties only consist of making sure the player is seeing the right screen. Each individual screen manages its relevant parts. Later we might break this down even further, but this is absolutely fine for now.

How do we implement this? Well, you probably won’t be surprised if I tell you that we need to make a new Movie Clip — this time, call it PlayScreen.

This new screen is going to do roughly the same thing as our entire game was doing by the end of the last part. That is, it’s going to contain the avatar, and it’s going to generate the enemies and make them move within it. One important difference between using a Movie Clip to contain everything versus using a document (as we were doing before) is that a document has a default background already set up (ours is grey), but a Movie Clip doesn’t — we have to add one ourselves.

Let’s do that now! Edit your PlayScreen Movie Clip and draw a filled rectangle. Just as with GameOverScreen, make this rectangle the same size as the stage, and set its registration point to the top-left corner. I’ve made mine a very light blue, so as to stand out against the editor’s background:

screenshot

We’re not restricted to using a plain background this time. Because I’m so vain, I’ll demonstrate this by sticking my initials all over the place:

screenshot

Alright great. Obviously you don’t have to use my initials. Or any initials at all, for that matter. You could draw a cave, or a black hole, or a chat window (since the game is about smilies! get it?) or whatever.

Now for the code. I already said that this screen is going to do the same thing as our game already was doing, so you can imagine that it’ll require almost exactly the same code. We could rewrite all this code from scratch. We could copy and paste it, renaming bits as required. Or… we could take advantage of our marvellous object-oriented design.

Remember that the entire game, the entire document, is basically a Movie Clip. When we assign it a document class, this is essentially the same as selecting a Movie Clip from the library and assigning it a Class when we “Export it for ActionScript”. So, there’s no reason that we couldn’t assign PlayScreen the same class that has, up till now, been the document class.

Right-click PlayScreen in the library, select Properties, and check Export for ActionScript. This time, instead of accepting the default value, enter the name of your document class. Click OK.

screenshot

Oh, right. First we’ll have to make a new document class, since no two different objects can share the same class. Cancel the Properties box.

A New Class of Document

Hit File > New and select ActionScript File. Enter the (by now familiar) code:

?View Code ACTIONSCRIPT3
1
2
3
4
5
6
7
8
9
10
11
package 
{
	import flash.display.MovieClip;
	public class DocumentClass extends MovieClip 
	{
		public function DocumentClass() 
		{
 
		}
	}
}

Save this in the Classes directory as DocumentClass.as. (There’ll be no confusing the purpose of this file!) Now, back in your FLA, change the document class to DocumentClass.

screenshot

Check everything’s fine by clicking that pencil icon — if it’s all OK, that should bring up the AS file that you just created.

Now you can set the PlayScreen‘s class to AvoiderGame. So do so!

If you save and run the game now, nothing will happen — that’s because the document class isn’t pulling in the PlayScreen. Head back to the DocumentClass AS file and modify it like so (lines 5, 7, and 8):

?View Code ACTIONSCRIPT3
1
2
3
4
5
6
7
8
9
10
11
12
13
14
package 
{
	import flash.display.MovieClip;
	public class DocumentClass extends MovieClip 
	{
		public var playScreen:AvoiderGame;
 
		public function DocumentClass() 
		{
			playScreen = new AvoiderGame();
			addChild( playScreen );
		}
	}
}

This is pretty much exactly the same code as the AvoiderGame AS file uses to create a new Avatar, though here we’re using it to create a whole game. Save it and run:

screenshot

Awesome.

AvoiderGame Once Removed

Actually we’re not quite done yet. Here’s the sketch of my proposed new setup:

screenshot

And here’s our current setup:

screenshot

We’ve got the same problem as before — a bloated class file — only now it’s not the document class. We want the document class to be pulling in the Game Over screen when the player dies. How can we do this?

If we were using AS2, we might use _root or _stage to tell the document to do something. We’re not going to do that.

In previous versions of this tutorial, I let the playScreen run a function in the document class directly. That’s probably the simplest way of handling things, but it gets very messy very quickly. Even with a game as simple as this, I got a few emails letting me know of problems this quick fix had caused. So we’re not going to do that, either.

Back in Part 1, when we were adding the game timer, I said:

An event listener is like a robot that’s constantly checking to see if a particular “event” has occurred, and which runs another function if so.

The line we used for this was:

?View Code ACTIONSCRIPT3
gameTimer.addEventListener( TimerEvent.TIMER, onTick );

(If you’ll recall, that line ran a function called onTick whenever the Timer “ticked”.)

What I’d like to do now is place a similar event listener on playScreen (line 11):

?View Code ACTIONSCRIPT3
8
9
10
11
12
13
public function DocumentClass() 
{
	playScreen = new AvoiderGame();
	playScreen.addEventListener( AvatarEvent.DEAD, onAvatarDeath );
	addChild( playScreen );
}

AvatarEvent.DEAD isn’t a built-in Flash event, of course, but we’ll get to that later. Right now let’s write the onAvatarDeath function into the document class:

?View Code ACTIONSCRIPT3
15
16
17
18
public function onAvatarDeath( avatarEvent:AvatarEvent ):void
{
 
}

This is just like the onTick function from AvoiderGame.as. Just as then, we need to give it some code to run:

?View Code ACTIONSCRIPT3
15
16
17
18
19
20
21
22
23
public function onAvatarDeath( avatarEvent:AvatarEvent ):void
{
	var gameOverScreen:GameOverScreen = new GameOverScreen();
	gameOverScreen.x = 0;
	gameOverScreen.y = 0;
	addChild( gameOverScreen );
 
	playScreen = null;
}

Lines 17-20 are copied straight from AvoiderGame.as. Line 22 introduces a new keyword: null. By setting an object equal to null you are essentially resetting it. All event listeners are removed, all contained objects are erased, all functions cease to exist. After being set to null, playScreen is in exactly the same state as before the line playScreen = new PlayScreen(); — this means that the next time we want to use it, we need to run that line again. Nullifying the playScreen will also remove it from view.

Now we need to actually trigger this event.

A Grand Event

You know how our Avatar, Enemy and AvoiderGame classes extend MovieClip so that they can do everything a MovieClip can do? Well, TimerEvent extends a class called Event in the same way. This means that we can make our own kind of event (the AvatarEvent I’ve been talking about) by extending Event, too.

So, let’s try that out, in the same way that we extended MovieClip all those times. Start a new AS file, AvatarEvent.as:

?View Code ACTIONSCRIPT3
1
2
3
4
5
6
7
8
9
10
11
package  
{
	import flash.events.Event;
	public class AvatarEvent extends Event 
	{
		public function AvatarEvent()
		{
 
		}
	}
}

This looks about right, but actually, there’s a problem. When you create an Event of any kind, it expects you to pass through the type of event in the same way that our Enemy class expects you to pass through an x- and y-coordinate — for example, an Event to tell an object to scroll is created like this:

new Event( Event.SCROLL )

We’ve not provided a way to specify the type of event like that in our code, so let’s add that in:

?View Code ACTIONSCRIPT3
1
2
3
4
5
6
7
8
9
10
11
package  
{
	import flash.events.Event;
	public class AvatarEvent extends Event 
	{
		public function AvatarEvent( type:String )
		{
 
		}
	}
}

Now we need to add a type of event for us to use. We can use a public const for this; it’s like a public var except it can’t be changed after you’ve hit Test Movie:

?View Code ACTIONSCRIPT3
1
2
3
4
5
6
7
8
9
10
11
12
13
package  
{
	import flash.events.Event;
	public class AvatarEvent extends Event 
	{
		public static const DEAD:String = "dead";
 
		public function AvatarEvent( type:String )
		{
 
		}
	}
}

Great, now we’ll be able to write:

new AvatarEvent( AvatarEvent.DEAD )

…because static consts belong to the class AvatarEvent, not to any specific instance of AvatarEvent.

It’s nearly ready to use, but we need to figure out what to do with this type that gets passed in to the new AvatarEvent. Well, actually… we don’t! Events already know what to do with a type that’s passed in to them, so we just need to “borrow” their code.

We can do this using the super() function, like so:

?View Code ACTIONSCRIPT3
1
2
3
4
5
6
7
8
9
10
11
12
13
package  
{
	import flash.events.Event;
	public class AvatarEvent extends Event 
	{
		public static const DEAD:String = "dead";
 
		public function AvatarEvent( type:String )
		{
			super( type );
		}
	}
}

What super( type ) does is, it runs the code from inside the constructor function of the Event class, and passes type through to that. That means we let the existing code (which we can’t see) inside the Event class deal with everything. Fine by me :)

(We’ll look at super in more detail in Part 5. In the meantime, feel free to check out my post about extends, override, and super.)

Now that we have the event listener and the event class, all that remains is to fire off the event when the avatar dies (i.e., when it hits an enemy). Head back to AvoiderGame.as and change this:

?View Code ACTIONSCRIPT3
46
47
48
49
50
51
52
53
if ( avatar.hitTestObject( enemy ) ) 
{
	gameTimer.stop();
	var gameOverScreen:GameOverScreen = new GameOverScreen();
	gameOverScreen.x = 0;
	gameOverScreen.y = 0;
	addChild( gameOverScreen );
}

to this:

?View Code ACTIONSCRIPT3
46
47
48
49
50
if ( avatar.hitTestObject( enemy ) ) 
{
	gameTimer.stop();
	dispatchEvent( new AvatarEvent( AvatarEvent.DEAD ) );
}

Line 49 fires off an AvatarEvent of type DEAD. That’s all there is to it. I removed all the code about the Game Over screen because we’re dealing with that in the document class now.

Save it and run, and hey, what do you know, it all works as it should.

I realise that this last big change didn’t change the game in a way that the player could notice, but reorganising the internal structure like this will certainly make it a lot easier to add new features in the future. I’ll prove this in the next part, where we’ll add a title screen and a reset button with minimal effort — available here.

Also, if you like, you can grab the zip with all the files I’ve been using so far from here.

{ 220 comments… read them below or add one }

Ryan May 31, 2009 at 3:49 pm

yay, if you dont mind ill pop in every now and then and try to offer help when I can

Michael Williams June 1, 2009 at 4:18 pm

That would be great! Thanks :D

felixmarcus June 15, 2009 at 1:31 am

Great tutorial so far… I’m learning more here than I have in an entire semester of ActionScript class!

Michael Williams June 15, 2009 at 1:56 am

Wow, thanks Felix, that’s great to hear :)

ismael July 29, 2009 at 4:29 am

hello i’m learning how to make the preloader in AS3
in my project i have 3 classes
the Main , Preloader(movieClip),Counter,LoadingProgress(movieClip),

 Main
package{

    import flash.display.MovieClip;
    import flash.events.Event;
    import flash.events.ProgressEvent;
    public class Main extends MovieClip

    {


        public var preloader:Preloader;
        public var loadingProgress:LoadingProgress;



        public function Main()

        {

          loaderInfo.addEventListener( Event.COMPLETE, onCompletelyDownloaded );
          loaderInfo.addEventListener( ProgressEvent.PROGRESS, onProgressMade );
          preloader=new Preloader();
          loadingProgress = new LoadingProgress();
          loadingProgress.x = 200;
          loadingProgress.y = 150;
          addChild( loadingProgress );
          addChild(preloader);
        }



        public function onCompletelyDownloaded(event:Event):void
          {
              gotoAndStop(2);

          }



         public function onProgressMade( progressEvent:ProgressEvent ):void

           { loadingProgress.setValue( Math.floor( 100 * loaderInfo.bytesLoaded / loaderInfo.bytesTotal ) );


           }










    }









}

Preloader
package{
import flash.display.MovieClip;

    public class Preloader extends MovieClip
    {

        public function Preloader()

        { 
           x = 350;
           y = 194;
           width=100;
           scaleY=scaleX;
         }  

    }






}

Counter
package{

     import flash.display.MovieClip;

     public class Counter extends MovieClip
{
    public var currentValue:Number;

    public function Counter()
    {
      reset();

    }

    public function addToValue( amountToAdd:Number ):void
    {
        currentValue = currentValue + amountToAdd;
    }

    public function reset():void
    {
        currentValue = 0;

    }

    public function updateDisplay():void
    {

    }
}



  }

LoadingProgress

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();

        }


        public function setValue( amount:Number ):void
        {
            currentValue = amount;
            updateDisplay();
        }




      }






  }

inside Preloader(movieClip) i have just loop animation
inside LoadingProgress(movieClip) i have dynamic textfield name percentDisplay
normaly have to display the % progress

when i run my project the message is
compiler error location LoadingProgress.as line 23 1120 acces of undefined property
percentDisplay

i realy need help in order to finish my project
thanks

Michael Williams July 29, 2009 at 11:54 am

In File > Publish Settings > Flash > Settings, do you have automatically declare stage instances checked or unchecked?

ismael July 29, 2009 at 4:16 pm

i have declared stage instances checked when i run the project i have the same
message:
compiler error location LoadingProgress.as line 23 1120 acces of undefined property percentDisplay

Michael Williams July 29, 2009 at 7:22 pm

Dang, OK. Well, is your dynamic text definitely called percentDisplay (double-check the spelling), and is it directly inside the LoadingProgress, or somewhere else, like in Preloader?

ismael July 29, 2009 at 9:31 pm

it directly inside LoadingProgress as instance name of my dynamic textfiled

as you did for the AS3 Avoider Game Tutorial Part 5: A Score

inside my MovieClip LoadingProgress i have created a dynamic text called percentDisplay

Michael Williams July 29, 2009 at 10:25 pm

Hmm. Gotta admit, I’m stumped. You want to send me your zip file so I can take a look? My address is on the About page if so (and remember to convert the FLA to CS3 format, please)

Michael Williams July 30, 2009 at 10:37 pm

Got it, thanks.

There’s a few more steps required to get the preloader working; you need to use three frames instead of two, add a stop(); call on the timeline, and some other things.

Check out Part 8 for more, or read the preloading tutorial over at 8bitrocket.

Jamie Steel August 4, 2009 at 5:38 pm

Seem to be getting this error message. I am no programmer and I have no idea what im doing really. But ive checked over it again and again and can’t seem to find any difference at all.
1046: Type was not found or was not a compile-time constant: GameOverScreen.
1180: Call to a possibly undefined method GameOverScreen.

public function onAvatarDeath( avatarEvent:AvatarEvent ):void
        {
            var gameOverScreen:GameOverScreen = new GameOverScreen();
            gameOverScreen.x = 0;
            gameOverScreen.y = 0;
            addChild( gameOverScreen );

    playScreen = null;

}

Jamie Steel August 4, 2009 at 5:52 pm

Rewrote the AvatarEvent.as looks exact the same but now i get only 1 error:

1119: Access of possibly undefined property DEAD through a reference with static type Class.

Any clues on what this could be mate?

Michael Williams August 5, 2009 at 2:30 am

Hey Jamie

Sounds to me like your GameOverScreen class isn’t called GameOverScreen (i.e. it doesn’t say public class GameOverScreen or public function GameOverScreen(), or isn’t called GameOverScreen.as). For the error #1119, perhaps you don’t have a line public static const DEAD:String = "dead"; inside your AvatarEvent?

If neither of those are the case, use the debugging tips to figure out exactly what lines of code are causing the errors, and let me know.

Jamie Steel August 5, 2009 at 3:48 pm

Hey mate I done this part of the tutorial again and it seems to be working fine. I have no idea what was wrong with my previous attempt, although I did notice i only had 4 movie clips whereas your version had 5 so I must have missed some part out. That’s me on to the next part, only programming tutorial iv’e done that is thorough enough for me (an Animation Student) and not a Programmer to understand :)

Anyway thanks for the quick reply!

Michael Williams August 5, 2009 at 4:13 pm

Hey Jamie, glad it’s working now (even if the reasons are a little mysterious!) and thanks for the kind words :)

James Coyle August 17, 2009 at 7:33 pm

Hi, nice tutorial although I’m having a bit of trouble creating a game over event and then using it to cut to my game over screen, i first tried extending the Event class as you did but to no avail. I’ve now tried replacing that with simply placing

dispatchEvent(new Event("dead"));

into my game class (not the best coding practice i know but im trying to simplify things to help isolate the problem) and then adding an event listener to the document class, this also didnt work although when i then added another event listener to the game class that one did work.

As far as I understand, the document class is linked directly to the stage which is where all events start their event flow, so why is it that the listener in my document class is not responding to the event? Any insight would be greatly appreciated as this is driving me mental!

Michael Williams August 18, 2009 at 12:24 am

Hi James,

Nice work trying to isolate the problem :)

Actually, events start at the object that triggers them, and optionally “bubble up” through the chain of display object parents until they reach the stage (which, as you say, is basically the same as the document class).

In other words, if the avatar dispatches an event, and that event is set to “bubble”, then the avatar’s parent (the play screen) will automatically detect this, and dispatch a duplicate event. The document class, being the play screen’s parent, will then automatically detect and duplicate this event.

This is how the document class can usually detect events that originate in objects that it doesn’t have any direct link to. If you simply write, within the document class, addEventListener( ... ) without specifying an object to attach the listener to (like playScreen.addEventListener( ... ), it’ll attach the listener to itself, and detect the duplicate of the original function that it ends up dispatching automatically! It gets a little confusing.

However, since none of the custom events in the tutorial are set to bubble by default, this neat effect won’t happen.

Could you copy and paste the line of code that dispatches the event (and let me know what class it’s in), and the line of code in the document class that listens for that event? Cheers.

James Coyle August 18, 2009 at 3:22 pm

document class

package Classes
{
    import flash.display.MovieClip;
    import flash.events.Event;

public class DocumentClass extends MovieClip
{
    var game:MovieClip = new Enemydodge();

    public function DocumentClass()
    {
        addChild(game);
        addEventListener("dead", gameover);     //My game over listener
    }

    public function gameover(event:Event):void
    {
        trace("fail");     //testing event with a trace for simplicities sake
    }
}

}

game class

package Classes
{
    import flash.display.MovieClip;
    import flash.events.Event;

public class Enemydodge extends MovieClip
{
    var hero:MovieClip = new Hero();
    var enemy:MovieClip = new Chaser2();

    public function Enemydodge()
    {
        addChild(enemy);
        addChild(hero);
        enemy.chase(hero, 5);
        addEventListener(Event.ENTER_FRAME, failtest);
    }

    public function failtest(event:Event):void
    {
        if(enemy.hitTestObject(hero))
        {
            dispatchEvent(new Event("dead"));      //game over event dispatcher
        }
    }
}

}

These are the 2 offending classes that keep causing problems, btw, to save an confusion I should probably mention that this isnt an avoider game like the one you’ve been making, instead i gave my enemy a crude AI to make it chase the player.

ps. are you sure that event flow starts at the target? in as3 bible they say that events start with the capture phase which works its way from the stage up to the target.

Michael Williams August 18, 2009 at 5:36 pm

You’re right, I was oversimplifying. Events *do* start with the capture phase, working up from the stage, but addEventListener() will only detect such an event if you set the third parameter to true like this:

addEventListener("dead", gameover, true);

By default (or if you set the third parameter to false), addEventListener() will only listen for events at the target or in the bubble phase (which comes after the capture phase).

Try this instead:

        public function DocumentClass()
        {
            addChild(game);
            game.addEventListener("dead", gameover);     //My game over listener
        }

Let me know if that works :)

James Coyle August 18, 2009 at 7:03 pm

Brilliant! I cant believe I overlooked such a simple solution, thank you very much for your help

Michael Williams August 19, 2009 at 11:00 am

You’re welcome; glad to hear it worked :)

DudexD August 22, 2009 at 11:50 am

Hi! great Tut’s, but i got small issue… i saved my work when i got to the AvoiderGame once removed part and went to bed:D at that time everything was as it should be, then next day when i loaded all files this error showed “5006: An ActionScript file can not have more than one externally visible definition: DocumentClass, onAvatarDeath” :S i’m not to familliar with fixing this kind of stuff but you know what i should do?:D

Michael Williams August 22, 2009 at 3:25 pm

Hi DudexD,

Sounds like you have the onAvatarDeath function in the wrong place within the class file — perhaps it’s outside the curly brackets that belong to the DocumentClass class?

Either that, or you could have written public class onAvatarDeath instead of public function onAvatarDeath accidentally.

DudexD August 22, 2009 at 6:01 pm

thats the code… it looks right from my point of view, and the weird thing is that it worked. then i saved everything and closed the program, then i opened everything again and then it didn’t work -_-

package 
{
    import flash.display.MovieClip;
    public class DocumentClass extends MovieClip 
    {
        public var playScreen:AvoiderGame;

    public function DocumentClass() 
    {
        playScreen = new AvoiderGame();
        playScreen.addEventListener( AvatarEvent.DEAD, onAvatarDeath );
        addChild( playScreen );
    }
}
public function onAvatarDeath( avatarEvent:AvatarEvent ):void
{
    var gameOverScreen:GameOverScreen = new GameOverScreen();
    gameOverScreen.x = 0;
    gameOverScreen.y = 0;
    addChild( gameOverScreen );

    playScreen = null;
}

}

Michael Williams August 22, 2009 at 6:57 pm

Ah — there’s the problem. The whole onAvatarDeath() function needs to be moved inside the DocumentClass‘s curly braces, so that it’s alongside the public var playScreen and the public function DocumentClass.

Do you see what I mean by that? Let me know.

DudexD August 22, 2009 at 11:54 pm

oh yeah… i see it now:D how can i be so blind?! Thanks alot. Peace out

DudexD August 23, 2009 at 1:21 am

one problem still tho… The game over isn’t showing, and i got everything right and there are no errors, but still don’t show. or that is wrong i does show like 1/10 of the times

Michael Williams August 23, 2009 at 1:16 pm

That’s peculiar. Any idea what’s different about the times it does show up?

DudexD August 23, 2009 at 1:39 pm

hmm no totaly random:S but now it have stopped showing at all.,.,.

DudexD August 23, 2009 at 1:40 pm

i got Cs4, if that help in anyway

DudexD August 23, 2009 at 3:08 pm

Ok i fixed it:D it was something in the AviderGame that was wrong so i jsut copied you’re code from the AvoiderGame in the zip and then it worked:D

Michael Williams August 24, 2009 at 2:12 pm

Good good :)

Naveed August 27, 2009 at 11:02 am

Great tutorial. So, far going so well. I am beginning to get hold on AS3. Anyways a great and one the best tutorial of Flash.

Michael Williams August 27, 2009 at 11:51 pm

Cheers Naveed :)

James August 30, 2009 at 4:48 pm

Have I misunderstood null? In the document class (posted below) I try to set gameScreen to null and add my gameOver screen but by setting the alpha to 0.5 I could see that the game was actually still running in the background.

package SpaceShipAndProbe
{
    import flash.display.MovieClip;
    import flash.events.Event;

public class DocumentClass extends MovieClip
{
    var gameScreen:MovieClip = new GameScreen();
    var gameOver:MovieClip = new GameOver();

    public function DocumentClass():void
    {
        addChild(gameScreen);
        gameScreen.addEventListener("dead", onDead);
        gameOver.alpha = 0.5;
    }

    public function onDead(event:Event):void
    {
        addChild(gameOver);
        gameScreen.removeEventListener("dead", deadScreen);
        gameScreen = null;
    }
}

}

Michael Williams August 30, 2009 at 6:21 pm

@James — this is my fault, I’ve oversimplified the explanation of what null does at this point in the tutorial. In Part 12 you’ll learn exactly what it means and why the game screen stays there, but for now, try this:

        public function onDead(event:Event):void
        {
            addChild(gameOver);
            gameScreen.removeEventListener("dead", deadScreen);
            removeChild( gameScreen ); //this line is new
            gameScreen = null;
        }

James August 30, 2009 at 8:31 pm

I already tried that and it does solve the problem of removing the gamescreen but in itself actually causes an even bigger problem in that every frame i get the following error message in my output panel:
TypeError: Error #1009: Cannot access a property or method of a null object reference.
at SpaceShipAndProbe::GameScreen/onFrame()
This just ends up confusing me even more because since I’m essentially cutting all ties between the document and game classes I dont understand why it’s trying to access that class.

ps. How long have you been actionscripting for? Sorry if it sounds kinda nosey but I’d just like to know roughly how much of a mountain I’ve got to climb

James August 31, 2009 at 11:39 pm

Hi, just to let you know that I solved the problem so you can ignore that last post, i just added a line of code to the game screen that that removed my onFrame listener when the player got hit, i must admit i’m slightly puzzled as to why I had to manually remove the listener though.

Michael Williams September 1, 2009 at 10:38 pm

Good to know. I think it’ll become clear why you have to do that manually when you read Part 12 — if not, let me know :)

Your other question is tricky… although I’ve only been using AS3 for a little over a year, I have been programming in other languages for many years before that, and the skills are very transferable. So, it’s hard to say I’m afraid. And I’m certainly not at the top of the mountain myself ;)

James September 2, 2009 at 11:34 am

Ok, I understand that setting my instance of the game to null and removeChild-ing it only destroys the links and that the code contained within it is still left intact and can therefore run which is why every frame flash was throwing a wobbly because my onFrame method was still running but flash didnt know what to do with it. Now forgive me if I’m being simple but why is it that my other handlers contained within the game class’ children such as KeyboardEvents didnt also have to be removed?

Michael Williams September 2, 2009 at 12:29 pm

You’re not being simple at all, that’s actually a very good question.

The answer is a little sneaky. When you removeChild() the play screen, you destroy its link to the stage. An object can only “hear” keyboard events through the stage, so even though the keyboard event listener still exists for a short time, it will not be triggered, because it can’t hear the events any more!

Similarly, your timer event won’t be triggered because you called gameTimer.stop() before removing the play screen. If you didn’t do this, that event listener would keep being triggered — try it and see.

Guy September 6, 2009 at 12:02 am

Great tutorials, but I do have a question. Why exactly do we use :void if it works without it? I want to type more stuff inside this comment because everybody else has really long comments and I don’t want to stand out. So that’s why I’m typing so much nonsense right now. Just making it look like a nice well written paragraph. Oh yeah, don’t forget to answer my question.

Michael Williams September 6, 2009 at 1:33 pm

Hey Guy,

We write :void to keep things neat and consistent. In a lot of cases, we’ll want our functions to return, say, a Number or a String or even a MovieClip, and we indicate this by writing :Number (or whatever) after the definition of the function.

It looks a bit odd and uneven if we have functions that don’t specify what kind of value they return, so we use :void to make it clear that we haven’t just forgotten to mention it.

Guy September 6, 2009 at 10:24 pm

Ok thanks, I was just curious.

Michael Williams September 7, 2009 at 4:11 pm

@Guy: No problem; curiosity is a great trait for programmers :)

asdf September 8, 2009 at 9:20 pm

Have you made any really great flash games like some of the popular ones on Kong? I can tell that you know and understand actionscript very well.

Michael Williams September 9, 2009 at 12:49 pm

@asdf: No, afraid not ;) I mainly do work for or with other people, and a lot of that is behind closed doors.

Thanks though :) Do you have any games out?

asdf September 10, 2009 at 12:21 am

A couple crappy ones that I made a while ago with AS2. You should make a game, it would be beast-like.

Michael Williams September 10, 2009 at 3:04 pm

@asdf: going to share them? :)

Thanks, it’s something I’d like to do, I just have other stuff I want to get to first.

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: