Learn ActionScript 3 by Following this Simple Avoider Game Tutorial

by Michael James Williams on September 17, 2008 · 385 comments

in Avoider Game Base,Tutorial

(This tutorial is also available in Spanish, Polish, Italian, French, Turkish, and Russian. I’ve also started re-writing it for HTML5.)

This tutorial’s getting a little old now. It still works, but if you want a more up-to-date guide to learning Flash, I recommend reading my post How to Learn Flash and AS3 for Game Development.

Introduction

A lot of Flash developers find the jump from ActionScript 2 to ActionScript 3 very daunting. Conversely, a lot of programmers of other languages find ActionScript 3 quite intuitive, but hate ActionScript 2! This tutorial does not require you to know AS2, or even have used Flash before. You’ll find it easier if you already know the basics of some programming language, like variables, if statements, loops, and functions, but don’t worry if that’s not the case. I will be pointing out some of the major differences between AS2 and AS3 for the benefit of those Flash developers making the switch, but I’m not going to focus on these changes.

Frozen Haddock has been kind enough to let me rewrite his ActionScript 2 Avoiding Game Tutorial in ActionScript 3. Thanks, Frozen Haddock! This is not a direct port of his tutorial, however. I’ll be redesigning the code to follow good AS3 practices, which means:

  • One frame
  • One layer
  • No items on the Stage
  • No code in the timeline
  • No code in any symbols

(If you’ve never used Flash to create a game before, the above will probably mean nothing to you. Trust me, that’s a good thing!)

These rules might have to be bent a little when it comes to adding a preloader. We’ll cross that bridge when we come to it.

We’ll also be using classes and events and OOP and all sorts of nice programmer things. But I’m getting ahead of myself. In this part of the tutorial, we’ll just be setting everything up and putting in some very basic game mechanics. To see just how basic, check it out by clicking the image below:

click here to see what we'll be working towards

And by the end of this 12-part tutorial, it’ll look like this, with keyboard controls, multiple levels, sounds, and more:

screenshot

Setup

Let’s start off simple. Boot up your copy of Adobe Flash CS3 (or later, if you’re reading this from the future) and select File > New > Flash File (ActionScript 3.0).

Click File > Save and create a new folder somewhere where you can store all the game’s files. I recommend using your name or initials in the folder’s name as this will make it easier to share with other people later. For reference, I’m calling mine AvoiderGame-MJW. Create a new folder, inside this folder, called Classes. Finally, enter a name for your FLA file (I used AvoiderGame-MJW.fla) and save it — in the main folder, not the Classes folder.

screenshot

There are some default settings we need to alter before we can start on the game proper. Click File > Publish Settings. Click the Flash tab, if it’s not already selected, then click the Settings button next to the ActionScript Version drop-down list:

screenshot

Click the little plus icon above the Classpaths box, and type ./Classes/ in the textbox that appears. This tells Flash that we are going to store the code that we write in the Classes folder we made earlier, so it should check in there if it can’t find any code that it needs.

screenshot

Also, tick the box marked, “Automatically declare stage instances”, if it’s not already ticked.

Next we’ll alter the properties of the game itself. Click Modify > Document and set it up however you like. Frozen Haddock gave his a size of 300 by 300 pixels, and a grey background. I’ve stuck with the grey, but gone for the oldschool-TV-ratio dimensions of 400 by 300 pixels. You can always change this later, so don’t fret too much over it. I do recommend sticking with a frame rate of 24 fps, though. Here’s what I did:

screenshot

OK, that’s the dull setup out of the way. Let’s create our enemy!

Creating the Enemy

The enemy is the object that you, as a player, will have to avoid. (Hence, Avoider Game.) Let’s draw it before giving it life. Click Insert > New Symbol and in the box that appears, give it a Name of Enemy (with a capital E!) and a Type of Movie Clip (in case we want to animate it later). Click OK. The Library will now show your new Enemy object:

screenshot

If you can’t see a Library, make sure Window > Library is checked. By default you will be automatically editing the Enemy — you can tell what you’re editing by the bar over the editing window:

screenshot

