AS3 Avoider Game Tutorial, Part 2: Multiple Enemies

by Michael Williams on September 22, 2008 · 95 comments

in Avoider Game Base, Tutorial

(This tutorial is also available in Spanish, Polish, and Italian.)

Introduction

In this part of my AS3 conversion of Frozen Haddock’s tutorial, I’ll show you how to add multiple enemies to your game. Check out what you’ll be working towards by clicking the image below.

screenshot

Setting Up

If you didn’t follow along with the first part of the tutorial, grab the zip file here and extract it to your hard drive, making sure it keeps the folder paths intact.

If you did follow the first part, I recommend making a backup of your existing game files by copying the main folder (I called mine AvoiderGame-MJW, remember) and naming the copy something like AvoiderGame-MJW-part1. This way, you can look back at the early game in the future and see how much you’ve progressed!

Either way, open the FLA file. Open the document class file (mine’s called AvoiderGame.as) and the Enemy.as file too, since we’re going to be editing them a lot.

Taking Control of the Enemy

Take another look at the Enemy’s constructor (it’s located in the Enemy.as file):

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

This little bit of code means that every single instance of the Enemy class will start off at (100,-15). This will not make for a very interesting Avoider game. It’s also not going to be any use when we start making enemies that move upwards — if they start above the screen, they’ll never make it onto the playing field!

Change the constructor function like so:

?View Code ACTIONSCRIPT3
6
7
8
9
10
public function Enemy( startX:Number, startY:Number ) 
{
	x = startX;
	y = startY;
}

We’ve added parameters to the constructor function. Now when we create an instance of Enemy in the document class, we can pass x and y values to it to specify where it should appear.

Switch to your document class (that’s AvoiderGame.as) and change the code that creates a new enemy from:

?View Code ACTIONSCRIPT3
15
enemy = new Enemy();

to:

?View Code ACTIONSCRIPT3
15
enemy = new Enemy( 100, -15 );

If you run the game (Control > Test Movie, remember), you’ll see that the enemy starts at (100,-15) — which is exactly as we’d expect. We’ve passed the values 100 and -30 to the Enemy constructor, which has first set startX = 100 and startY = -15, and then set x = startX and y = startY. Of course you can change the numbers in Enemy(100,-15) to make it start out in different places. Try it out.

Irresponsible Cloning

How can we make more than one enemy appear? Let me show you an example of what not to do. It’s the simplest method: we literally copy and paste the enemy until we have as many as we need.

First, define a few more enemies as public vars in your document class (lines 10-12):

?View Code ACTIONSCRIPT3
7
8
9
10
11
12
13
14
public class AvoiderGame extends MovieClip 
{
	public var enemy:Enemy;
	public var eric:Enemy;
	public var ernie:Enemy;
	public var emily:Enemy;
	public var avatar:Avatar;
	public var gameTimer:Timer;

Next, set these up with different starting positions in the document class’s constructor, and add (using .addChild) them to the game (lines 20-25):

?View Code ACTIONSCRIPT3
16
17
18
19
20
21
22
23
24
25
public function AvoiderGame() 
{
	enemy = new Enemy( 100, -15 );
	addChild( enemy );
	eric = new Enemy( 160, -120 );
	addChild( eric );
	ernie = new Enemy( 205, -60 );
	addChild( ernie );
	emily = new Enemy( 317, -85 );
	addChild( emily );

Next, in your onTick function, get them all moving:

?View Code ACTIONSCRIPT3
37
38
39
40
41
42
public function onTick( timerEvent:TimerEvent ):void 
{
	enemy.moveDownABit();
	eric.moveDownABit();
	ernie.moveDownABit();
	emily.moveDownABit();

Finally, check each of them for a collision with the player:

?View Code ACTIONSCRIPT3
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
if ( avatar.hitTestObject( enemy ) ) 
{
	gameTimer.stop();
}			
if ( avatar.hitTestObject( eric ) ) 
{
	gameTimer.stop();
}			
if ( avatar.hitTestObject( ernie ) ) 
{
	gameTimer.stop();
}			
if ( avatar.hitTestObject( emily ) ) 
{
	gameTimer.stop();
}

Run the game. Sure, it works, but it’s a pretty very messy solution. Go ahead and undo all of that copying and pasting, it’s unnecessary.

Forming an Army

Copying and pasting enemies like that lets us refer to each one by a specific name. But… do we ever actually need to do that? Is there ever a situation where we need to tell just one enemy to act differently to the rest? Only when something happens to that enemy — when it hits the player, perhaps, or when it leaves the screen — but in those cases we single the enemy out by its situation, not by its name. I’ll show you what I mean in a bit.

What we’re going to do is create a group of enemies, and use the document class as a “general”, telling the group how to behave. I’m going to call this group army, for obvious reasons. We’ll use an Array as the structure for the group; this is basically an ordered list of objects.

First we need to define the new army, just as we did for the enemy. It’s going to have to be accessible for the duration of the game, so we’ll define it within the document class but outside the constructor (line 7):

?View Code ACTIONSCRIPT3
7
8
9
10
11
12
public class AvoiderGame extends MovieClip 
{
	public var army:Array;
	public var enemy:Enemy;
	public var avatar:Avatar;
	public var gameTimer:Timer;

Also, remove that line, public var enemy:Enemy; (line 10 above). Since the enemies are all going to be part of the army, and the army is a public var, we don’t need the enemies to be public vars any more.

Now, alter the game’s constructor like so:

?View Code ACTIONSCRIPT3
14
15
16
17
18
19
public function AvoiderGame() 
{
	army = new Array();
	var newEnemy = new Enemy( 100, -15 );
	army.push( newEnemy );
	addChild( newEnemy );

What have we done?

  • Line 16 — Set the army as a new instance of Array, just as we’ve done for the enemy.
  • Line 17 — So as not to get confused, I’ve renamed enemy to newEnemy, as it will now only be used for creating new enemies. Since there’s no var newEnemy statement (public or otherwise) anywhere, we need to stick var on the front here.
  • Line 18 — Added the new enemy to the army. (“Pushed” it onto the end of the list of enemies.)
  • Line 19 — added the new enemy to the game (all that’s changed here is that enemy has been renamed newEnemy).

Now we need to make the enemy move. Remember this is done in the onTick function. We’re going to need a for each…in loop, which is new to ActionScript 3.

Edit the onTick function so that:

?View Code ACTIONSCRIPT3
31
32
33
34
35
public function onTick( timerEvent:TimerEvent ):void 
{
	enemy.moveDownABit();
	avatar.x = mouseX;
	avatar.y = mouseY;

becomes:

?View Code ACTIONSCRIPT3
31
32
33
34
35
36
37
38
public function onTick( timerEvent:TimerEvent ):void 
{
	for each ( var enemy:Enemy in army ) 
	{
		enemy.moveDownABit();
	}
	avatar.x = mouseX;
	avatar.y = mouseY;

I think it’s actually quite clear what’s happening here. The for each…in loop goes through everything in the army’s list of items and tells it to move down a bit. The confusing part is that it looks like we are telling the loop only to look at items of type Enemy — but that’s not how it works. We are merely telling the loop that it should expect everything inside the army to be of type Enemy. We could have added the avatar to the army back in the constructor function — and then the game would have crashed because the Avatar class doesn’t contain a function called moveDownABit(). Anyway, don’t worry about this too much, it’ll become more intuitive as you use it more.

There’s one more change we need to make before we can run this: checking for collisions. We can just move the collision detection code to be inside the for each…in loop (lines 36-39):

?View Code ACTIONSCRIPT3
31
32
33
34
35
36
37
38
39
40
41
42
43
public function onTick( timerEvent:TimerEvent ):void 
{
	for each ( var enemy:Enemy in army ) 
	{
		enemy.moveDownABit();
		if ( avatar.hitTestObject( enemy ) ) 
		{
			gameTimer.stop();
		}
	}
	avatar.x = mouseX;
	avatar.y = mouseY;
}

Although, this means that we are checking for collisions before we’ve moved the avatar, i.e. we’re checking if the enemy is colliding with where the player used to be, which hardly seems fair. So, rearrange it a bit:

?View Code ACTIONSCRIPT3
31
32
33
34
35
36
37
38
39
40
41
42
43
44
public function onTick( timerEvent:TimerEvent ):void 
{
	avatar.x = mouseX;
	avatar.y = mouseY;
 
	for each ( var enemy:Enemy in army ) 
	{
		enemy.moveDownABit();
		if ( avatar.hitTestObject( enemy ) ) 
		{
			gameTimer.stop();
		}
	}
}

Save it and run it, and you’ll see everything’s working out just as before. Now to add more enemies.

Adding to the Army

Try this:

?View Code ACTIONSCRIPT3
31
32
33
34
35
public function onTick( timerEvent:TimerEvent ):void 
{
	var newEnemy:Enemy = new Enemy( 100, -15 );
	army.push( newEnemy );
	addChild( newEnemy );

You should recognise lines 33-35. We’ve just put the code for creating a new enemy in the onTick, so that every tick it will create a new enemy. What do you expect will happen when we run it?

screenshot

Hm. It’s creating new enemies in the same place at such a fast rate that they’re overlapping. Let’s try to fix this by starting the new enemies off in all different places.

We’ll need the Math.random() function for this. Math.random() returns a random number between 0 and 1. My game is 400 pixels wide, so I’d like the enemies to start off with an x-coordinate of between 0 and 400. Therefore (lines 33-34):

?View Code ACTIONSCRIPT3
31
32
33
34
35
36
public function onTick( timerEvent:TimerEvent ):void 
{
	var randomX:Number = Math.random() * 400;
	var newEnemy:Enemy = new Enemy( randomX, -15 );
	army.push( newEnemy );
	addChild( newEnemy );

So now the enemies will be created at some random point above the screen. Save it and run it, and what do we get?

screenshot

Argh!

All right, so, maybe they’re still coming in at too fast a rate…

Less Enemies per Second, Please

Right now, the enemies are appearing at a rate of one new enemy per tick. Since a tick is 25ms, there are 40 ticks per second, and therefore 40 new enemies per second. I think if we reduced this to four new enemies per second, we’d be good. Since 4 is 1/10 of 40, we need to reduce the new-enemies-per-tick rate to 1/10.

We could do this by making a new enemy appear every ten ticks. I think it would be more fun if we said there was a 1/10 chance of a new enemy appearing on any given tick; this way, sometimes we’d have more than four enemies appearing per second, and sometimes we’d have less, but over time we’d average out at four/sec. The uncertainty involved makes the game a little more exciting, however (though perhaps “exciting” is a little bit of a misnomer at this early stage of the game’s development…).

How can we do this, then? Well, we know that Math.random() generates a random number between 0 and 1. Since these random numbers are evenly distributed, that means that there’s a 1/10 chance of the number generated being between 0 and… well, 1/10. I.e., the chance of Math.random() < 0.1 is 1/10.

So, let’s change our code to make use of this fact (lines 29 & 34):

?View Code ACTIONSCRIPT3
28
29
30
31
32
33
34
35
36
public function onTick( timerEvent:TimerEvent ):void 
{
	if ( Math.random() < 0.1 )
	{
		var randomX:Number = Math.random() * 400;
		var newEnemy:Enemy = new Enemy( randomX, -15 );
		army.push( newEnemy );
		addChild( newEnemy );
	}

(Note: each time you call Math.random() the number generated is different, so this new code isn’t interfering with our random positioning code.)

Save it and run it.

screenshot

Much better! Actually, I think this may now be too easy. Why not fiddle around with the if (Math.random() < 0.1) statement to see what works best for you?

Wrapping Up

That’s it for part two. You can download a zip file with everything I’ve been working on from here.

In the next part, we’ll add a Game Over screen so that finally the game will have an aim! It’s available here.

If you’d like to try expanding upon this part yourself, how about trying to make the starting enemy appear at a random location? I’m sure you can do that now. Also, the enemies sometimes appear partly off one side of the screen. Can you fix that?

{ 2 trackbacks }

AS3: Avoiding game part 2 at
October 1, 2008 at 11:15 pm
AS3: Base Tutorial, Part 2 | Avoider Game . com
March 31, 2009 at 12:20 am

{ 93 comments… read them below or add one }

Martin August 11, 2009 at 12:49 am

Thanks for the great tutorial. I got a little project where I also need to instance a movieclip very often. But I choose a different way, like you did, and like to know if it´s a good way. At least my enemies need individual behaviours, so I did this way: My enemies got the timerEvent in their own class. That means that every enemy calls the moveDown-function on itselfs. And I don´t need an array for the army. And in my case I would need a second array for the direction (which is the “individual” behaviour). Would you say, this way is ok?

Martin

Michael Williams August 11, 2009 at 1:20 am

Hey Martin. Well, first off I’d say that if it works for you, it’s OK! :D

Having multiple timers may lead to some problems later, though. For example, they might take more processing power or get out of sync with each other (though I haven’t tested this — it’s pure speculation). It could also make things more complicated later on, like pausing the game (you’ll have to pause every single enemy’s internal timer) or testing for collisions between enemies (how do you do this without an army array?)

It’s up to you to decide whether or not these disadvantages outweigh the advantages you described. Often there’s no right answer. I’d be interested to hear what you decide, and whether that changes as you go on!

Martin August 11, 2009 at 1:31 am

update: I try it in your way and I think it is better. Don´t need a second array. Just to have one eventlistener is quite better for the performance than to have 20 or 30.

Michael Williams August 11, 2009 at 12:48 pm

Ah, OK. That’s interesting to know, thanks :)

mahmoud August 14, 2009 at 1:18 pm

hi

i think that we had two enemy 1-the enemy we make it in old tutorial 2-the array enemy :) so we should delete public var enemy:Enemy; and the final hitTestObject and the enemy after this code public function AvoiderGame() { army = new Array(); …..

Michael Williams August 15, 2009 at 12:49 am

Hehe, you’re seeing into the future ;) We actually do remove that “extra” enemy later on. Well done for spotting it :)

shawn August 23, 2009 at 4:09 pm

hey MJW, what code shoud i add in to prevent the enemies from overlapping each other?

shawn August 24, 2009 at 2:37 am

Plus, you stated that the enemies sometimes appear partly off one side of the screen. Whats the solution for that?

Michael Williams August 24, 2009 at 2:23 pm

Hey Shawn,

Those are challenges best left for you to work out yourself ;)

Here’s a hint, though. To stop the enemies appearing partly off the screen, you’ll need to make sure they aren’t created too far to the left or right. In other words, make sure the x value isn’t too low or too high.

For stopping enemies overlapping each other, you’ll first need to check whether any enemies do overlap when a new one is created (perhaps using hitTestObject), and move the new one to a different place if so.

Martin September 3, 2009 at 11:16 pm

Hi Michael, another little question. If I´d like to have enemies with, for example three, different looks, but with the same behaviour, what should I do. Should I put them all three into the enemy-mc with their own instance and having an little randomizer in the enemy class which select one of (enemy1, enemy2, enemy3) them? I think in this case the enemy-class should add the enemy on the stage. But would the collision detection work as usual? I´ll give a try.

Martin September 3, 2009 at 11:57 pm

Ok, I think I got it. I leave the enemy-mc empty. In the enemy class I select one of the enemies, which having their own empty(?) class (created by flash:thanks) an add it to the enemy stage. In the document class I add the enemy as usual to the root stage. I think that should be a good way. Martin

Michael Williams September 4, 2009 at 4:41 pm

Hi Martin,

That’s a neat way of doing it! Nice job.

Sean September 6, 2009 at 12:01 pm

Hi there, I have managed to finish this tutorial, with my own graphics – an evil face and a plane.

The problem is, when I move my mouse to move the ship, to avoid the evil faces, it doesn’t run smoothly at all. It has the ‘exact’ same coding as your version, and yours runs fine – I really don’t understand what’s going on!

My Computer:

OS: Windows 7 GPU: Nvidia 9800 GTX+ HDD: 1TB RAM: 6 GB

So I’m sure it’s not that my computer can’t manage to run the poxy thing! :P

Michael Williams September 6, 2009 at 1:38 pm

Hey Sean,

Haha, no, I don’t think it’s your computer! :P

Do you have any trace() statements inside your code? Also, do you see any errors or other text appear in the Output panel?

Sean September 6, 2009 at 5:00 pm

No trace statements and no errors :)

I could send you the code? Not sure how, can’t find any contact info :)

Just want to also say that this website is awesome and I can’t wait to finish each and every one of your tutorials :)

Michael Williams September 7, 2009 at 4:10 pm

Thanks Sean, I’ve sent you an email :)

Evenhumm September 28, 2009 at 2:59 pm

Lol i got this funny bugg i couldn’t fgure out, first of all the game freeze the moment an enemy entered the stage, i figured it was the gameTimer.stop() in the hitTestObject so i removed the stop, guess what. The game starts but the enemys stop moving down at random places half way down the stage. Anyone got simmiliar problem?

Eventuallt i downloded the sourcecode and compared the avoidergame.as but didn’t find any big difference. So i ended up erasing my avoidergame and copy pasting MJW’s, lol.

Michael Williams September 29, 2009 at 12:42 pm

Hey Evenhumm,

That is a weird bug! Have you got it working now?

Manu September 30, 2009 at 1:59 am

Hey, for the random x position spawning, is there a problem withh putting:

        public function Enemy(){

        x = Math.random()*450 + 50;
        y = -40;

    }

On the enemies class file or will it interfere with future operations?

BTW – Thank you soooo much for these tutorials. I just recently started learning AS2 but numerous people told me to go straight onto AS3 but I haven’t been able to find any good tutorials like this XD ~Manu…

Michael Williams September 30, 2009 at 1:37 pm

Hi Manu, thanks for the kind words :)

Moving the positioning code inside the constructor like you’ve done is fine, and I don’t think it’ll cause any problems later. Kudos to you for experimenting :)

Evenhumm September 30, 2009 at 7:28 pm

yupp copying your code worked fine

Michael Williams October 1, 2009 at 10:43 am

@Evenhumm: Good good. Any ideas what the problem was?

Evenhumm October 1, 2009 at 12:57 pm

Nope, wierdest bug i’ve ever had, and i tend to get a lot of them :P .

Craig November 2, 2009 at 11:35 pm

heya :)

I’m having difficulty figuring out how to code something that I think is pretty close to what you are doing in this tutorial…

I’m trying to make a basic snake application, but I’m getting hung up on the logic I’ll need to create the new snake body blocks, then make them follow the last block created.

I think I can set up making them follow each other, but I’m having trouble figuring out how to reference the individual blocks (example, last block created needs to follow last block created-1). I think I’d do this with an array like the one you set up, as each enemy gets pushed into the army array, is there a way to reference it to make it do something different than the others?

If this is too off-topic, just let me know, thanks so much by the way for the tutorials, I have looked EVERYWHERE for places where I can learn actionscript 3, including buying some books, and your tutorials have so far been by far the easiest to understand. If you make any more, please let me know!

Michael Williams November 3, 2009 at 12:30 am

@Evenhumm: Heh, OK. Perhaps your copy of Flash is cursed ;)

@Craig: Thank you for the kind words :) I’m glad you’ve found this useful.

You are definitely on the right track with the method you described. However, it’ll be hard to do this with the for-each loop I’ve used in this tutorial.

You can change the loop from this:

   for each ( var enemy:Enemy in army ) 
    {
        enemy.moveDownABit();
        if ( avatar.hitTestObject( enemy ) ) 
        {
            gameTimer.stop();
        }
    }

to this:

    var currentEnemyNumber:int = 0;
    for ( currentEnemyNumber = 0; currentEnemyNumber < army.length; currentEnemyNumber = currentEnemyNumber + 1 )
    {
        var currentEnemy:Enemy = army[ currentEnemyNumber ];
        currentEnemy.moveDownABit();
        if ( avatar.hitTestObject( currentEnemy ) ) 
        {
            gameTimer.stop();
        }
    }

…and that will work exactly the same.

Do you see how this works? The for-loop creates an int (a whole number) which starts at 0, then 1, then 2, and so on, until it has covered the whole “length” of the army array. Inside the loop, for every value of currentEnemyNumber, it gets that enemy from the array (so the first, then the second, then the third, and so on).

Once you understand that, try playing around with that and your idea of using “last block created – 1″. It might be tricky, but it’ll be worth it :)

Navras November 25, 2009 at 5:33 pm

Hiya James

Remeber me? I had some trouble with the preloader few months ago but now im trying to make my own game but i cant really seem to get my array or whatsoever to work properly… I mean I am doing the right thing to use an array? heres the situation:

My avatar shoots boxes in an arc throw from his position and when they collide with something their speed becomes 0 and and avatar is capable of standing up on them.

But everytime i throw a new box my avatar falls through the previous box which he was standing on although the movieclip of the previous box is still there but i can stand on the new box. At this point I’m clueless…

Michael Williams November 25, 2009 at 8:46 pm

Hey Navras,

Sounds like an array could be useful there, but you’ve gone a bit beyond the scope of this tutorial with your question. If you’re finding arrays confusing (a lot of people do, I’ve noticed!), check out this Papervision3D tutorial I wrote recently. I explain arrays in a slightly different way there than I do here, so it might be clearer.

Also, you might like to check out Dru Kepple’s intro to Arrays, it’s really in-depth!

Navras November 26, 2009 at 2:09 pm

Thnx I’m Looking into it right now !

noobmaster December 28, 2009 at 3:52 pm

“If you’d like to try expanding upon this part yourself, how about trying to make the starting enemy appear at a random location? I’m sure you can do that now. Also, the enemies sometimes appear partly off one side of the screen. Can you fix that?”

*What do you mean by the starting enemy appear at a random location? The way we set it up; he does randomly appear at the x coordinate.

*About the 2nd part, I did it :P . I hope it’s not wrong :

if (Math.random() < 0.1)
            {
                var randomX:Number = Math.random() * 400
                if (randomX  385)
                {
                    var remainder:Number = 30 - (400 - randomX);
                    var newEnemy = new Enemy((randomX - remainder), -15);
                }
                else
                {
                    var newEnemy = new Enemy(randomX, -15);
                }

            army.push(newEnemy);
            addChild(newEnemy);
        }

BTW, how can we check about the enemy vs enemy collision? I tried storing the x coordinate variable of the enemy in an array and check it with the next enemys x coordinate variable but it didn’t work. The third enemy, whose x coordinate variable is not checked with the first enemies; would jump on top of the first enemy :( .

noobmaster December 28, 2009 at 3:57 pm

The pre tags aren’t working as they should and honestly, I don’t know why they aren’t.

Anyways, here is the code: http://pastebin.com/f415d91dd

Michael Williams December 29, 2009 at 1:26 am

Hey noobmaster, not sure why the pre tags weren’t working, but they seem to be now.

Oh, I meant the very first enemy, the one created in the AvoiderGame() function, not the ones created in the onTick() function.

Nice work with your code :) Though… do the enemies still appear off the left edge of the screen? I can see how they wouldn’t appear off the right edge though, that’s great.

To check for enemy-enemy collisions, well, from the sound of it, you’ll have to check each new enemy against every single other enemy that exists! Quite a few tests… you’ll need another loop, I suppose.

noobmaster December 29, 2009 at 11:05 am

“Nice work with your code :) Though… do the enemies still appear off the left edge of the screen? I can see how they wouldn’t appear off the right edge though, that’s great.”

Yes, they are both working fine. Depending on the enemies size; you might have to reduce it’s size. The 30 px should be 15, since the ‘crosshair’(?) divided our enemy in half.

The left edge is working fine. I ran a test of 3 minutes (with invincible avatar) and saw no cut off smiley faces.

if (randomX < 15)
                {
                    var divident:Number = 15 - randomX;
                    var newEnemy = new Enemy((randomX + divident), -15);
                }

In here we check if the enemies x location is smaller than 15. If it is our enemy is cut off. So to not give or take any extra x coordinate, I subtract randomX from 15. The outcome is the part that the enemy is cut off. So if randomX was 7, then the most outter edge of our enemy would be at -8 (7 – 15). We move the enemy 7 spaces to the right and the outter most edge is at -1… OPPS. Thanks for making me notice this bug :)

Btw, is there a way to make trace work? Trace is great tool for debugging but i can't make it work with this project. :(

Michael Williams December 29, 2009 at 1:03 pm

Excellent :)

Trace isn’t working? That’s really weird… what setup are you using?

DudexD January 17, 2010 at 10:38 pm

I’m having a problem.

I’m trying to add a coin, that falls from the sky and give points if the player collects.

i’v pretty much just copied the enemy class and changed som values and stuff.

the only thing stopping me right now is this error:

 1136: Incorrect number of arguments. Expected 0. 

 
if ( Math.random() < 0.1 )
            {
                var randomX2:Number = Math.random() * 400
                var newCoin:Coin = new Coin( randomX2, -15 );
                coinArmy.push( newCoin );
                addChild( newCoin );
}

The:

 var newCoin:Coin = new Coin( randomX2, -15 ); 

is the line the error is from it say

Michael Williams January 18, 2010 at 8:42 pm

Nicely narrowed down.

The error means that it’s expecting you to write:

var newCoin:Coind = new Coin()

…instead of:

var newCoin:Coind = new Coin( randomX2, -15 )

…i.e. it doesn’t want any arguments to be passed to it. This suggests to me that your constructor function in Coin.as just starts:

public function Coin()

…unlike Enemy,as, which starts:

public function Enemy( startX:Number, startY:Number )

Make sense?

DudexD January 18, 2010 at 11:00 pm

Well thank you:D but i actually found out that the error came because of that i had saved the class coin in the wrong folder :S Kind of anoying:P But now i got even an great fail tho, when the enemy and the coin collides they both stop moving down… i dunno why since they don’t any hitTest to check for those 2’s collide.

Michael Williams January 19, 2010 at 5:36 pm

That’s peculiar. Any ideas? Is the .moveABit() function still being called on each of them?

Michael Reinhardt January 29, 2010 at 2:15 pm

I wrote some code to test if the enemies overlap by using a for each loop for the enemies array and breaking out of it if the hitTestObject returns true. I was worried that this might bog down the program since the enemies remain as stage children even when they’re not in view any more.

So, I don’t know if you covered this later in the tutorial as I’m just going through it the first time, but I ended up adding the following right after the enemy.moveDownABit(); in the main for each loop:

if ( enemy.y > 315 )
{
    removeChild( enemy );
    army.shift();
}

This removes the enemy from the stage and removes the first element from the array and shifts the rest of the array accordingly. Now, this only works because we know that the enemy leaving the stage is the front-most one, which is the first in the array. If the enemies moved at different speeds or in different directions this would be harder.

In any case, I’m really enjoying this tutorial. Thanks!

Michael Williams January 31, 2010 at 5:23 am

Hey Michael,

Good call! Indeed, this is eventually covered in the tutorial (though not for a while), but your method is slightly different — and it’s a nice clean one that works well :)

Thanks for posting it! Let me know how you get on.

Omar February 20, 2010 at 7:18 am

Thanks for the great tutorial it is really helped my a lot to understand the concept and the structure of the AS3

i am now in 2nd part of the tutorial, i got this error: 1067: Implicit coercion of a value of type Array to an unrelated type flash.display:DisplayObject.

the error refers to: addChild(army); please help me to fix it

thanks in advance //////////////////////////////////////////////////////////////// package { import flash.display.MovieClip; import flash.utils.Timer; import flash.events.TimerEvent;

public class AvoiderGame extends MovieClip 
{
    public var army:Array
    public var avatar:Avatar;
    public var gameTimer:Timer;

public function AvoiderGame() 
{

    army = new Array()
    var newEnemy = new Enemy(100, -15);
    army.push(newEnemy)
    addChild(army);

    avatar = new Avatar();
    addChild( avatar );
    avatar.x = mouseX;
    avatar.y = mouseY;

    gameTimer = new Timer( 25 );
    gameTimer.addEventListener( TimerEvent.TIMER, onTick );
    gameTimer.start();
}

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

    for each(var enemy:Enemy in army)
    {
        enemy.moveDownABit()
        if ( avatar.hitTestObject( enemy ) ) 
        {
            gameTimer.stop();
        }
    }
}

}

}

Michael Williams February 22, 2010 at 9:23 pm

Cheers Omar :)

You’re trying to addChild() the array, army, when you need to be adding the new enemy, newEnemy: addChild( newEnemy )

Hope that’s clear ;)

Thomas March 1, 2010 at 3:36 am

Hi! Thank you so much for this tutorial. It really helps me understanding AS.

There’s one problem however with my hitTestObject. I only get a hit when my bouwvakker(the mouse-object) hits the latest drawn brick. My bouwvakker just skips the rest of the downcoming parts and only recognizes a hit when it hits the latest drawn brick.

Could you please help me? My code can he found here: http://pastebin.com/BYhL7A25

Thanks in advance

Brian March 4, 2010 at 2:10 am

I double checked everything, but nothing is appearing when I test out the movie.

Leave a Comment

Writing code? Write <pre> at the start and </pre> at the end to keep it looking neat.

CommentLuv Enabled

Anti-Spam Protection by WP-SpamFree

Previous post:

Next post: