working.jpg

One of the most important reasons you continue playing a game is because it has variety. You never know what’s going to happen. That is why almost all of the most successful games have tons of variety in them – new monsters, new weapons, new plots.

Let’s take a look at our avoider game right now. We’ve come a long way from the beginning, but is there still really a reason for us to play on? We have levels, but is there any big, visible change after we advance to a level? Of course, what’s one of the most easiest ways to make a big, visible change?

Different enemies.

This chain of tutorials will explain how to create different enemies. Everyone is welcome to contribute, as we are all starting from the same page! That is, the end of Part 12 of the AS3 base avoider game.

Click the preview image above to see what we have after implementing this.

Sizes

We already have different enemies in our game – every single enemy created is “different” in a sense – the place they come from. All of our enemies are different already, however most people will say that it’s still the same – they can’t visually see the difference.

amorphous

In Amorphous+, we can see the difference between enemies – their colour is different, their behaviour is different, their size is different.

Why don’t we just make our enemies have a different size? That way, people can visually see the difference, without us having to manually create a new MovieClip for each separate enemy.

In an earlier tutorial, the scaleX and scaleY properties were introduced. This was further expanded in this tutorial.

ScaleX and scaleY basically set the size (scale) of an object. 0.5 would be half the size, and 2 would be 2 times the size.

This is extremely simple to do – just open Enemy.as and add Line 14 and 15.

?View Code ACTIONSCRIPT3
6
7
8
9
10
11
12
13
14
15
16
public function Enemy( startX:Number, startY:Number, xSpeed:Number, ySpeed:Number )
{
x = startX;
y = startY;
 
xSpeed = 0;
ySpeed = 3;
 
scaleX = ( Math.random() * 1 ) + 0.5;    //Generates a random number between 0.5 and 1.5
scaleY = scaleX;
}

Of course, you can adjust this to match the specifications of your game. ScaleY is equal to ScaleX so that the enemies don’t stretch out of control, like this:
stretched-enemy

Yay differences!

sizes

Directions

What else can you do to add a little bit more difference in the game?

Right now, the game’s very easy to expect. Enemies come from the top, you avoid them, they fall down to the bottom, and then the garbage collector collects them.
Why don’t we just make it so that you DON’T know which direction they’re coming from?

First of all, we need to set something so that the game knows which direction is which.

Add this to your onTick function:

?View Code ACTIONSCRIPT3
public function onTick( timerEvent:TimerEvent ):void
{
gameClock.addToValue( 25 );
if ( Math.random() < currentLevelData.enemySpawnRate )
{
var enemyDir:int = Math.floor(Math.random()  * 4 + 1);

We’re setting a new variable called enemyDir (short for direction). It’s a whole INTeger, and it rounds down (in other words, removing everything after the decimal point). Math.random() * 4 generates a random integer between 0 and slightly less than 4 and adds 1 to it. This makes it so that you can never get 0 (nothing positive + 1 = 0) or 5 (Because it generates something slightly less than 4, which includes 3.9999, but not 4). This makes it so that enemyDir is 1, 2, 3 or 4, with an equal chance of each. See this post if I’m not being clear.

This doesn’t really do anything right now, so let’s set the different directions:

?View Code ACTIONSCRIPT3
var enemyDir:int = Math.floor(Math.random() * 3 + 1);
{
if ( enemyDir == 1 )
{
var randomX:Number = Math.random() * 400;
var randomY:Number = -15;
}
else if ( enemyDir == 2 )
{
var randomX:Number = 415;
var randomY:Number = Math.random() * 300;
}
else if ( enemyDir == 3 )
{
var randomX:Number = Math.random() * 400;
var randomY:Number = 315;
}
else if ( enemyDir == 4 )
{
var randomX:Number = -15;
var randomY:Number = Math.random() * 300;
}
var newEnemy:Enemy = new Enemy( randomX, randomY );
army.push( newEnemy );
addChild( newEnemy );
gameScore.addToValue( 10 );
sfxSoundChannel = enemyAppearSound.play();
}

Notice how I added a new paramater called randomY – this sets the Y position, so that you can really have different directions.

1 is North, and the directions go clockwise, so 2 is East, 3 is South, etc. Remember that in Flash, y is opposite – the top is the origin.

Let’s try this out now:

You should get an error message:

Warning: 3596: Duplicate variable definition.

Don’t worry, this is fine. It’s just a warning.

Click to play demo.

Hmm… something’s wrong.
Oh yes! The enemies are being made at different positions, but they’re still moving the same way!
To fix this, we have to add 2 more parameters to our Enemy – the speed.

Go to enemy.as and change the constructor function like so:

?View Code ACTIONSCRIPT3
public function Enemy( startX:Number, startY:Number, xMovement:Number, yMovement:Number )
{
x = startX;
y = startY;
 
xSpeed = xMovement;
ySpeed = yMovement;
 
scaleX = ( Math.random() * 1 ) + 0.5;    //Generates a random number between 0.5 and 1.5
scaleY = scaleX;
}

As you can see, the 2 new parameters are xMovement and yMovement. xSpeed is set to xMovement so that there’s not too much confusion.

Now all we need to do is go into AvoiderGame and edit the speed for the different directions:

?View Code ACTIONSCRIPT3
if ( enemyDir == 1 )
{
var randomX:Number = Math.random() * 400;
var randomY:Number = -15;
var randomXSpeed:Number = 0;
var randomYSpeed:Number = Math.random() * 4 + 1;
}

And repeat for the other 4 sides.
Remember which way the enemies should go!

Now it’s working :D
working

Tidying Up

As of right now, all the enemies are moving in straight lines. This isn’t very fun – you can see the enemies coming and know exactly where they’re going. Why don’t we create enemies that can travel at a slant?

It’s quite simple – just set the randomX/YSpeed that’s 0 to another random number. Here’s what I did:

?View Code ACTIONSCRIPT3
if ( enemyDir == 1 )
{
var randomX:Number = Math.random() * 400;
var randomY:Number = -15;
var randomXSpeed:Number = Math.random() * 2 - 1;
var randomYSpeed:Number = Math.random() * 4 + 1;
}

Behold the slanted goodness!

Click to play demo.

You can still predict where the enemies are going to go, however it is a little bit harder.

We still need to garbage collect the enemies going off the side, so edit it like so:

?View Code ACTIONSCRIPT3
if ( enemy.y > 350 )
{
removeChild( enemy );
army.splice( i, 1 );
}
if ( enemy.y < -50 )
{
removeChild( enemy );
army.splice( i, 1 );
}
if ( enemy.x > 450 )
{
removeChild( enemy );
army.splice( i, 1 );
}
if ( enemy.x < -50 )
{
removeChild( enemy );
army.splice( i, 1 );
}

Finally, let’s put the Avatar in the middle, since enemies aren’t just coming from the top anymore:

?View Code ACTIONSCRIPT3
avatar = new Avatar();
addChild( avatar );
if ( useMouseControl )
{
avatar.x = mouseX;
avatar.y = mouseY;
}
else
{
avatar.x = 200;
avatar.y = 150;
}

(In AvoiderGame.as)

Ah, nothing beats the sweet smell of success in the morning (or afternoon)!

Wrapping Up

Why don’t you try making this even more different – maybe really do add different MovieClips as you progress through different levels!

I don’t have much challenges for you, so post something in the comments and let us know of another challenge!

However, I have one very challenging challenge – we are inviting you to write your own tutorials! I was completely new to Flash when I saw Michael and FH’s tutorials, so we’re all in the same boat. Just send an email to me, Michael, or FH. I’m on vacation for the duration of May, so I probably won’t be able to reply to most of your email messages. Alternatively, post a comment below, or sign up to our new forums!

And as for topics, you could try making an enemy that follows you – This will make the game far more challenging (and fun).

You can download the .zip here.

A special thank you to FH for giving me this idea.

Thanks for looking :D

13 Responses to “AS3: Enemies, Part 1”

  1. [...] out his tutorial here: AS3: Enemies, Part 1. It leads on from Part 12 of mine, so if you’ve completed that, you’ll be able to [...]

  2. MichaelJW says:

    Thanks again for writing this, Mushy. Great job too :D

  3. Bram says:

    Nice work, it’s good to see someone adding more things to the avoidergame. Thanks for taking the time to write this! Keep em coming ;)

  4. Great post :)

    (I promise to get up to date with this after my exams, and start writing AS3 parts!)

  5. [...] before, FrozenHaddock was way ahead of me in adding this feature to his game. Let’s play catch-up, [...]

  6. [...] going to adapt a technique from Mushyrulez’s Enemies tutorial for controlling the bullet’s direction. (Check out his post if you want to see a full [...]

  7. Ardavanski says:

    Hi guys!

    I just did the enemy part 1 tutorial, and as i see, they do NOT get deleted (only them going south) + i get a bunch of warnings.

    Ok, in a clear way;

    Enemy tutorial, part 1:::

    Enemys going ALL directions, but only them going south will be deleted, the rest going east west and north will just continue, like if we was in part 11 without garbage collection.

    and i get a bunch of warnings that actually stresses me ALOT since i think its a error all the time :( any way to get rid of them?

  8. Ardavanski says:

    The Enemys not getting deleted FIXED BUT

    I still get anoying Warnings, how should i fix them?

  9. MichaelJW says:

    Cool, how did you fix it?

    Warnings are irritating, but won’t stop your game running — they’re not errors, just things Flash thinks you should be doing differently.

    In this case, they’re due to having code like this:

    if ( something )
    {
        var someVariable:Number = 3;
    }
    else if ( something else )
    {
        var someVariable:Number = 11;
    }
    

    Flash says “hey, you wrote ‘var someVariable:Number’ twice there, watch out, because the second one might overwrite the first”. As long as you’re sure that’s not going to happen, it’s fine. But if you want to get rid of the warning, you need to make sure you’re only defining the variables once per function — i.e., put the “var someVariable:Number” at the top of the function, and just change the value in the if-statements.

  10. Ardavanski says:

    if ( enemy.y > 350 )
    {
    removeChild( enemy );
    army.splice( i, 1 );
    }
    if ( enemy.y 450 )
    {
    removeChild( enemy );
    army.splice( i, 1 );
    }
    if ( enemy.x < -50 )
    {
    removeChild( enemy );
    army.splice( i, 1 );
    }

    This :) I had deleted a bit of it without knowing it, so i downloaded the source, compared it and saw the error :)

    And about that, Thx good to hear they are not errors :)
    Ill just keep them :)

  11. [...] next? Well, in the last part I mentioned Mushyrulez’s Enemies tutorial and the need for garbage collection. Now I’m also going to recommend using Rasmus’s Diagonal [...]

  12. Sharedtut says:

    Great job, thank you for sharing.

  13. Mushyrulez says:

    Thanks for reading…!

Leave a Reply