Table of contents for AS3 Avoider Game Tutorial
- Learn ActionScript 3 by Following this Simple Avoider Game Tutorial
- AS3 Avoider Game Tutorial, Part 2: Multiple Enemies
- AS3 Avoider Game Tutorial, Part 3: Game Over
- AS3 Avoider Game Tutorial, Part 4: Menus and Buttons
- AS3 Avoider Game Tutorial, Part 5: A Score and a Clock
- AS3 Avoider Game Tutorial, Part 6: Several Small Improvements
- AS3 Avoider Game Tutorial, Part 7: Keyboard Control
- AS3 Avoider Game Tutorial, Part 8: Adding a Preloader
- AS3 Avoider Game Tutorial, Part 9: Music and Sound Effects
- AS3 Avoider Game Tutorial, Part 10: Multiple Levels
- AS3 Avoider Game Tutorial, Part 11: Saving and Loading
- AS3 Avoider Game Tutorial, Part 12: Garbage Collection
(This tutorial is also available in Spanish)
Introduction
In this part of my AS3 conversion of Frozen Haddock’s avoiding game tutorial, we’ll be inserting a button to let the player restart the game if they die, and adding a menu screen to the start of the game.
Click the image below to see how this will look.
If you’ve not been following the tutorial so far, 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.
Let Me Try That Again
At the minute, if the player touches an enemy, he’s sent to the game over screen and has to refresh the page in order to play again. We’re going to add a simple button to this screen that lets the player try again.
Create a new symbol of type Button (Insert > New Symbol, and select the Button option). Call it RestartButton, and click OK.

You’ll enter editing mode for this new button. Draw whatever you like, as long as it’s obvious that clicking this will start the game again. Here’s mine:

Now check out the timeline at the top of the screen:

A button actually contains four separate images:
- Up — What the button looks like normally.
- Over — What the button looks like when the mouse is pointing at it.
- Down — What the button looks like when it’s being clicked.
- Hit — The area of the button that is “sensitive” to the mouse (more on this in a bit).
The shaded grey box with a dot in it in the Up column indicates that we have drawn an image for that state. Let’s draw images for the others now. Right-click each of the empty boxes in turn and select Insert Keyframe:


…

OK, great. Click the shaded grey box with a dot in it (also known as a keyframe) in the Over column. It should have copied the image from the Up column into it; if not, you can copy and paste it from that column. Change the image in some suitable way — I’m just going to invert the colours of mine:

Now change the Down keyframe in some other way:

The Hit keyframe is a little different. The shape you draw in here defines the “clickable” area of the button. The player will never actually see this image. If you drew a button with a shadow, for instance, and you wanted the player to be able to click the button but not the shadow, then you would just draw the button’s shape in here and leave the shadowed area blank. (Does that make sense?)
Anyway, for my button I don’t want to leave any of the button unclickable, so I’m going to make the shape the same shape as the button:

I’ve coloured it bright red just to remind myself that this is not going to be seen by the player, but you can make it any colour you like. You can even leave the original image there, if you want.
Now we need to add this button to the game over screen. Save what you’ve done, then double-click the GameOverScreen in the Library.

Find your new RestartButton in the Library and drag it onto the game over screen.

(Oops. I forgot that the black border of the button wouldn’t show up against the black background of the game over screen. Oh well.)
Remember back in the first part of this tutorial, when I talked about instances and classes? Well, the button on the game over screen is an instance of the class RestartButton. Since we haven’t defined it in ActionScript, it doesn’t have an instance name. If we want to be able to access it with code (and we do), we need to give it one.
Click the button you just added, and check out the Properties panel:

The box marked