If you’re not editing the Enemy for some reason, just double-click it in the Library (or right-click it and select Edit). Draw your Enemy. Frozen Haddock picked a smiley face for his bad guy. Who knows why? Maybe it’s got something to do with those blasted banner adverts. I’m going to do the same. You can make anything you want, but I’m going to assume that we’re all using a roughly circular Enemy, so bear in mind that if you draw a stickman, some parts of this tutorial won’t apply to you. Also, if you’re not used to the Flash drawing environment, it can be a little unintuitive. I recommend this quick drawing tutorial if that applies to you. Here’s my guy:

screenshot screenshot screenshot screenshot

Pretty awesome. There’s a bit of a problem though. You see that little black crosshair with the white background? That’s called the registration point, and when we start writing code to say, “put the Enemy at such-and-such a position”, it’s this point that Flash is going to actually place at that position. (It’s hard to explain in words; later on this will become much clearer.) For this reason, I’m going to move the face around so that the registration point is dead centre. Here’s how to do it:

First, make sure you’re editing your Enemy, and then select everything (click Edit > Select All). A crosshatch pattern will appear:

screenshot

Now, group everything together by clicking Modify > Group Together. A blue box will appear. If you now click and drag anything inside that box, the entire enemy will move as one. (If you had tried this before, you would have ended up dragging his eye out.)

screenshot

Go to the Align panel. If you can’t see it, make sure Window > Align is checked. With the Enemy still selected (i.e., with the blue box still around it), make sure the To stage button is in, and click the two central Align buttons:

screenshot

Now that we’ve finished with the Enemy’s design, we can get out of editing mode. Click Scene 1 on the bar above the editing box. This would be a great time to save our work, so hit File > Save.

The Enemy’s Instructions

So far, nothing we’ve done has been significantly different from what we would have done in any previous version of Flash. That’s about to change. It’s time to start writing code to control the Enemy’s behaviour. As I mentioned at the start, this code is not going to go in either the timeline or the Actions of the Enemy symbol. Instead, it’s going to be kept in an external file. There are a number of benefits to this:

  • The code is completely separate from the artwork, so you can give your artist the FLA file without having to give them the source code.
  • Likewise, you can give a programmer parts of the code without having to send them all your artwork and sounds — or even the rest of the code.
  • If you have a number of programmers each working on separate parts of the code, it’s much easier to put it all back together later.

Click File > New and select ActionScript File. A blank text-editing window will appear. Immediately save the file, as Enemy.as, in the Classes folder you created earlier. This file is going to contain the class — a programming template — for our antagonistic smiley faces.

It’s around this point in an AS3 tutorial that most AS2 programmers start to complain about how much harder it is to use AS3, because there’s so much more that has to be written just to get an object to do something. Please bear with me, and you will see that, although there are indeed more lines of code needed to set this up, they aren’t very difficult to understand, and the approach we take in writing them will really pay off in the long run.

Begin by typing the following:

?View Code ACTIONSCRIPT3
1
2
3
4
package 
{
 
}

The package keyword simply says that everything between the next pair of curly braces is part of a single… well, package. In this case, everything in this package concerns the Enemy object.

As part of this package (so, between the curly brackets), we need to define the Enemy’s class — the template that specifies what it can do, and what we can do with it:

?View Code ACTIONSCRIPT3
1
2
3
4
5
6
7
package 
{
	public class Enemy extends MovieClip 
	{
 
	}
}

Let’s examine this bit by bit:

  • class Enemy — “everything between the next pair of curly brackets makes up the Enemy class.”
  • public — “this class can be accessed by any other piece of code that knows about it.” The alternative would be internal, meaning that only code inside the same package could access this class.
  • extends MovieClip — “I can do anything a MovieClip class can do — and more besides.” So, for example, since we can write code that makes a MovieClip move to the next frame of its animation, we can do the same with an Enemy (or at least we could, if it contained more than one frame). On top of that, we can give this Enemy an HP count (say) which a MovieClip doesn’t have, thus extending the functionality.

The thing is, even though MovieClip is such an important and frequently-used class of object, Flash still has to be told where it is. So, we write in line 3, below:

?View Code ACTIONSCRIPT3
1
2
3
4
5
6
7
8
package 
{
	import flash.display.MovieClip;
	public class Enemy extends MovieClip 
	{
 
	}
}

Finally, the Enemy class needs what’s known as a constructor function. This is just a function that runs whenever a new Enemy is created. All constructor functions must have the same name as the class they belong to, so:

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

There’s that word public again. Note that the Enemy function has an empty pair of parenthesis directly after it; more on that later.

So now we have our Enemy class set up, we need to link it to our Enemy graphic. Save the AS file and go back to the FLA file (it’ll be on the tab bar at the top of the window, or in the Window menu, assuming you haven’t closed it). Right click the Enemy in the Library, and select Properties. Click the Advanced button, if it’s there, to show the Linkage panel. Check the Export for ActionScript box, and make sure that the Class reads “Enemy”. If everything’s linked up fine, then clicking the little pencil icon should open up the Enemy class that we were just working on.

screenshot

Click OK to close the Properties box.

Now we need to code in the Enemy’s actual behaviour. What does it need to do? At this point, all we need it to do is:

  • Appear above the top of the screen when it’s created
  • Keep moving downward from that time onward

We already have a space to put code that needs to execute upon the creation of the Enemy — the constructor function. So:

?View Code ACTIONSCRIPT3
1
2
3
4
5
6
7
8
9
10
11
12
package
{
	import flash.display.MovieClip;
	public class Enemy extends MovieClip
	{
		public function Enemy()
		{
			x = 100;
			y = 0;			
		}
	}
}

Since MovieClips have x and y properties, so does our Enemy class.

Those of you familiar with Cartesian coordinates are probably saying, “whoa, Michael! I thought we wanted the Enemy to appear at the top of the screen, but you’ve set the y-coordinate to zero, which is surely the bottom.” I’m afraid that Flash is weird in that respect: y increases as you go down the screen. For my 400 by 300 pixel stage, the coordinates look like this:

screenshot

You get used to it.

I’m going to handle the movement by having something else tell the Enemy to move downward, just a little bit, every split-second. We need to add this movement functionality to the Enemy class, since MovieClips don’t already have something that can do that, so let’s create a new function:

?View Code ACTIONSCRIPT3
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package 
{
	import flash.display.MovieClip;
	public class Enemy extends MovieClip 
	{
		public function Enemy() 
		{
			x = 100;
			y = 0;			
		}
 
		public function moveDownABit():void 
		{
			y = y + 3;
		}
	}
}

Let’s break this down again:

  • function moveDownABit() — everything between the following pair of curly brackets makes up a function called moveDownABit. Again, we have that empty pair of parenthesis after the function name.
  • public — another part of the game is going to actually run this function, so it needs to be public.
  • :void — this function does not return any feedback. Don’t dwell on this; I’ll explain it when we make a function that does return something.
  • y = y + 3; — increase the y-coordinate of the Enemy by 3 pixels (remember, this will move the enemy downwards, not upwards).

Making an Enemy

Save your Enemy.as file and go back to the FLA file. Our next step is to get an actual enemy into the game; up till now we’ve just been dealing with a template of an Enemy, not an actual enemy itself. It’s like we’ve been working on a blueprint, and now we need to use that blueprint to build an actual, physical house.

It’s important to remember that Flash started off as a tool for creating animating movies. Even though it’s developed a lot since then, Flash still considers everything you create with it to be a MovieClip. As we know, MovieClips have a constructor function that runs when they’re created, and therefore so does your game. We’re going to extend this function to make it create an Enemy within the game when the game is started. But how do we access the game’s constructor? If you said, “another AS file,” you’re correct.

Create a new AS file, and save it in the Classes folder with the name AvoiderGame.as. Add these lines to the file, and save it:

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

Look familiar? Apart from the names of the class and the constructor, it’s exactly the same as our Enemy AS file started out. Let’s link it to our FLA file.

Move back to the FLA file and make sure you’re not still editing the Enemy. Find the Properties panel — if you can’t see it, make sure Window > Properties > Properties is checked. There’s a box marked Document class; enter AvoiderGame. It’s important to use capital letters in the right places here — since we’ve called the file AvoiderGame.as and the class within the file AvoiderGame, we have to follow suit with the name of the document class. Clicking the little pencil icon should bring up the AvoiderGame class file.

screenshot

Great, so now we can edit the actual game’s constructor to make it create an enemy at startup:

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

Watch your capitalisation here! Enemy with a capital E is the class file that defines features common to all Enemies; enemy with a small e is a specific example — an “instance” — of an Enemy. It’s like, Person is a class, but I am an instance of that class, and you are another instance of that class.

At the minute, this instance, enemy, of Enemy is only available to the constructor function, because it is first referred to within that function. We need it to be available throughout the entire game, so add this line of code (line 6):

?View Code ACTIONSCRIPT3
1
2
3
4
5
6
7
8
9
10
11
12
13
package 
{
	import flash.display.MovieClip;
	public class AvoiderGame extends MovieClip 
	{
		public var enemy:Enemy;
 
		public function AvoiderGame() 
		{
			enemy = new Enemy();
		}
	}
}
  • public — you know what this means.
  • var — “the following is a new variable that I am defining.”
  • enemy:Enemy — “the variable is called enemy, and it is an instance of the Enemy class.”

Since the enemy variable is defined within the AvoiderGame class, it’ll be available throughout the class.

So now we’ve created an enemy, but it’s just sort of floating about in the aether. We need to tie it down to the actual game:

?View Code ACTIONSCRIPT3
8
9
10
11
12
		public function AvoiderGame() 
		{
			enemy = new Enemy();
			addChild( enemy );
		}

Here’s a new function: addChild(). We use this to make objects actually appear on-screen. Any object that is “addChild()-ed” to the document class (remember, the AvoiderGame class is our document class) will appear on-screen — well, as long as its x- and y-coordinates are inside the rectangle that make up the screen!

We say that the enemy is now a child of the AvoiderGame class, and that the AvoiderGame class is the enemy’s parent. An object can only have one parent, but it can have as many children as you like.

At last, we can run the game and expect some results! Save everything, then hit Control > Test Movie. You’ll get something like this:

screenshot

Hooray! Only… we want all of the enemy to start above the window, not just half of it. What Flash has done is position the enemy so that its registration point is positioned at the point (100,0). We could move the registration point to the bottom of the enemy, but I think that’s a sloppy solution. Instead, let’s just change the enemy’s starting y-position; alter the constructor in the Enemy.as file like so:

?View Code ACTIONSCRIPT3
6
7
8
9
10
		public function Enemy() 
		{
			x = 100;
			y = -15;
		}

You’ll need to alter that y-value depending on the height of your Enemy (mine’s 30 pixels tall).

Bringing the Enemy to Life

Although we’ve built in some functionality to let the enemy move downwards, we haven’t written any code that actually tells the enemy to do so. Let’s do that next.

The basic idea, as I outlined above, is to have the game tell the enemy to move a few pixels down every split-second. Frozen Haddock’s tutorial used a couple of neat methods for achieving this, but we don’t need to use either of those, because AS3 has a new solution: the Timer class that does it all for us.

Edit the game’s constructor function to create a new instance, gameTimer, of the Timer class. This is a built-in class, so you don’t need to create a new AS file; just edit AvoiderGame.as like so::

?View Code ACTIONSCRIPT3
8
9
10
11
12
13
14
		public function AvoiderGame() 
		{
			enemy = new Enemy();
			addChild( enemy );
 
			gameTimer = new Timer( 25 );
		}

Note that this time the parenthesis after the class name are not empty. That number 25 says that we want to set the interval of the timer to 25ms (milliseconds; 1000ms = 1 second), i.e., we want it to do something every 25ms.

We want this gameTimer to last throughout the game, of course, so we need to make it available to the entire class (line 7):

?View Code ACTIONSCRIPT3
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package 
{
	import flash.display.MovieClip;
	public class AvoiderGame extends MovieClip 
	{
		public var enemy:Enemy;
		public var gameTimer:Timer;
 
		public function AvoiderGame() 
		{
			enemy = new Enemy();
			addChild( enemy );
 
			gameTimer = new Timer( 25 );
		}
	}
}

…and Timer is like MovieClip, in that Flash has to be told about it before we can use it (line 4):

?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.utils.Timer;
 
	public class AvoiderGame extends MovieClip 
	{
		public var enemy:Enemy;
		public var gameTimer:Timer;
 
		public function AvoiderGame() 
		{
			enemy = new Enemy();
			addChild( enemy );
 
			gameTimer = new Timer( 25 );
		}
	}
}

(By the way, don’t worry about how I know that it’s flash.utils.Timer and flash.display.MovieClip; I looked it up.)

All right, so we have a Timer that goes off every 25ms. But at the minute it’s not connected to anything; it’s not telling the enemy to move down the screen. So, add the following (line 17) to your game’s constructor:

?View Code ACTIONSCRIPT3
11
12
13
14
15
16
17
18
		public function AvoiderGame() 
		{
			enemy = new Enemy();
			addChild( enemy );
 
			gameTimer = new Timer( 25 );
			gameTimer.addEventListener( TimerEvent.TIMER, moveEnemy );
		}
  • gameTimer.addEventListener — “apply an event listener to the gameTimer with the following parameters.” 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. In this case, the event is…
  • TimerEvent.TIMER — this event goes off every time a Timer completes an interval; in our case, this event will be triggered every 25ms, because that is the interval of the gameTimer.
  • moveEnemy — this is the function that’s going to be run every time the TimerEvent occurs. We haven’t written this function yet; we’ll get to that in a minute.

TimerEvent is yet another thing that Flash has to be told about, so import it at the top (line 5):

?View Code ACTIONSCRIPT3
1
2
3
4
5
package 
{
	import flash.display.MovieClip;
	import flash.utils.Timer;
	import flash.events.TimerEvent;

Now we need to write that moveEnemy function that’ll actually be run every 25ms (lines 21-24):

?View Code ACTIONSCRIPT3
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
	public class AvoiderGame extends MovieClip 
	{
		public var enemy:Enemy;
		public var gameTimer:Timer;
 
		public function AvoiderGame() 
		{
			enemy = new Enemy();
			addChild( enemy );
 
			gameTimer = new Timer( 25 );
			gameTimer.addEventListener( TimerEvent.TIMER, moveEnemy );
		}
 
		public function moveEnemy( timerEvent:TimerEvent ):void 
		{
 
		}
	}

Again, we’ve got something inside the parenthesis. This allows the event listener to pass information about the event through to the moveEnemy function, in the form of an instance (timerEvent) of the class TimerEvent. We don’t need to know any of that information, however, so we won’t be referring to it again. Also, there’s void again.

All we have to do now is use this new function to tell the enemy to move. Remember the moveDownABit function we put inside Enemy earlier? Time to make use of it:

?View Code ACTIONSCRIPT3
21
22
23
24
		public function moveEnemy( timerEvent:TimerEvent ):void 
		{
			enemy.moveDownABit();
		}

So this tells the enemy instance to run its moveDownABit function. Save everything, and run the game (Control > Test Movie, remember).

Nothing happens.

We have to tell the gameTimer to start! Go ahead and edit your game’s constructor as below (line 19):

?View Code ACTIONSCRIPT3
12
13
14
15
16
17
18
19
20
		public function AvoiderGame() 
		{
			enemy = new Enemy();
			addChild( enemy );
 
			gameTimer = new Timer( 25 );
			gameTimer.addEventListener( TimerEvent.TIMER, moveEnemy );
			gameTimer.start();
		}

Save everything, and run it again. Success! The enemy is moving downscreen, at a healthy rate of 3 pixels per 25ms (or 120 pixels/second).

Now we need to add some amount of interactivity, otherwise this is just a movie and not a game.

Get your Head in the Game

First we have to make our player’s avatar. In your FLA file, create a new symbol, of type Movie Clip, called Avatar. (Check out the section above on creating the enemy if you can’t remember how to do this.) Draw whatever you want to represent the player. Frozen Haddock defied convention again by picking a skull for his protagonist. I want to get in on some of this action.

screenshot

Don’t feel bad if your drawings aren’t anywhere near as good as mine. After all, I do have a GCSE in graphic design.

Alright, so once you’ve made your Avatar, centred the registration point, got out of editing mode, and saved the FLA, what’s next? You will probably not be surprised to hear that we’re going to create a new AS file for the Avatar. Save it as Avatar.as in the Classes folder, and start editing it:

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

Same old story. Go ahead and link it to the Avatar in the Library.

What is our avatar going to do? At the minute, it’s just going to follow the mouse around the screen — effectively, it’ll be a mouse pointer. We can actually control the avatar’s position from within the AvoiderGame class, so we don’t need to add any more code to the Avatar class right now.

Switch to editing the AvoiderGame.as file, and let’s add an instance of the Avatar class to the game. I’ll put in all the code at once, this time, since it’s pretty much the same as when we did it for the enemy. (The following is in the AvoiderGame.as file) (New code: lines 10, 18, & 19):

?View Code ACTIONSCRIPT3
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
	public class AvoiderGame extends MovieClip 
	{
		public var enemy:Enemy;
		public var avatar:Avatar;
		public var gameTimer:Timer;
 
		public function AvoiderGame() 
		{
			enemy = new Enemy();
			addChild( enemy );
 
			avatar = new Avatar();
			addChild( avatar );
 
			gameTimer = new Timer( 25 );
			gameTimer.addEventListener( TimerEvent.TIMER, moveEnemy );
			gameTimer.start();
		}
 
		public function moveEnemy( timerEvent:TimerEvent ):void 
		{
			enemy.moveDownABit();
		}
	}

If you run the game now, you’ll see that the avatar instance appears in the top left corner of the screen — i.e., at position (0,0). We want it to start off wherever the mouse cursor is. Flash has two properties we can use for this: mouseX, which gives the x-coordinate of the mouse cursor, and mouseY, whose functionality you can probably guess. As mentioned above, anything that extends a MovieClip will have an x and a y property that we can edit. So (lines 20 & 21):

?View Code ACTIONSCRIPT3
13
14
15
16
17
18
19
20
21
22
23
24
25
26
		public function AvoiderGame() 
		{
			enemy = new Enemy();
			addChild( enemy );
 
			avatar = new Avatar();
			addChild( avatar );
			avatar.x = mouseX;
			avatar.y = mouseY;
 
			gameTimer = new Timer( 25 );
			gameTimer.addEventListener( TimerEvent.TIMER, moveEnemy );
			gameTimer.start();
		}

If you run this, the avatar will indeed appear at the mouse cursor (this is easier to see if you use the keyboard shortcut for Test Movie which is Ctrl-Enter on Windows and Command-Enter on Macs). Since we use the gameTimer to alter the enemy’s position every split-second, let’s also use it for the avatar’s position (lines 31 & 32):

?View Code ACTIONSCRIPT3
28
29
30
31
32
33
		public function moveEnemy( timerEvent:TimerEvent ):void 
		{
			enemy.moveDownABit();
			avatar.x = mouseX;
			avatar.y = mouseY;
		}

Oh, wait, moveEnemy isn’t really a suitable name for the function now. How about moveEnemyAndAvatar?

?View Code ACTIONSCRIPT3
28
29
30
31
32
33
		public function moveEnemyAndAvatar( timerEvent:TimerEvent ):void 
		{
			enemy.moveDownABit();
			avatar.x = mouseX;
			avatar.y = mouseY;
		}

We’ll have to update the gameTimer’s event listener to point to this function with its new name, or it’ll get confused:

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

Save and run the game, and bask in the glory of your new, skull-shaped mouse cursor!

screenshot

Putting the “Avoid” in “Avoider Game”

You might have noticed that if you do happen to run your avatar into the enemy… absolutely nothing happens. This isn’t very good for an avoider game, so let’s correct that.

How will we know if the avatar has hit the enemy? MovieClips have a built-in function called hitTestObject which detects whether the MovieClip is touching another specified MovieClip. Naturally our Avatar and Enemy classes have this as well. Since the objects only move when the gameTimer goes off, we should check for a collision in the gameTimer’s event listener’s connected function (lines 34-37):

?View Code ACTIONSCRIPT3
28
29
30
31
32
33
34
35
36
37
38
		public function moveEnemyAndAvatar( timerEvent:TimerEvent ):void 
		{
			enemy.moveDownABit();
			avatar.x = mouseX;
			avatar.y = mouseY;
 
			if ( avatar.hitTestObject( enemy ) ) 
			{
 
			}
		}
  • avatar.hitTestObject( enemy ) — this will return a value of true if the avatar is touching the enemy
  • if — “if the statement between the next pair of parenthesis is true, then run the code between the next pair of curly brackets

At the minute there’s nothing between the curly brackets, so nothing will happen upon a collision. Before we add anything there, we should really change the name of the moveEnemyAndAvatar function, since once again it is no longer accurate. I can see that we’ll be adding more and more to this function in future parts of this tutorial, so let’s not bother with a cumbersome name like moveEnemyAndAvatarAndAlsoCheckToSeeIfTheyHaveCollided. Instead, I’m going to define a new word:

  • Tick — every time the gameTimer goes off, that’ll be called a Tick from now on. Everything that needs to be updated or checked will occur once per Tick.

So now we can rename the function to onTick:

?View Code ACTIONSCRIPT3
28
29
30
31
32
33
34
35
36
37
38
		public function onTick( timerEvent:TimerEvent ):void 
		{
			enemy.moveDownABit();
			avatar.x = mouseX;
			avatar.y = mouseY;
 
			if ( avatar.hitTestObject( enemy ) ) 
			{
 
			}
		}

Don’t forget to change the gameTimer’s event listener to point to the new name. We won’t need to alter it again after this.

Finally, let’s make the game actually do something when the enemy hits the avatar. Since I haven’t covered lives, we haven’t made a game over screen, and there’s no scoring system yet, I’ll take this as an opportunity to show you something.

You know how we had to start the gameTimer before anything happened? Well, add this to your onTick event (line 34):

?View Code ACTIONSCRIPT3
28
29
30
31
32
33
34
35
36
		public function onTick(event:TimerEvent):void {
			enemy.moveDownABit();
			avatar.x=mouseX;
			avatar.y=mouseY;
 
			if (avatar.hitTestObject(enemy)) {
				gameTimer.stop();
			}
		}

Now save and run the game, and see what happens when you run into the enemy. Don’t worry, the game hasn’t crashed; we’re just no longer running any Tick code. Two things we can notice from this:

  1. The collision detection is terrible
  2. A pause feature is going to be very easy to implement later

Wrapping Up

So there’s your very basic Avoider Game. If you want to modify it and give all the code to someone else, just zip up the main folder (mine was called AvoiderGame-MJW, remember) and send it to them. You can download mine from this link. Alternatively, if you just want to give them the game itself, without them being able to edit it, switch to your FLA, select File > Export > Export Movie, give a name to your SWF file, and send that instead.

I realise that what we’ve got so far is very crude, both in terms of code and gameplay. Now that we’ve got the basic framework down, future parts of the tutorial will be able to add more in less time. In the next part, we’ll add multiple enemies, and after that we’ll be adding a clock, and a game over screen, and lives, and a scoring system, and, well, everything that Frozen Haddock’s series has.

Thanks for reading!

Edit: The next part is available!

{ 361 comments… read them below or add one }

Etsuko Umeda January 26, 2013 at 6:31 pm

Hello MIchael ,your tutorial is great !! 
Now I simplified yourprogram “DocumentClass.as” By Flash CS4.

 
package
{   import flash.display.MovieClip;
    import flash.events.Event;
    import flash.events.MouseEvent;
public class DocumentClass extends MovieClip
         {   public var playScreen:AvoiderGame;
    public var gameOverScreen:GameOverScreen;
        public var menuScreen:MenuScreen;
public function DocumentClass(){
    menuScreen = new MenuScreen();
    menuScreen.addEventListener( NavigationEvent.START, onRequestStart );
    menuScreen.x = 0;
    menuScreen.y = 0;
    addChild( menuScreen );}
public function onRequestStart( navigationEvent:NavigationEvent ):void{
                var BackGround:background = new background();
                addChild( BackGround );
    playScreen = new AvoiderGame();
    playScreen.addEventListener( AvatarEvent.DEAD, onAvatarDeath );
    playScreen.x = 0;
    playScreen.y = 0;
    addChild( playScreen );}
public function restartGame(navigationEvent:NavigationEvent):void{
    var BackGround:background = new background();
    addChild( BackGround );
    playScreen = new AvoiderGame();//再び戦場が始まる
    playScreen.addEventListener( AvatarEvent.DEAD, onAvatarDeath ); 
    playScreen.x = 0;
    playScreen.y = 0;
    addChild( playScreen );}
public function onAvatarDeath( avatarEvent:AvatarEvent ):void{
    var finalScore:Number = playScreen.getFinalScore();
    gameOverScreen = new GameOverScreen();
    gameOverScreen.addEventListener( NavigationEvent.RESTART,       restartGame );
    gameOverScreen.x = 0;
    gameOverScreen.y = 0;
    gameOverScreen.setFinalScore( finalScore );
    addChild(gameOverScreen); 
    playScreen = null;}
        }   }

Sen January 30, 2013 at 12:40 pm

hey there !
Thanks to Michael for these great beginner tutorials! I appreciate it. Very useful man!

Ian February 12, 2013 at 3:48 am

It gets a bit confusing since the line numbers aren’t consistent throughout the tutorial.

Hasan March 16, 2013 at 4:44 am

Thanks alot. This is very helpful. I just began learning actionscript and its hard to find written tutorials that explain things in plain english.

Jessany May 8, 2013 at 12:12 pm

I can get the function in the .as files to turn GREEN.. What do I need to do??? So far.. pretty straight forward! ;)

Serrin June 26, 2013 at 11:37 pm

hey :)

firstly great tutorial, very easy to understand, even for a, AS3 noob like me :P
now i dont know if anyone is still checking this every now and then, but if yes, i have a little question.

if you declare a public variable with

“public var enemy:Enemy”

why do you still have to type

“enemy = new Enemy()”

inside the function? couldn’t you just use the enemy instance as it is declared before?

thx a lot if anyone can help me out clearing up my confusion here :)

simplestairlifts.co.uk July 5, 2013 at 9:17 am

The growing demand of stairlifts motivated Acorn to make a number of stairlifts having different utilization and
functionality.

Acorn could be the very first stairlift manufacturer
to come up with DC powered stairlifts.

Rachana July 8, 2013 at 6:13 pm

Hey Michael,
Thanks a lot..i did everything at one go and all credit goes to your simplest tutorial. Even though i am new to it, i manged pretty well.
Hope to have your such great guidance throughout my gaming career.

Kassie Brown August 13, 2013 at 12:09 pm

Hi, so how would you go about making this 2 player?

Erin August 14, 2013 at 2:56 am

GREAT tutorial but I keep running into an issue – I’ve even downloaded your code to look at it and I can’t find any difference. Maybe you could help…it says that I have a “Warning 1106: Empty statement found where block of code expected” on line 34 but I can’t seem to find any issue?
Here’s the code I have:

public function onTick( timerEvent:TimerEvent ):void
        {
            enemy.moveDownABit();
            avatar.x = mouseX;
            avatar.y = mouseY;

        if ( avatar.hitTestObject( enemy ) )
        {
            gameTimer.stop();
        }
    }
}

}

Maxwell August 26, 2013 at 12:36 pm

I have a problem, im using cs6, and i’ve done everything up until where i try to link the AS file with the symbol for the enemy, the name is correct, but it keeps saying that a defenition for the class could not be found in the classpath… Im not sure what i’ve done wrong here

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

{ 24 trackbacks }

Previous post:

Next post: