AS3 Avoider Game Tutorial, Part 4: Menus and Buttons

by Michael James Williams on October 12, 2008 · 289 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, 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.

screenshot

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.

screenshot

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:

screenshot

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

screenshot

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:

screenshot

screenshot

screenshot

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:

screenshot

Now change the Down keyframe in some other way:

screenshot

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:

screenshot

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.

screenshot

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

screenshot

(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:

screenshot

The box marked is what we need. Enter restartButton (as usual, be careful with the capital letters!)

screenshot

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:

?View Code ACTIONSCRIPT3
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):

?View Code ACTIONSCRIPT3
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:

?View Code ACTIONSCRIPT3
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:

?View Code ACTIONSCRIPT3
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:

?View Code ACTIONSCRIPT3
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:

?View Code ACTIONSCRIPT3
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:

?View Code ACTIONSCRIPT3
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:

?View Code ACTIONSCRIPT3
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):

?View Code ACTIONSCRIPT3
14
15
16
17
public function onClickRestart( mouseEvent:MouseEvent ):void
{
	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):

?View Code ACTIONSCRIPT3
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:

?View Code ACTIONSCRIPT3
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:

screenshot

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:

screenshot

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.

screenshot

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:

screenshot

…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:

?View Code ACTIONSCRIPT3
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:

?View Code ACTIONSCRIPT3
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:

?View Code ACTIONSCRIPT3
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:

?View Code ACTIONSCRIPT3
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:

?View Code ACTIONSCRIPT3
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?

{ 288 comments… read them below or add one }

Michael Williams May 29, 2010 at 12:12 am

Nice work, Crump! That’s awesome :D How did you solve it?

Morgan May 29, 2010 at 6:21 am

Ive gone through your brilliant tutorial, and really enjoyed it! I managed to add a few extras which i was very proud of given that its was my first time using external .as files.

Now im trying to make a my own program and at the moment im trying to get my DocumentClass to add my first screen to the stage. My first screen is a class called SpaceCrystalScreen. Here is the code for my DocumentClass:

package
{
    import flash.display.MovieClip;

public class DocumentClass extends MovieClip
{
    var spaceCrystalScreen:SpaceCrystalScreen;

public function DocumentClass();
{
    spaceCrystalScreen = new SpaceCrystalScreen();

    spaceCrystalScreen.x = 0;
    spaceCrystalScreen.y = 0;
    addChild (spaceCrystalScreen);
}

}

}

however whenever i try to reference spaceCrystalScreen i get the 1120 error
1120: Access of undefined property spaceCrystalScreen.

it should be very simple and i cant understand why because i have declared the variable at the class level. can you see whats wrong?

cheers
mate!

Morgan May 29, 2010 at 6:24 am

sorry a mistake above
it should be public var spaceCrystalScreen:SpaceCrystalScreen;

but even when i add that it still throws the error… :(

Morgan May 29, 2010 at 6:46 am

Sorry to spam! but i rewrote my class and now it works. i hate not knowing what i did wrong though!

ps. your tutorial is great! ive read a few books on AS3 and now i get them!

ayumilove May 31, 2010 at 11:30 pm

@Morgan

ActionScript error #1120 means that an object “property” within Flash or Flex is not defined. But this doesn’t really help you fix it. One main reason for this AS3 Error is that you haven’t given the MovieClip or Button an instance name when you placed it on the stage in Flash. Another reason is that the reference is not correct.

Michael Williams June 12, 2010 at 1:34 pm

@Morgna: Great to hear — and thanks :D

@ayumilove: Good points. Man, I wish Flash would give you a little more detail on the error (like which property it is).

Colin June 13, 2010 at 9:26 am

hello,

i’m loving the tutorial so far but i’m getting an error that reads:

C:\Users\Ghost Train\Documents\Flash\Avoider\Classes\MenuScreen.as, Line 11 1120: Access of undefined property startButton..

i’ve triede “trace()”ing it and i have the instance of startButton name correctly on the stage, what other ways do you think i should try and solve this?

thank you

Josh June 14, 2010 at 6:00 pm

My restart button doesn’t do anything.
I’ve checked the code 5 times over and can’t find a problem…

I need some help =/

Michael Williams June 22, 2010 at 3:32 pm

@Colin: Have you turned “auto-declare stage instances” on, as in the start of Part 1? Also, is your startButton inside the MenuScreen clip, and is the MenuScreen exported for ActionScript?

@Josh: Put trace() statements in the most important points: start with one in the CLICK event handler function. (The trace() statement outputs a line of text to the Flash Output panel; use it like this: trace("this is a test");)

Colin July 11, 2010 at 2:52 pm

i am having a huge problem with my document class. I get this error: Line 1 5006: An ActionScript file can not have more than one externally visible definition: DocumentClass, onAvatarDeath. WHAAA? help please
Code:
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;

}

}

Ivan Ruiz July 12, 2010 at 6:56 pm

hi, first of all thank you i have learned a lot but i have a problem and have been trying to solve it for years

is the problem

1061: Llamada a un método addEventListener posiblemente no definido mediante una referencia con tipo estático Class.

can anyone tell me what can cause that problem

thanx

Michael Williams July 23, 2010 at 11:50 am

@Colin: This error is because your onAvatarDeath() function is outside the DocumentClass‘s curly braces. Move it back inside the braces and the problem should be solved :)

@Ivan Ruiz: Looks like you’re trying to call .addEventListener() on a class, rather than on an instance of a class. For example, perhaps you’re doing MenuScreen.addEventListener() instead of menuScreen.addEventListener().

WorkingMan July 27, 2010 at 6:53 pm

When we make the buttons for the menu screen and the game over screen, we have to drag the button onto the MovieClip in Flash and then create an instance for each button.

Is there a way to place the button on the MovieClip and create instances by using Actionscript in the code?

Thanks

Mudkip August 3, 2010 at 4:58 pm

I’m having a problem with removing playScreen and gameOverScreen.

I set them to null, like it says in the tutorial, but they still remain there, EventListeners and all.

No idea what I’m doing wrong.

Mudkip August 3, 2010 at 5:02 pm

Also, when I trace gameOverScreen or playScreen after setting them to null, they do in fact show as null, but they remain.

James August 4, 2010 at 3:11 am

Hi, me again,
This time it’s for a location problem.
Where can I find the properties thing(for the replay button), in CS4 10.0?????
I looked through every possible menu in the instance right click drop down, but couldn’t find it.

TJ August 10, 2010 at 3:52 pm

Thanks for this awesome tutorial. =D

I have a problem though… I’m pretty sure I’ve followed everything here, but when I click on Start and Restart, it doesn’t kill the menu or game over screens. The smileys start falling down, with the game over or menu screen as a background.

package{
    import flash.display.MovieClip;

public class Main extends MovieClip{
    public var playScreen:AvoiderGame;
    public var GameOver:GameOverText;
    public var mainMenu:MainMenu;

public function Main(){
    mainMenu = new MainMenu();
    mainMenu.addEventListener( NavigationEvent.START, onRequestStart);
    addChild (mainMenu);
}

public function onPlayerDeath(playerEvent:PlayerEvent):void{
    GameOver = new GameOverText();
    GameOver.addEventListener( NavigationEvent.RESTART, onRequestRestart);
    addChild (GameOver);

    playScreen = null;
}

public function restartGame():void {
    playScreen = new AvoiderGame();
    playScreen.addEventListener(PlayerEvent.DEAD, onPlayerDeath);
    addChild(playScreen);

    GameOver = null;
}

public function onRequestRestart( navigationEvent:NavigationEvent):void {
    restartGame();
}

public function startGame():void {
    playScreen = new AvoiderGame();
    playScreen.addEventListener( PlayerEvent.DEAD, onPlayerDeath);
    addChild(playScreen);

    mainMenu = null;
}
public function onRequestStart( navigationEvent:NavigationEvent):void {
    startGame();
}

}

}

There’s my code. XD

TJ August 10, 2010 at 3:58 pm

Ah dang. I just solved it.

Apparently I didn’t link the BG to the Game AS.

Sorry! >.<

Anyways, awesome tutorial. ;D

Michael Williams August 21, 2010 at 12:15 am

OK! So, it seems I let these comments pile up again. Sorry about that. Here goes:

@WorkingMan: Yes! Entirely possible. Just export the button for ActionScript in the library and then use the same methods you use to put an instance of the Avatar on the screen.

@Mudkip: You need to removeChild() them. I explain more about what null actually does in Part 12 of the tutorial.

@James: Hi. Click the button, then click Window > Panels > Properties panel. (Or it might just be Window > Properties. I don’t have CS4.)

@TJ: Thanks! Well done for fixing it :)

Xadjim September 15, 2010 at 4:01 pm

i dont get the dispatch crap…. the super function is a mystery to me too….what are they actually doing? if someone answers… pls do that simple

Dan September 16, 2010 at 5:29 pm

@Xadjim

Gonna take a stab at this, if anyone else has better explanations then please share.

==========

Dispatching events is the way you pass info from class to class without specifying objects. (Also makes your code reusable down the road.) Sort of like tossing a ball from person A to person B:

So imagine you have two people/classes, PersonA and PersonB.

PersonA has the ball, and wants to throw the ball to PersonB.

PersonA dispatches an event: “throwing ball”

PersonB has an event listener for “throwing ball”, and catches it.

Later on, you can have PersonC with an event listener for “throwing ball”, or have her dispatch it.

==========

Super basically calls the function of the parent.

As above in Michael’s tutorial, NavigationEvent extends Event. NavigationEvent by itself doesn’t do anything; the constructor is empty. But once it calls super(), NavigationEvent calls Event’s constructor, and NavigationEvent is constructed with Event’s properties and functions.

If you didn’t call super() in the constructor, you’d have to build NavigationEvent yourself to handle event passing.

ayumilove September 17, 2010 at 12:53 pm

[/QUOTE]i dont get the dispatch crap…. the super function is a mystery to me too….what are they actually doing? if someone answers… pls do that simple[/QUOTE]

just think dispatch as broadcasting a news.

everywhere around you, something is broadcasting.
You as the listener listens to those signals.

You walk down your local neighborhood and you heard an adult shouting at the top of his voice “Selling Ice cream, Vanilla, Strawberry and Chocolate Flavor”

But you did not stop by since you are allergic to ice cream (lol who knows?)

you walk further down and again you listened to night club playing jazz music.

Assuming you are a jazz fanatic, you decided to take a visit into the night club.

The ‘visit’ action you took is called a trigger function.
As a listener, you listen to things that are of interest to you.
You found something interesting and you do something about it. (visit jazz night club)

==============================

super function is basically calling the parent , to do something.

for instance:

mommy can I have an ice cream?
mommy: gives an ice cream

mommy, can you do my homework please?
mommy: receives the homework and do it for you.

ayumilove September 17, 2010 at 12:55 pm

There are much more a super can do,

Google on super for as3 on their uses if you are excited on what it does

Xadjim September 17, 2010 at 2:19 pm

Thanks for your answers :) but why didnt we used a funktion like “movedownabit” in gameoverscreen… so that when we touch an enemie that the gameOver.ShowGameover(); start? was it because of the restart function?

anyway:
When i use playScreen=null; nothing actually happens…eventlisteners keep doing and enemies in playScreen keep coming

Dan September 17, 2010 at 7:00 pm

@Xadjim

Logically, it doesn’t make sense to have moveDownABit() in the GameOverScreen. Enemies move downward, not game over screens =). Anyway, GameOverScreen isn’t created until something happens between Avatar and Enemy, and the AvoiderGame class keeps track of those objects.

Sort of like a soccer/football match, think of AvoiderGame as the referee, the one who makes the rules and oversees the field. He knows when Enemy has touched Avatar and calls GameOverScreen.

For your other problem, did you call gameTimer.stop() when it’s game over?

Xadjim September 18, 2010 at 1:04 am

@Dan
I know that gameoverscreens dont move down :D but i meant like not exactly the same :D

i mean a function in gameOverScreen which starts wenn we touch an enemy and shows gameover and restartbutton instead of Y++ or something… you know what i mean?

anyway: those playScreen=null things dont reset everything for me… you maybe know why? if someone of you have facebook may i pls add you? so i can show you my game (and sourcecode) and you maybe tell me what i did wrong?

Xadjim September 19, 2010 at 12:56 am

lol i finally got what Super(); does.. it calls the constructor of the extended class … if i extend event … it calls the constructor of the event class…. but what does the constructor do?

and why do we need it?

and why did he code this:
public static const RESTART:String = “restart”;

    public function NavigationEvent( type:String )

{}

i mean he creates a new string variable and fill it with “restart”
than he makes the constructor wich expects a String variable and saves it in type..
but why and when do we give him the expected string he is waiting for?

hope someone can help me soon :( i really wanna understand this

pls someone heeelp :’(

Dan September 20, 2010 at 6:49 pm

@Xadjim

The Event constructor allows use of…well, Event. You can read more about it Adobe’s LiveDocs.

We’ve created our own event called NavigationEvent; it by itself does nothing. Extending the class is sort of like saying, “I’m going to have a son, but he hasn’t been born yet.” Calling super() fills in NavigationEvent with Event, thus the son is born and can now assume the father’s duties, very loosely speaking.

The string is for specifying the type of event being invoked. Recall this line in NavigationEvent:

public static const RESTART:String = "restart";

NavigationEvent.RESTART refers to “restart”. Also recall this line in DocumentClass:

gameOverScreen.addEventListener(NavigationEvent.RESTART, onRequestStart);

The first parameter is listening for “restart”, so that it’ll call the method to restart the game.

As for why NavigationEvent takes a String, the Event class takes a String as well. You may have noticed constants like “MouseEvent.CLICK”; these are all strings that Event recognizes and handles appropriately. In NavigationEvent we had to define our own constants and handle them too.

Xadjim September 21, 2010 at 12:41 am

ah thanks Dan and it dasnt matter if we write “restart” or “RESTART” because that confused me… in the one side we wrote “death” and than XYZ.DEATH… one time with Capitalletters and one time without

nice and this super function really seems super to me because the consructer of events seems like it can handle everything.. i still dont get what it is doing and why we need to super() the eventconstructor….is this to define the restard/death thing actually tog et an real event? like CLICK?

Dan September 26, 2010 at 7:34 pm

@Xadjim

It may be easier to try something simple rather than understand something as complex as the Event class at this time. I suggest reading the next part, Part 5 in this series. Michael’s tutorial continues with more super() examples, where you’ll have Score extend a Counter class. From there, you can have things like Lives, Coins, Energy, etc. You’ll see that super() fills in child classes with something they all have in common; in this case, something to count.

Xadjim October 3, 2010 at 7:21 pm

Thanks dan for your help…. i will download his pack for the next part ( coz the super think somehow destroyed my actuall game) :D and keep learnin from his tut :D thanks a lot for your help

Michael Williams October 5, 2010 at 1:12 am

I’m back from holiday!

Really cool to see the discussion on super() and event dispatching :)

Dan and ayumilove, both your explanations were great! I may start using those metaphors in the future ;)

Enkuro October 17, 2010 at 12:48 am

I keep getting an undefined error whenever I add the code:

gameOverScreen.addEventListener( NavigationEvent.RESTART, onRequestRestart );

It’s really annoying me. The game works when I take that out (apart from being able to restart). I’m pretty sure it’s defined.

Nacho October 18, 2010 at 4:46 am

I am obviously doing something wrong, I followed the tutorial thoroughly, I do not get any errors froms flash whatsoever, and I checked the code multiple times, however, I seem to get “false game overs” randomly at some points.
Let me try to make it more clear:
When my game starts the Menu Screen Works just fine.
The actual game starts wonderfully, and the character dies the way its supposed to.
When the Game Over Screen appears, I can press the restart button and continue playing just fine.
At this point, however, the game starts going crazy randomly: Sometimes it will work OK, buy once in a while my character will die for absolutely no reason at all, and I’ll get a Game Over screen.

I understand that this is probably confusing, and the fact that I can’t point out to you in which class the mistake may be probably makes it even more complicated to you, but I could really use some help.

Thanks a lot for your awsome tutorials! Thanks beforehand, and forgive my crappy English, I’m not a native speaker.

Nacho October 18, 2010 at 4:51 am

Wow, I found the mistake about five seconds later, I feel really stupid, I was adding a second playScreen along with the initial MenuScreen.

Thanks anyway =)
Feel free to delete my useless comment should you want to =P

Paul December 2, 2010 at 5:41 am

Hey,
I’m on the part with making the restart button work (right before Hobson’s Choice) and my game works until I die, then I get this output…

TypeError: Error #1010: A term is undefined and has no properties.
at GameOverScreen()
at AvoiderGame/onTick()
at flash.utils::Timer/_timerDispatch()
at flash.utils::Timer/tick()

Any idea as to what’s causing it?
Thanks for the tutorials, they’re extremely helpful and I’m learning alot. Keep up the good work!

Mike January 19, 2011 at 4:25 am

I’m trying to make a button during the game but the timer is causing it to only work for one tick, then the button goes back to the UP frame and doesn’t work, even though I’m still over it. Any Help?

StevenJ February 10, 2011 at 4:38 am

If anyone’s having the error “1120: Access of undefined property startButton”, remember that if you’re duplicating or even making a new Start button, you need to give it an instance name in the Properties WINDOW, and not just as part of the “export as actionscript” dialog box thingy. (I mean you need to use the box that when blank says “”

Yuval February 26, 2011 at 9:35 pm

Morgan, even thou your message is very old, I will tell you what you did wrong: You added a semi-colon after the function name.
public function DocumentClass();

This is really a very amazing tutorial, it makes moving from as2 to as3 a breeze, but I don’t understand why you made a separate start and restart functions/events, the restart is basically a game start.

wYke April 7, 2011 at 8:42 pm

Hey, when using Flash CS5, can’t have instance name

So what I did was:

package 
{
    import flash.display.MovieClip;
    import flash.display.SimpleButton;
    import flash.events.MouseEvent;

public class GameOverScreen extends MovieClip 
{
    public var restartButton:RestartButton;

public function GameOverScreen() 
{
    restartButton = new RestartButton();
    restartButton.addEventListener( MouseEvent.CLICK, onClickRestart );
}

public function onClickRestart( mouseEvent:MouseEvent ):void 
{

}

}

}

But not sure if it’s the same thing. I tried opening the source file from this tutorial 4 and open in Flash CS5, but there’s no similar code like above and there’s no instance name in the RestartButton property. What’s going on actually?

Dodoy April 9, 2011 at 10:55 am

so far so good ive no problem at this tutor thx alot..

Eva May 24, 2011 at 10:55 am

Hey guys!
I have a problem, when the game starts, the menuScreen becomes the background image, and when i push the restart button and the game restarts the gameOverScreen stays in the background!

What to do to change this?

Alan May 28, 2011 at 10:44 am

So this is how as3 class works. working through this exsample of code has answered a mass of questions (it may have created a load more), but you have my thanks anyway

Q Smith June 2, 2011 at 12:30 am

NOTE!!!!!!!!!!!!!

If you are using Flash CS5.5, you must use the following code, not what he said.

package 
{
    import flash.display.MovieClip;
    import flash.display.SimpleButton;
    import flash.events.MouseEvent;

public class GameOverScreen extends MovieClip
{

public var ResetButton:resetButton;

public function GameOverScreen()
{
    ResetButton = new resetButton();
    trace("Game over screen");
    ResetButton.addEventListener(MouseEvent.CLICK, onClickRestart);
    trace("WTF");
    ResetButton.x = 265.05;
    ResetButton.y = 430.3;
    addChild(ResetButton);
}

public function onClickRestart(mouseEvent:MouseEvent):void
{
    trace("clicked Restart");
    dispatchEvent(new NavigationEvent(NavigationEvent.RESTART));
}

}

}

Q Smith June 2, 2011 at 12:32 am

A: Don’t know why the formatting is so weird.

B. the class for my button is resetButton

C. The position is where I decided it should go (my screen is 550×550).

D: Later on, you’ll have to account for this in garbage collection (probably can do it in onClickRestart or wherever you account for gameOverScreen.

Q Smith June 2, 2011 at 12:39 am

You need to account for it in onClickRestart as it isn’t accessible in DocumentClass.as

Also, the trace(“WTF”) and whatnot just print to the console so you can see where in the code you have gone. If you plan on programming, learn to love it.

P.S. Sorry for the spam posting. Took me almost an hour to figure that crap out, figured I’d save someone else the trouble (assuming they read the comments.

Q Smith June 3, 2011 at 5:03 pm

Have to do the same thing for the START button on the startScreen.

jerry June 29, 2011 at 6:07 pm

i had a few compiler errors in document class, fixed them and now this shows up in the output tab when i test it.
i swapped my document class with the one provided in the .zip but i still get this error.

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

Fireball916 July 29, 2011 at 2:41 am

AvoiderGame-EAP\Classes\MenuScreen.as, Line 11 1061: Call to a possibly undefined method addEventListener through a reference with static type Class.

Can’t figure out what to do…. >=/

Timor August 31, 2011 at 4:47 pm

Hey. Thanks for the great tutorail.
i tried to make a Back button but i get an error :

Implicit coercion of a value of type Class to an unrelated type Function.
public function onAvatarDeath( avatarEvent:AvatarEvent ):void
        {
            gameOverScreen = new GameOverScreen();
            gameOverScreen.addEventListener( NavigationEvent.RESTART, onRequestRestart );
            gameOverScreen.x = 0;
            gameOverScreen.y = 0;
            addChild( gameOverScreen );
            gameOverScreen.addEventListener(NavigationEvent.BACK, backToMenu)
            playScreen = null;
        }
        public function backToMenu(navagationEvent:NavigationEvent):void
        {
            DocumentClass();
        }

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

{ 2 trackbacks }

Previous post:

Next post: