Space Invaders part 2 in Flash MX

This has been 'adapted' from the excellent tutorials found at www.video-animation.com/flash_12.shtml - there are many more well worth investigating.

This Flash game tutorial carries on from part 1. In that we constructed our defender, our rows of aliens, and got our defender to shoot bullets. At the last stage, it was getting a little sluggish because we had too many characters on stage at once - 30 aliens and 50 bullets. So the first thing we will do will be to :

Reduce the number of bullets.
Make some bombs and work out how and where and when to drop them
Make some covers to protect the defender
Do some collision detection
Check if bullets hit aliens
Check if bombs hit defender
Check if bullets hit bombs
Check if bombs hit covers
Check if aliens hit defender
Then ..
Add score and lives fields
Add code to increase score when alien is hit and defender is hit
If all aliens are dead, go to next level
If defender's lives are all gone, return to start.
Create new level/s and a start page...


1. Reduce the number of bullets

In the original you had just one bullet, then we increased this to 50. You can have as many as you like but they slow the game.
Select your defender movie clip and open its actions window. Change the 50 to a 5 (or whatever number you choose) at the line where it says

// inside mouseDown method
if(bulletNum>50){
bulletNum = 0;
}


2. Bombs

On a new layer draw some sort of aliens' bomb shape. Select it and press F8, give it the name of Bomb and give it the instance name of bomb.
Select the bomb and in its actions window write this code:

onClipEvent (enterFrame) {
this._y += 5;
if (this._y>Stage.height) {
this.removeMovieClip();
}
}

The above code will drop the bomb and remove it when it hits the bottom of the screen.
We now need to create a number of bombs. The following code will create 10. We will just drop them randomly from any horizontal position and within a range in the vertical position.
So select controller_mc and in the actions window, after the line:
"dropdown = false;"
It will be in the enterFrame method just before the last curly bracket:

// controller mc enterFrame
// .....
dropdown = false;
// drop bombs
if(Math.random() < 0.1)
{
// duplicate the bomb mc
_root.bomb.duplicateMovieClip("bomb" + bombNum,200+ bombNum);
// set the coords to a random position
eval("_root.bomb" + bombNum)._x =random(700);
eval("_root.bomb" + bombNum)._y = 300*Math.random();

// increment the bomb number
bombNum++;
// if more than 10 bombs , start again at 0
if(bombNum>10){
bombNum = 0;
}
}

All we have done is recycled our bullet code. We have randomly selected a time (whenever the random function generates a number between 0 and 0.1). You can try whatever number you like there, experiment with 0.5, 0.8.
Duplicated the bomb mc, remembering to put it on our 200+ depths.
Set the x value to be between 0 and 700, our Stage width
Set the y value to be between 300* 0.01 and 300* 1.0.
And then increment the bomb Number. There should be bombs dropping all over the place.


3. Covers

Create another layer and draw some sort of cover or barrier to hide behind. Select it, press F8, call the movie clip Cover and call the instance "cover". Select the frame in the actions layer and put this code after the duplicate aliens code:

for(var j=0;j<6;j++)
{
duplicateMovieClip("cover", "cover"+j, 300 + j);
_root["cover"+j]._x = j*100 + 80;
_root["cover"+j]._y = 350;
}


It is basically the same code for creating the aliens. Since the covers don't move that's it for them except for collision detection later. Notice the depths were put at 300+. Just keep going up in hundreds each lot of mc's that you duplicate.


4. Collision Detection - Bullets Hit Aliens

First create a new layer and call it "textfields". Create a dynamic TextField. In the "variable" field in the Properties window call the variable "score". Create another Dynamic Text field and call its variable "lives". Place these textfields up the top somewhere. Our scores and lives will be displayed here.
Select your bullet mc on the stage. And in the actions window add some code. The whole code for bullet should look like this:

onClipEvent (enterFrame) {
this._y -= 30;
if (_x<0 || _x>Stage.width || _y<0) {
this.removeMovieClip();
}
for (var i = 0; i<3; i++) {
for (var j = 0; j<10; j++) {
if (_root.bullet, hittest(_root["alien"+i+"_"+j])) {
_root.score +=1;
_root["alien"+i+"_"+j].removeMovieClip();
this.removeMovieClip();

}
}
}
}


The top bit we already had. The bottom for loops just cycle through all the aliens testing to see if a bullet has hit an alien. If there is a hit,
+ the score is incremented by 1, (you can use 10 or 100 for dramatic effect),
+ and the hit alien together with the bullet is removed from the screen.
+ The score will be displayed in the first TextField we created above, with the variable "score".
The variable "lives" will be decremented (-1) when a bomb hits our defender.
Before we go any further, we need to make a another frame in our root movie so that we have somewhere to go after our level ends. So select frame 2 on each layer and hit F6, (except for our actions layer, hit f5 for that) to make new keyframes on every layer. Delete the contents of all the frame 1's , except for the actions layer.
For the actions layer, select frame 1 and hit f6 to make a new keyframe there. Delete all the code in that frame and simply put in the code :

stop();


Also make sure to put a stop(); action at the top of the code for layer 2, actions layer. Otherwise it will just loop back to the front page.
Now everything that was on frame 1 is now on frame 2, the only thing on frame 1 is the code (stop();) in the actions layer.
Now make a button (only on frame 1) on a new layer called "start" and put this code on the button to send it to frame 2:
on(release){
_root.gotoAndStop(2);
}
You can also add some graphics, some instructions, whatever to the front page.


5. Bombs Hit Defender, Bullets and Covers

Put this code into our Bomb mc.

onClipEvent (enterFrame) {
this._y += 5;
if (this._y>Stage.height) {
this.removeMovieClip();
}
// bombs hit defender
if (this, hittest(_root.defender)) {
_root.lives -= 1;
if(_root.lives <=0)
{
// change to go to page 1
Mouse.show();
_root.gotoAndStop(1);
}
this.removeMovieClip();
}
// bombs hit bullets
for(var k=0;k<6;k++){
if(this, hittest(_root["bullet"+k]))
{
this.removieMovieClip();
}

}
// bombs hit covers
for(var l=0;l<6;l++)
{
if(this, hittest(_root["cover"+l]))
{
_root["cover"+l].removeMovieClip();
this.removeMovieClip();
}
}
}

If a bomb hits a defender, a life will be lost and if lives < 0 then the game is over and the player gets sent to frame 1 to restart. We also show the mouse so that users can find the start button.

If a bullet hits a bomb, it is simply removed. Same for the covers.


6. Finishing Level 1

Add an empty keyframe on frame 3. Later we will put the new level there.
Go back to frame 2 and on the control_mc , this is the final code for it:

onClipEvent (load) {
dropdown = false;
speed = 10;

}
onClipEvent (enterFrame) {
_root.deadcount=0;
for (var i = 0; i<3; i++) {
for (var j = 0; j<10; j++) {
// if alien hits defender
if(_root["alien"+i+"_"+j].hittest(_root.defender)){
// change to go to page 1
// remove all the mc's - aliens
for(var i=0;i<3;i++){
for(var j=0;j<10;j++){
_root["alien"+i+"_"+j].removeMovieClip();
}
}
// remove covers
for(var i=0;i<6;i++){

_root["cover"+i].removeMovieClip();
}

Mouse.show();
_root.gotoAndStop(1);

}

// move horizontal
_root["alien"+i+"_"+j]._x += speed;
// check if any aliens left alive
if(_root["alien"+i+"_"+j]!=null){
++_root.deadcount;
}

if (_root["alien"+i+"_"+j]._x<0) {
// set direction to right
speed = 10;
// drop down
dropdown = true;
break;
}
if (_root["alien"+i+"_"+j]._x>Stage.width) {
// set direction to left
speed = -10;
// drop down
dropdown = true;
break;
}

}
}// end for loops

// drop down
if (dropdown) {
for (var i = 0; i<3; i++) {
for (var j = 0; j<10; j++) {

_root["alien"+i+"_"+j]._y += 20;
}
}
}
dropdown = false;

// drop bombs

if(Math.random() < _root.0.1)
{
// drop a bomb
// duplicate the bomb mc
_root.bomb.duplicateMovieClip("bomb" + bombNum,200+ bombNum);
// set the coords to the bomb
eval("_root.bomb" + bombNum)._x =random(700);
eval("_root.bomb" + bombNum)._y = 300*Math.random();

// increment the bomb number
bombNum++;
// if more than 5 bombs , start again at 0
if(bombNum>6)
bombNum = 0;
}

if(_root.deadcount==0)
{
// remove covers
for(var i=0;i<6;i++){
_root["cover"+i].removeMovieClip();
}
// go to next level
_root.gotoAndStop(3);
}
}

In the enterframe method, we declare a variable which will count the number of undead aliens or !null aliens, ie. still alive. Whenever the deadcount(misnomer) is 0, that means that all the aliens are killed. And then we can go to the next level (frame 3). Before that we clean up any movieclip's left on stage.
Make a New Level

Go to frame 3 and hit F6 for every layer. Make a new baddie and call it "bug3". Wherever there is a reference to "alien" replace it with "bug3" (NB the original tutorial said just "bug" which Jed thinks may be a typo, but if there is a problem, try "bug").

For example on the Control layer, frame 3 the code for initialising the baddie formation would be:

for(var i=0;i<3;i++){
for(var j=0;j<10;j++){
this.attachMovie("bug3","bug3"+i+"_"+j,depth);
_root["bug3"+i+"_"+j]._x = j*40;
_root["bug3"+i+"_"+j]._y = i*40;
depth++;
}
}

You can make each new level harder by increasing your baddie speed, the rate they dropdown, and by increasing the frequency of bombs on each level.

Some code optimisation tips:
Keep your code centralised into one script, not scattered all over the place like these
Use as few enterFrame loops as possible
Use gifs or pngs for the sprites (Flash really likes pngs, a Macromedia file format which combines the best of gifs and jpegs)
Use 'while' loops instead of 'for' loops
Set up an array of baddies for better collision detection
Have a look at Steve's game so far.
Download Steve's fla to study it.

Rewind and play, or Save and then press Apple Return (Ctrl Return on Windows).

Steve has rewritten the tutorial to speed the game, which improves the game but is perhaps harder for a beginner to follow.


<< Back to Flash Tutorials