
Photo by adselwood.
HP. Lives. Mans. Credits. 1-UPs. All ways of giving the player an extra chance to play, rather than ending the game after a single mistake. These are also ways of rewarding the player for obtaining a certain number of points, reaching a particularly tricky spot, or inserting another coin.
As before, FrozenHaddock was way ahead of me in adding this feature to his game. Let’s play catch-up, and look at different ways of measuring health.
Click the image below to try the game out:
As usual, if you followed the AS3 Avoider Game Tutorial you should be able to fit this into your game, even if you’ve made improvements. I’m going to base this tutorial on the game you end up with after completing the base tutorial. If you didn’t follow the tutorial, you can follow along with me using the files in this zip file, here.
Whatever you’re using, open the FLA, and let’s get started.
Three Strikes, You’re Out
So at the minute, the game goes straight to the game over screen as soon as the avatar hits an enemy. A simple lives system changes this so that, when the avatar hits an enemy:
- If the player has at least one life left, he loses one life
- Otherwise, Game Over.
Wording it like this makes it fairly obvious what we’ve got to change. Open AvoiderGame.as, and find the piece of code that deals with an enemy hitting the avatar:
179 180 181 182 183 | if ( avatarHasBeenHit ) { bgmSoundChannel.stop(); dispatchEvent( new AvatarEvent( AvatarEvent.DEAD ) ); } |
Based on our simple pair of rules (above), it’s easy to rewrite this:
179 180 181 182 183 184 185 186 187 188 189 190 | if ( avatarHasBeenHit ) { if ( playerLives > 0 ) { playerLives = playerLives - 1; } else { bgmSoundChannel.stop(); dispatchEvent( new AvatarEvent( AvatarEvent.DEAD ) ); } } |
Of course, we’ll need to create this new variable playerLives. Make it a class-wide variable of type int. (An int is just a whole number, i.e. it has no fractions and no decimal point.)
12 13 14 | public class AvoiderGame extends MovieClip { public var playerLives:int; |
We need to give this a value, so do that in the constructor:
33 34 35 | public function AvoiderGame() { playerLives = 3; |
I’ve picked three lives — for some reason, this is a fairly common number. Test this change and you’ll find that when you touch an enemy, whoops, the game freezes.
That’s my fault; I forgot we stopped the tick timer as soon as the avatar touched an enemy, rather than when we checked what to do. To fix this, we just need to move the line gameTimer.stop(); from here:
169 170 171 172 173 | if ( PixelPerfectCollisionDetection.isColliding( avatar, enemy, this, true ) ) { gameTimer.stop(); avatarHasBeenHit = true; } |
…to the piece of code we were editing earlier:
180 181 182 183 184 185 186 187 188 189 190 191 192 | if ( avatarHasBeenHit ) { if ( playerLives > 0 ) { playerLives = playerLives - 1; } else { gameTimer.stop(); bgmSoundChannel.stop(); dispatchEvent( new AvatarEvent( AvatarEvent.DEAD ) ); } } |
If we test this out now, we’ll find that, er… it doesn’t seem to work. We get Game Over as soon as we touch an enemy:
What’s going on? We need a better look. It’s time for a visual approach.
Counter, Our Old Friend
Remember the Counter class? Both the Clock and Score classes extend it to keep track of their internal numbers. Let’s create a lives counter.
So, first create a new symbol of type Movie Clip. Call it Lives and export it for ActionScript. Put a dynamic text field inside, with an instance name of livesDisplay. You can decorate it as well, if you like:

Now create a new AS file, and save it as Lives.as in your Classes folder. The code is almost identical to that for the Score class, so I’ll just paste it here:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | package { import flash.text.TextField; public class Lives extends Counter { public var livesDisplay:TextField; public function Lives() { super(); } override public function updateDisplay():void { super.updateDisplay(); livesDisplay.text = currentValue.toString(); } } } |
There’s the basic code, now we have to connect this to the play screen. Open the PlayScreen symbol and drag in an instance of Lives from the Library.

Give this an instance name of gameLives.
Now, because we turned off “Automatically declare stage instances” back in Part 12, we need to declare this object as a class-wide variable in AvoiderGame.as:
12 13 14 | public class AvoiderGame extends MovieClip { public var gameLives:Lives; |
…and now we can tie this in to our existing code, based around playerLives, without much of a change:
34 35 36 37 | public function AvoiderGame() { playerLives = 3; gameLives.setValue( playerLives ); |
182 183 184 185 186 187 188 189 190 191 192 193 194 195 | if ( avatarHasBeenHit ) { if ( playerLives > 0 ) { playerLives = playerLives - 1; gameLives.setValue( playerLives ); } else { gameTimer.stop(); bgmSoundChannel.stop(); dispatchEvent( new AvatarEvent( AvatarEvent.DEAD ) ); } } |
Notice here that we’re not removing the playerLives variable and replacing it with this new gameLives, we’re merely using gameLives to represent the playerLives value. Why? Well, it lets us separate the internal values with the external display of those values. If we wanted, we could add a second display object to show the number of lives in a different way. It’s up to you, as the programmer, to decide whether this is worth it.
Anyway, run the game:
We certainly start with three lives, but as soon as we hit an enemy this very rapidly counts down to zero. Let’s experiment by setting the initial number of lives to 99 (do this in the AvoiderGame constructor function):
Now it’s easy to see the source of the problem (apologies to anyone reading that understood this several paragraphs ago
). The player doesn’t lose a life just at the point they touch an enemy; they lose a life for every tick during which they are touching an enemy!
We could leave the game like this, change the display from a number to a health bar, and let the number of “lives” (HP, really) increase every tick the player wasn’t touching an enemy. Feel free to do that, if it suits your game. However, I’m going to go with the FrozenHaddock design of making the enemy disappear once it touches the avatar, taking one of the player’s lives with it.
An Eye For An Eye
This isn’t actually going to require much of a change to our code. Take a look through and see if you can figure out what’s going to need to change before reading on.
The answer lies in this part:
167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 | while ( i > -1 ) { enemy = army[i]; enemy.moveABit(); if ( PixelPerfectCollisionDetection.isColliding( avatar, enemy, this, true ) ) { avatarHasBeenHit = true; } if ( enemy.y > 350 ) { removeChild( enemy ); army.splice( i, 1 ); } i = i - 1; } |
All we need to do is remove the enemy at the point it hits the avatar. Our existing code will take care of the rest. The simplest way of doing this is like so:
167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 | while ( i > -1 ) { enemy = army[i]; enemy.moveABit(); if ( PixelPerfectCollisionDetection.isColliding( avatar, enemy, this, true ) ) { avatarHasBeenHit = true; removeChild( enemy ); army.splice( i, 1 ); } if ( enemy.y > 350 ) { removeChild( enemy ); army.splice( i, 1 ); } i = i - 1; } |
The new lines here are 174-175. Hopefully you’re biting your lip at the sight of duplicate code at lines 179-180 — if so, you’re right to whimper. Really, we should avoid such duplication. I shall leave it up to you to clean up this small mess I have created
Time to test!
Oops, I forgot to change the number of lives back to three. Well, never mind; it actually plays pretty well like this, I think. As always, you should adjust this to fit your game.
Challenges
You won’t be surprised to hear me suggest adding sound effects to accompany a lost life. And I already mentioned the idea of changing the lives counter to a health bar, like in beat-em-up games. What else can we do with this?
Well, for a start, you could combine lives AND a health bar: run out of HP and you lose a life. HP automatically regenerates; lives don’t. Frantic uses a system like this.
We don’t have any way of rewarding the player with an extra life right now. You could do this at the start of each level, or when the player gets a certain number of points. Alternatively, how about mixing this with the Collectibles tutorial, and creating an item that gives the player a 1-UP? Similarly, you could add a “shield” power-up that stops the player taking damage for a while.
Speaking of other tutorials, Mushyrulez’s Enemies tutorial is perfect for this. Perhaps the bigger enemies could do more damage, taking two or three lives at a time, while the smaller enemies actually regenerate your health?
Let me know what you come up with
Wrapping Up
You can download the zip of all the files from this tutorial here.
Hey, I managed to get all the way through that without making a lame “get a life” joke. I think that’s pretty impressive.







{ 15 comments… read them below or add one }
Great. I made it to 11720. But hey, remember to embeded the fonts, mine became times new roman.
Other challenges could be:
- Add an animation to the enemies when they disappear.
- Make the ‘sheild’ active on the player when he is losing one life, and make a blinking animation on him.
D’oh, school boy error on my part
Nice suggestions!
Thank you, its really awesome, and your right 100 Lives is perfect
Do i actually HAVE to do that garbage collecting in part 12 to make it work?
Anoyingly, it dont show how many lives i got. And when i put that new var in, it says duplicate…something.
Do i have to do that?
That “duplicate” error is probably due to having “automatically declare stage variables” unchecked, rather than the actual garbage collection. If you haven’t checked that, then removing the
public var gameLives:Lives;line should get rid of that error.Fixed:) Thank you. Wow, you know Michael, just following those 12 tutorials, i have learned a lot of AS3! I had like 80% more errors that i asked you for help about, but i solved them all by myself and how? – Remembering what you told us! Your tutorials are GREAT, seriously if there was Tutorial awards, my vote would definently go to you!
Good good — and thanks
Have you read my series on debugging?
I have
And i laughed so much at that
Sometimes it’s best to give your brain time to figure things out on its own, without your interference. So if it feels like you’ve been BANGING YOUR HEAD TO A BRICK WALL and getting nowhere solving your problem
Funny because its so true! same as this;
What a lot of new programmers do here is sit and stare at the above lines of code, trying to figure out just where the heck a problem could be occurring, and getting annoyed because it all looks fine.
The up is what i did :<
Hopefully not any more!
Is this regarding visual basics?
Actually it’s about ActionScript 3.0, a scripting language for Flash.
I’ve completed this, but I’m not sure what’s wrong…
I’ve commented out stuff and tested what stuff was before the tutorial to figure out that the location of the problem is the setValue part.
What happens is it compiles the file without any errors or warnings, but then when I click the start button I get the following in the output:
TypeError: Error #1009: Cannot access a property or method of a null object reference. at AvoiderGame() at DocumentClass/onRequestStart() at flash.events::EventDispatcher/dispatchEventFunction() at flash.events::EventDispatcher/dispatchEvent() at MenuScreen/onClickStart()But if it’s commented out, it works fine (don’t know about the parts in the tutorial after that though).
I’ve checked your .fla and as far as I can tell, everythings the same. I’ve checked: instance name, Lives properties, Lives.as, and the stuff in AvoiderGame.as.
While I do have added features, none should effect this.
PS. I do know the AvoiderGame.as is run properly until it gets to that one line. It doesn’t do anything after (used a trace).
Hey Graham,
Looks like
gameLivesisn’t set to anything, for some reason. (I.e. you’re missing a line where you type, for instancegameLives = new Lives()or whatever.Does that help?
I’m not sure what I changed (I went to the past version and redid the tutorial), but I fixed it.
My next goal is to make HP, which is separate from lives. Then, see if I can add in HP for the enemies, and speed up the shooting (I added in the shooting feature that you have the tutorial for).
Oh OK, cool
HP, good idea! Let me know how that goes.
{ 1 trackback }