All right, now we can write some code to get it to actually do something when it’s clicked.
Hey! …Listen!
So far we’ve used event listeners to trigger a function on the death of the avatar and the “tick” of the game timer. Now we’re going to be listening for the “click” of the restart button.
Since the button exists in the GameOverScreen, code concerning it must go in the GameOverScreen class. But… we never actually made such a class. So let’s do it now! Create a new AS file and enter the following:
1 2 3 4 5 6 7 8 9 10 11 | package { import flash.display.MovieClip; public class GameOverScreen extends MovieClip { public function GameOverScreen() { } } } |
Save this as GameOverScreen.as in your Classes directory.
Hopefully this code is looking quite familiar by now. Save everything and test the game. It’ll give you an error:
GameOverScreen.as, Line 2 1046: Type was not found or was not a compile-time constant: SimpleButton.
What? Flash has detected that there is a button on the GameOverScreen but is saying “what is this? I have never heard of this ‘button’”. Flash can be pretty dumb sometimes.
We need to tell Flash exactly what a button is. Go back to GameOverScreen.as and modify it to import the SimpleButton class definition (line 4):
1 2 3 4 5 6 7 8 9 10 11 12 13 | package { import flash.display.MovieClip; import flash.display.SimpleButton; public class GameOverScreen extends MovieClip { public function GameOverScreen() { } } } |
Now you can save it and test it. You’ll notice that the button changes when you hover over it and when you click it. Obviously it doesn’t actually do anything because we haven’t added the event listener yet. So let’s do that next.
Since this code is so similar to what we’ve added in earlier parts, I’ll just insert all of it at once and explain it afterwards:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | package { import flash.display.MovieClip; import flash.display.SimpleButton; import flash.events.MouseEvent; public class GameOverScreen extends MovieClip { public function GameOverScreen() { restartButton.addEventListener( MouseEvent.CLICK, onClickRestart ); } public function onClickRestart( mouseEvent:MouseEvent ):void { } } } |
- public function onClickRestart( mouseEvent:MouseEvent ) — This is the function that we want to be run upon clicking restart (hence, “on click restart”). Just as before, we are allowing information about the event (of the clicking) to be passed to this function.
- restartButton.addEventListener( MouseEvent.CLICK, onClickRestart ); — This adds the event listener to the button, and tells it that if the button is CLICKed (yes, Flash really requires you to write CLICK in capitals like that) then it should run the onClickRestart function.
- import flash.events.MouseEvent; — Without this line, Flash wouldn’t know what a mouse event was, which means it wouldn’t know the meaning of the word CLICK.
To start the game again, we have to remove the game over screen and reload the play screen. In Part 3 we rearranged everything so that the document class handled all this screen manipulation, so it’s that class that we need to modify. Open DocumentClass.as and add this new function:
24 25 26 27 28 29 30 31 | public function restartGame():void { playScreen = new AvoiderGame(); playScreen.addEventListener( AvatarEvent.DEAD, onAvatarDeath ); addChild( playScreen ); gameOverScreen = null; } |
Lines 26 & 27 set up the playScreen in exactly the same way as the constructor. This is necessary, because when the player gets Game Over, that line playScreen = null will erase the event listener and reset the x and y coordinates of the playScreen, as I explained in Part 3.
Line 30 would erase the gameOverScreen, but there’s a problem. gameOverScreen is only defined in the onAvatarDeath() function, so it isn’t available to the restartGame() function. Let’s make gameOverScreen available to the whole document class, just like playScreen:
1 2 3 4 5 6 7 | package { import flash.display.MovieClip; public class DocumentClass extends MovieClip { public var playScreen:AvoiderGame; public var gameOverScreen:GameOverScreen; |
Now we need to remove the var from the var gameOverScreen statement from onAvatarDeath, since we’ve already defined it:
16 17 18 19 20 21 22 23 24 | public function onAvatarDeath( avatarEvent:AvatarEvent ):void { gameOverScreen = new GameOverScreen(); gameOverScreen.x = 0; gameOverScreen.y = 0; addChild( gameOverScreen ); playScreen = null; } |
Here’s what my class looks like:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | package { import flash.display.MovieClip; public class DocumentClass extends MovieClip { public var playScreen:AvoiderGame; public var gameOverScreen:GameOverScreen; public function DocumentClass() { playScreen = new AvoiderGame(); playScreen.addEventListener( AvatarEvent.DEAD, onAvatarDeath ); playScreen.x = 0; playScreen.y = 0; addChild( playScreen ); } public function onAvatarDeath( avatarEvent:AvatarEvent ):void { gameOverScreen = new GameOverScreen(); gameOverScreen.x = 0; gameOverScreen.y = 0; addChild( gameOverScreen ); playScreen = null; } public function restartGame():void { playScreen = new AvoiderGame(); playScreen.addEventListener( AvatarEvent.DEAD, onAvatarDeath ); playScreen.x = 0; playScreen.y = 0; addChild( playScreen ); gameOverScreen = null; } } } |
I’ve added lines 13 & 14 to position the playScreen at (0,0), just like with the gameOverScreen, and duplicated them in restartGame(). In a later part, I’ll simplify the way things work so that we don’t have to write the same code twice all the time.
REBOOT!
So now we have a function in gameOverScreen that is run when the restart button is clicked, and a function in the document class that restarts the game. It’s certainly tempting to hook the two together directly, but as I explained in the previous part, that leads to problems down the line. We’ll take the same approach here as we did with the avatar’s death: creating a new custom event.
What’ll happen is this:
- Player clicks restart button
- Restart button sends off a MouseEvent of type CLICK
- MouseEvent.CLICK is picked up by an event listener within gameOverScreen, and triggers onClickRestart()
- onClickRestart(), in turn, sends off our new custom event — let’s call it NavigationEvent — of type RESTART
- NavigationEvent.RESTART is picked up by an event listener within the document class, and triggers a new function: onRequestRestart()
- onRequestRestart() runs the restartGame() function
Phew! It’s long, but it’s actually quite straightforward. It also gives us scope for letting the player restart the game in other ways: when they press “R”, perhaps, or after a few seconds have passed. In either case, we just need to fire off a NavigationEvent.RESTART event, and we’ll already have done the rest.
Our new custom event looks much like the AvatarEvent:
1 2 3 4 5 6 7 8 9 10 11 12 13 | package { import flash.events.Event; public class NavigationEvent extends Event { public static const RESTART:String = "restart"; public function NavigationEvent( type:String ) { super( type ); } } } |
(Save this as NavigationEvent.as in the Classes folder.) Firing off the event is simple, too (this next bit goes in GameOverScreen):
14 15 16 17 | public function onClickRestart( mouseEvent:MouseEvent ) { dispatchEvent( new NavigationEvent( NavigationEvent.RESTART ) ); } |
And with this being your third event listener, you should have no problems adding it to the document class (line 21):
18 19 20 21 22 23 24 25 26 27 | public function onAvatarDeath( avatarEvent:AvatarEvent ):void { gameOverScreen = new GameOverScreen(); gameOverScreen.addEventListener( NavigationEvent.RESTART, onRequestRestart ); gameOverScreen.x = 0; gameOverScreen.y = 0; addChild( gameOverScreen ); playScreen = null; } |
Of course, you need to create the onRequestRestart() function within the document class, and tell it what to do:
29 30 31 32 | public function onRequestRestart( navigationEvent:NavigationEvent ):void { restartGame(); } |
So now when the restart button is pressed (and after a long chain of events), the document class’s restartGame function will be run, which in turn will remove the game over screen and reload the play screen. Save it and test it, and at last, the player can restart the game without refreshing the page!
Hobson’s Choice
Adding a menu to the start of the game really isn’t difficult now. The code is going to be practically the same as for the game over screen. Let’s go through the steps real fast.
First, create a menu screen. You can create one from scratch if you like, but since the game over screen is already the right size I’m going to make a copy of that to start from.
Go back to your FLA file and find GameOverScreen in the Library. Right-click it and select Duplicate. It’ll ask for a name, so type in MenuScreen; leave the Type as Movie Clip. Double click the new MenuScreen in the Library to enter editing mode, and delete the restart button. Make whatever changes you want to the interface. Here’s mine:

A true work of art.
Now for the button. Again, you can make one from scratch like we did earlier (remember it needs to be of type Button!), or you can duplicate the existing RestartButton. Totally your choice. Either way, call the new button StartButton and edit it accordingly. Here’s mine:

I’m not being lazy, I’m maintaining a consistent style throughout my application. Add this new button to your MenuScreen and set the instance name to startButton.

Now let’s write the code. Right-click the MenuScreen and select Properties. Check the Export for ActionScript box, enter MenuScreen in the Class box if it doesn’t come up automatically, and click OK. As usual, it’ll tell you:

…so let’s create that class file.
Hit File > New and select ActionScript file. This is going to be the class file for our MenuScreen. Here’s the code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | package { import flash.display.MovieClip; import flash.display.SimpleButton; import flash.events.MouseEvent; public class MenuScreen extends MovieClip { public function MenuScreen() { startButton.addEventListener( MouseEvent.CLICK, onClickStart ); } public function onClickStart( event:MouseEvent ):void { dispatchEvent( new NavigationEvent( NavigationEvent.START ) ); } } } |
Save the file in your Classes directory as MenuScreen.as.
I’m not even going to explain most of this code, because it is almost exactly the same as GameOverScreen.as. Note, however, that in line 16 I’ve dispatched a NavigationEvent of type START — but at the minute the NavigationEvent class only has a RESTART type. Let’s add this new type to NavigationEvent.as right now:
1 2 3 4 5 6 7 | package { import flash.events.Event; public class NavigationEvent extends Event { public static const RESTART:String = "restart"; public static const START:String = "start"; |
Simple enough.
At the minute, the document class is displaying the play screen when it starts up. We’re going to change it to display our new menu screen instead. Change these lines:
6 7 8 9 10 11 12 13 14 15 16 | public var playScreen:AvoiderGame; public var gameOverScreen:GameOverScreen; public function DocumentClass() { playScreen = new AvoiderGame(); playScreen.addEventListener( AvatarEvent.DEAD, onAvatarDeath ); playScreen.x = 0; playScreen.y = 0; addChild( playScreen ); } |
to this:
6 7 8 9 10 11 12 13 14 15 16 17 | public var menuScreen:MenuScreen; public var playScreen:AvoiderGame; public var gameOverScreen:GameOverScreen; public function DocumentClass() { menuScreen = new MenuScreen(); menuScreen.addEventListener( NavigationEvent.START, onRequestStart ); menuScreen.x = 0; menuScreen.y = 0; addChild( menuScreen ); } |
Note that I’ve added a new public var called menuScreen, and am no longer setting up the playScreen here.
Now we just need to make that new onRequestStart() function (line 13, above) and we’ll be sorted:
35 36 37 38 39 40 41 42 43 44 | public function onRequestStart( navigationEvent:NavigationEvent ):void { playScreen = new AvoiderGame(); playScreen.addEventListener( AvatarEvent.DEAD, onAvatarDeath ); playScreen.x = 0; playScreen.y = 0; addChild( playScreen ); menuScreen = null; } |
Save everything and test the game and… success!
Wrapping Up
I realise I went through things a bit faster in this part than I have previously. I’m doing this so as not to repeat myself, but if it’s just making things more confusing, please let me know.
As always, you can grab the zip file with everything I’ve done so far here, and you can subscribe to my RSS feed (to be alerted as soon as the next part is available) here.
In Part 5 I’ll show you how to add a clock and a score. Until then, why not have a go at adding a button to the Game Over screen that takes you back to the menu?


{ 2 trackbacks }
{ 160 comments… read them below or add one }
← Previous Comments
Hey, thanks FooSai! How’ve you found it past Part 4?
Nice work on getting the “back to menu” button working, by the way
Cheers
All good so far, just done part 7 and I’m going to go through the challenges you set before I move on.
-FS
Sounds good
Hey Michael!
Just have to say, this is a very helpfull and good guide!
Having a problem atm, I just finished the part where your restart button should restart the game without having to refresh. But I keep getting this sentence:
1114: The public attribute can only be used inside a package. Source:public function onRequestStart( navigationEvent:NavigationEvent ):void
and
1114: The public attribute can only be used inside a package.public function onRequestRestart( navigationEvent:NavigationEvent ):void
Hey, thanks Nejirax
Sounds like you may have your curly braces in the wrong order. That function should be inside the curly brackets belonging to the class, but outside the curly brackets belonging to any other function.
(It’s difficult to explain in a comment; if you’d like to paste your whole class file here I’ll take a look.)
I hit the same problem to earlier users such as Vectomon and Dan where they were getting an error that said “Access of undefined property startButton”.I found out that this was simply due to not linking my MenuScreen to it’s actionscript.
Other than that, these tutorials are great! Thanks a lot Michael!
Hey Michael,
Nicely solved
Thanks for your kind words!
When I run it, I get this:
GameOverScreen.as, Line 11 1120: Access of undefined property restartButton.
NVM, I saw your outer comment. =D
Hehe, OK Jeff, glad you got it sorted
← Previous Comments