The Spawn Engine

an educational open source Flash game engine

Add enemies to the stage in Flash instead of using code

One of the reasons that we call the Spawn Engine just that, is because the Engine spawns enemies and pickups for the player to interact with. There are functions for spawning, moving, collision testing and removing these objects. But lets say you want to add enemies to the stage in Flash instead of using code. How and why would we want that?

One reason could be that you don’t want enemies to just randomly rain down. You want them to come in very specific and different formations at different intervals. Lets say a first wave of five enemies in a formation like a circle. Then a second wave of 10 in the shape of a square, and so on. Of course this is possible to do inside the newEnemy function but this can be tedious and difficult. We have an excellent tool in Flash, why not use it?

Well it is possible to add the enemies to the stage in Flash and design our level this way. Its more WYSIWYG and simple. Once you play test the level it’s easy to make small changes to add or remove enemies or space them out more. It could be a very comfortable way of designing levels. Lets take a look at one way of doing this.

First we need to turn off the random spawning. Go to your startGame function and comment out the call to setNextEnemy.

//setNextEnemy();

Next we need to add our enemies on stage. Make sure you use the top layer and the second key frame called “game”. Add as many or few enemies you want. To first try this method I would only add a few enemies first and later add more. Put them high up on the stage or even above the stage. These enemies will fall down like the spawned enemies did before, once we alter the code.

Also make sure you select all your enemies added to the stage and add these to a new movieclip. Give that movieclip an instance name “enemies_mc”.

Now if you run your game you will have the added enemies just haning there. They wont move and you can’t shoot them. They need to be added to your enemies array in order for the functions in the Engine to be able to interact with them. The function moveEnemies uses the enemies array and so does the function checkBulletEnemyCollissions. We don’t want to rewrite these since they work. We only need to make sure that the enemies inside enemies_mc are added to the enemies array.

Lets do this by going to the startGame function and right at the end of the function, before the closing curly brace, add some lines of code.

for (var i=0; i<enemies_mc.numChildren; i++) {
// what happens inside the loop
}

All we have done is added an empty for loop. We will replace that comment and fill this loop out with more code but I first want to explain what the loop will do. The movieclip enemies_mc is a container that has several movieclips inside it. A container is often refered to as parent and the objects inside are called children. The stage is a parent with the child enemies_mc just as enemies_mc is a parent to the children of type enemy inside it.

We don’t want or need to know how many enemies (children) are inside enemies_mc (the parent) since we can use the numChildren property that tells us the number of children inside the parent. And we can refer to these children and loop through them all one by one.

The idea now is that each child inside enemies_mc will be added to the enemies array. To get a specific child inside the parent we use the function getChildAt() which needs a parameter, a index number pointing to the child we want to get. We write inside our for loop

var mc = genemies.getChildAt(i);

and mc is now a variable which is the child inside enemies_mc. The index i is the variable we have in our for loop meaning that i will start at 0 and go to 1, 2, 3 and so on depending on how many enemy objects are inside the enemies_mc.

Next we want an if statement that checks that the child mc is actually an Enemy object. So we write

if (mc is Enemy) {
// more inside the if statement
}

We want to remove that comment inside the if statement and add the code that actually adds an enemy to the array. And we don’t want to add mc to the enemy array. We want to make a new Enemy object. It gets a bit complicated to have a movieclip inside a movieclip and that child is also in an array that we use for moving and collision detection. No, we much rather want a movieclip right on the stage just like we do in the newEnemy function. There are other ways to solving this but I wanted to choose one that looked like code you’ve seen before, like the newEnemy functions.

Go to the newEnemy function and find the one row that creates a new Enemy variable, the two rows that change the x and y values and the two rows that add that Enemy variable to the stage and to the array. Replace the comment in the if statement above with these five rows of code. Remember to set the x and y values of the new Enemy object equal to the x and y values of mc!

Only one thing left. We have now gone through all the Enemy objects inside enemies_mc and used each of these to create new Enemy objects that have been added to the array and stage. We no longer need enemies_mc and after our for loops closing curly brace we write

removeChild(enemies_mc);

to remove that movieclip. Try your code! Don’t read on just yet. See if you can get the code to work first! 🙂

One problem might be that the new Enemy objects don’t end up exactly where the Enemy objects inside the enemies_mc are placed, even if you wrote e.x = mc.x; This is because mc is inside enemies_mc and it’s x and y values are relative to it’s container and not relative to the stage. For a full explanation of this concept read the excellent article Understanding Flash’s Coordinate Systems by Michael James Williams. The quick and simple answer is that you need to add the x and y values of enemies_mc by writing e.x = mc.x + enemies_mc.x;

My code looks like this. Does yours?

for (var i=0; i<enemies_mc.numChildren; i++) {
var mc = enemies_mc.getChildAt(i);
if (mc is Enemy) {
var e:Enemy = new Enemy;
e.x = mc.x + enemies_mc.x;
e.y = mc.y + enemies_mc.y;
addChild(e);
enemies.push(e);
}
}
removeChild(enemies_mc);

And that is how we can add enemies to the stage in Flash instead of using code. This was just one quick simple way to solve the problem. I’m sure there are several others and if you find one or have any questions or suggestion please comment.

2011/03/15 Posted by | Tutorials | , , , , , , | Leave a comment

2×2 pickups in each spawn using for loops

Lets say we want to have 2×2 pickups in each spawn using for loops. Maybe your pickup is ammo and you need more ammo pickups in order to balance the game. Having four pickups come each time in a 2×2 formation makes it harder to pick them all up but not impossible. This addon is a simple change to the newPickup function.

Remember that this addon is written for version 0.1 so if you are reading this from the future using some other version then there might be some small changes you’ll need to take into account.

First we need to change the line

var p:Pickup = new Pickup;

to separate the declaration and initiation by writing

var p:Pickup;
p = new Pickup;

This simply because we want to add a for loop and inside the loop we want to initialize a new p (second row) while keeping the declaration outside the loop (first row).

Now how do we write a for loop? If you dont remember you should read Step 2 of activetuts Loop article. Read it? Good! Lets continue. You know we want the loop to go around twice and in each loop create two pickups next to each other. Lets write the for loop like this

var p:Pickup;
for (var j:int=0; j<2; j++) {
p = new Pickup;

Where do we put the closing brace? Well we want the for loop to create the pickup and add it to the stage and our pickup array. So add the closing brace right before setNextPickup().

You can test your code now but we are only spawning two pickups now and they will both have random x values and not be next to each other. To fix this we first want to move the creation of slumpX out of the loop, like this

var p:Pickup;
var slumpX = 10 + Math.random()*530;
for (var j:int=0; j<2; j++) {

Now we only make the random number slumpX once outside the loop and can use that inside the loop to place our pickups in formation. We want to change p.x = slumpX so it uses the variable j from the loop for example like this

p.x = slumpX + j*10;

In our first round in the loop we know that j is zero so the first pickup will be placed on an x value of slumpX + 0*10 which will put the pickup at slumpX. Our next and last pickup will be placed at slumpX + 1*10 which means that 10 is how far to the right the second pickup will be placed. Try it out! Maybe you want your pickups closer or farther apart. A little beta testing will help determine that.

How would you write if you want to make sure that regardless of how wide the pickup is there will always be a distance of 10 between the two pickups? You would of course use the property width of the movieclip p by writing p.width like

p.x = slumpX + j*(p.width + 10);

Try it out!

So now we have two pickups spawn next to each other. Lets add another two by using another for loop. This second loop should be placed right around the first by starting before and finishing after like this

for (var i:int=0; i<2; i++) {
for (var j:int=0; j<2; j++) {

The first loop has a loop variable i that we can use in order to space out the pickups along the y axis. We need to change the line p.y = 10 by using the i variable just like we used the j variable to space out the x values.

p.y = 10 + i*(p.height + 10);

Now test the code! It should run and give you 2×2 pickups in each spawn. My code looks like this now

public function newPickup(te:TimerEvent) {
var p:Pickup;
var slumpX = 10 + Math.random()*530;
for (var j:int=0; j<2; j++) {
for (var i:int=0; i<2; i++) {
p = new Pickup;
p.x = slumpX + i*(p.width+10);
p.y = 10 + j*(p.height + 10);
addChild(p);
pickups.push(p);
}
}
setNextPickup();
}

If you understand this tutorial you should be able to add two or three enemies spawning next to each other in each spawn. Or every time you shoot instead of just one shot you could have two. Give it a try!

How can you make this addon better? What did I do wrong or less effective? Just comment below!

2011/03/13 Posted by | Tutorials | , | Leave a comment