The Spawn Engine

an educational open source Flash game engine

How to add more class files

With this tutorial I’m going to show how to add more class files to the Spawn Engine. I’m using version 0.1.2 and CS5. We will add this to later versions of TSE but for now it’ll just be a tutorial showing you how to add it yourself and explaining why this is good practice.

Action Script 3 is an object oriented language (OOP). I’m not going into detail on what OOP is since there are plenty of articles out there doing a better job than I’d do. Check out these two!

First the steps, then we’ll discuss what we’ve won.

1) Right click in your library on the enemy movie clip and choose Properties. There is already a Class linked to this movie clip: Enemy. But that class don’t have any file, so we are going to make one now.

2) Click on the pen button “Edit class definition” and CS5 opens a new tab with an as-file for the class Enemy. The class is empty except for the basic structure (package, import, class and constructor). So we are going to move a few things from the engine to this class.

3) Save the file as Enemy.as in the same folder as your other files for this project.

4) Inside the Enemy class add the line

private var speed:int;

private const MIN_SPEED:int = 7;
private const MAX_DIFF_SPEED:int = 6;

This will be the move speed of the enemy movie clip which earlier was found in the engine. We need to remove it from the engine and only have this data inside the Enemy class.

5) Inside the public function Enemy (the constructor) we add the line

speed = MIN_SPEED + Math.random() * MAX_DIFF_SPEED;

We want each new enemy that is spawned to have its own unique speed. In version 0.1.2 all enemies have the same speed 9 set by a constant. What will the speed of these new enemies be?

6) Under the constructor we add a new function getSpeed that should look like

public function getSpeed():int
{
return speed;
}

Why did we do this?

7) There are a few changes that we need to do in SpawnEngine.as now. Find this lines of code and comment it so it looks like this

//private const ENEMY_SPEED:int = 9;

We no longer need this constant since that data is now stored inside each Enemy object.

8) Find this line

enemies[i].y += ENEMY_SPEED;

and rewrite it to

enemies[i].y += enemies[i].getSpeed();

We want to use the new function that returns the variable speed which now is a unique value for each Enemy object.

8) Test your changes! You should be able to see some enemies moving faster than others. If you want to change the minimum and maximum speed of the enemies you’ll need to go the the Enemy class file and change the constants we added in step 4.

What your Enemy.as should look like now

package {
import flash.display.MovieClip;
public class Enemy extends MovieClip
{
private var speed:int;
private const MIN_SPEED:int = 7;
private const MAX_DIFF_SPEED:int = 6;
public function Enemy()
{
// constructor code
speed = MIN_SPEED + Math.random()*MAX_DIFF_SPEED;
}
public function getSpeed():int
{
return speed;
}
}
}

Why did we do this?

This was just one small step in the right direction. We moved one piece of data, speed, from the engine into a separate class file. The engine don’t need to know everything and do everything. With more class files the engine will be shorter and more manageable. We put the functions and the variables where they belong, inside the class of the object. This also allows us to do things that were difficult to do before, like adding a unique speed to each enemy. Or maybe we want to add health to each enemy or some other value inside each enemy. This is much easier to do when the enemy has its own class. To improve the enemy class we could move more functionality to it from the engine. Each enemy can move itself instead of the engine doing the work for example.

Could we have done this differently?

Now we wrote the Enemy class to fit into the engine. I wanted to show this while making very small changes to the engine. We wrote a function getSpeed and we could of course have done that differently. We could have written a function inside the Enemy class where the enemy moves itself instead of a function that sends the speed to the engine so the engine can move the enemy. Had we written this class file at the same time we wrote the engine things would be different from now when we write the class file after the engine. Future versions of the engine will show this.

What’s next?

Now that we have done this small change on enemies you can do this for the pickups and more.

2012/03/07 Posted by | Tutorials | , , , | Leave a comment

Improved Collision Detection

Tutorial written by Leo “130x” Cederwall – leo.cederwall [at] gmail.com and edited by Niklas Mårdby (marten@work).

[ edit: My students are working hard on writing tutorials for the add-ons they have coded to the Spawn Engine. Over the next few weeks these tutorials will appear here. //Niklas ]

As you will have noticed, the Spawn Engine uses the hitTestObject which isn’t completely satisfactory when checking collisions between objects in the game. We need an improved collision detection. Let’s start with importing a necessary library. Write at the top of the package where the other imports are.

import flash.geom.Rectangle;

Lets also define a new variable which is the Collision object we will use when checking collisions.

private var collisiondetection:Collision=new Collision();

As you see we are going to use a Collision class. More about this at the end of the tutorial.

Now we need to change a few things in checkBulletEnemyCollissions and checkPickups. We need to replace hitTestObject and use a new function checkCollision instead.

Change ”if ( player.hitTestObject ( enemies[i ] ) )” to ”if ( checkCollision (player, enemies[i] ) )” and ”if ( player.hitTestObject ( pickups[i ] ) )” to ”if ( checkCollision (player, pickups[i] ) )”.

Last thing is to define the checkCollision function by writing:

function checkCollision(target1_mc:MovieClip, target2_mc:MovieClip):Boolean
{
var collisionRect:Rectangle = collisiondetection.getCollision (target1_mc,target2_mc);
if (collisionRect != null && collisionRect.width > 0 && collisionRect.height > 0)
{
return true;
}
else
{
return false;
}
}

[edit: As you see this function has two parameters and returns a Boolean. The two parameters are two MovieClip objects that we call target1_mc and target2_mc. These two could be a bullet and the player or any two movieclips you want to check if they collide. The first thing we do in the function is to create a Rectangle and to set the size of it we use the Collision class function getCollision. Now if the two movieclips are overlapping then the rectangle will have a width and height. If so, return the value true to checkBulletEnemyCollissions or where you called checkCollision from. //Niklas ]

And then also put the Collision.as file in your flash projects directory. The code for that file is below. Credits to Frederik Humblet och Grant Skinner for their work!

/*
Collision detection by Frederik Humblet
(c) Boulevart N.V.
http://labs.boulevart.be

Port from the AS2 version by Grant Skinner
http://www.gskinner.com/blog/archives/2005/08/flash_8_shape_b.html
*/
package {
import flash.geom.Rectangle;
import flash.geom.Point;
import flash.geom.Matrix;
import flash.geom.ColorTransform;
import flash.display.DisplayObject;
import flash.display.DisplayObjectContainer;
import flash.display.BitmapData;
import flash.display.Bitmap;
import flash.display.BitmapDataChannel;
import flash.display.BlendMode;
public class Collision {
public function getCollision(target1:DisplayObject,target2:DisplayObject,tollerance:Number=0):Rectangle {
var res:Rectangle;
if (target1.parent==target2.parent) {
var par:DisplayObjectContainer=target1.parent;
var rect1:Rectangle=target1.getBounds(par);
var rect2:Rectangle=target2.getBounds(par);
var isIntersecting:Boolean=rect1.intersects(rect2);
if (isIntersecting) {
var combinedrect:Rectangle=rect1.union(rect2);
var alpha1:BitmapData=getAlphaMap(target1,combinedrect,BitmapDataChannel.RED,rect1);
var alpha2:BitmapData=getAlphaMap(target2,combinedrect,BitmapDataChannel.GREEN,rect2);
alpha1.draw(alpha2,new Matrix,new ColorTransform(),BlendMode.LIGHTEN);
if (tollerance>1) {
tollerance=1;
}
if (tollerance<0) {
tollerance=0;
}
var colorsearch:uint;
if (tollerance==0) {
colorsearch=0x010100;
} else {
var tollByte:Number=Math.round(tollerance*255);
colorsearch=(tollByte<<16)|(tollByte<<8)|0;
}
res=alpha1.getColorBoundsRect(colorsearch,colorsearch);
res.x+=combinedrect.x;
res.y+=combinedrect.y;
return res;
}
}
return res;
}
private function getAlphaMap(target:DisplayObject,rect:Rectangle,channel:uint,myrect:Rectangle):BitmapData {
var bmd:BitmapData=new BitmapData(rect.width,rect.height,true,0);
var m:Matrix=new Matrix();
var offX:Number=target.x-myrect.x;
var offY:Number=target.y-myrect.y;
var xpos:Number=myrect.x+offX-rect.x;
var ypos:Number=myrect.y+offY-rect.y;
m.translate(xpos,ypos);
bmd.draw(target,m);
var alphachannel:BitmapData=new BitmapData(rect.width,rect.height,false,0);
alphachannel.copyChannel(bmd,bmd.rect,new Point(0,0),BitmapDataChannel.ALPHA,channel);
return alphachannel;
}
public function getCollisionPoint(target1:DisplayObject,target2:DisplayObject,tollerance:Number=0):Point {
var pt:Point;
var collisionRect:Rectangle=getCollision(target1,target2,tollerance);
if (collisionRect!=null && collisionRect.size.length>0) {
var xcoord:Number=(collisionRect.left+collisionRect.right)/2;
var ycoord:Number=(collisionRect.top+collisionRect.bottom)/2;
pt=new Point(xcoord,ycoord);
}
return pt;
}
public function isColliding(target1:DisplayObject,target2:DisplayObject,tollerance:Number=0):Boolean {
var collisionRect:Rectangle=getCollision(target1,target2,tollerance);
if (collisionRect!=null && collisionRect.size.length>0) {
return true;
} else {
return false;
}
}
}
}

Comment below if you have questions, ideas or anything else relating to this tutorial.

2011/03/27 Posted by | Tutorials | | Leave a comment

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

Connect your animation to code

Sometimes you want to connect your animation to code.

In the engine now we only have very basic graphics and not really any animations. Lets say you want to have the players object be a space ship and when you press the right key the ships movieclip somehow reflect that it is moving to the right. Maybe the wings tilt or the engine exhaust point differently. How do we connect this in the movieclip to the code in the engine?

Well first you need to change your movieclip. I’ve added a flame coming out the rear of the ship. Inside the player movieclip I’ve added two new key frames. On the first key frame the flame points straight down. This frame I’ve named “forward”. On the second frame I’ve rotated the flame slightly so the bottom of the flame points to the left. This frame we name “right”. The last frame has the flame pointing to the right and this frame we name “left”.

So we now have our player movieclip with three different frames. When I press the right key we want the movieclip to show the frame named “right”. When I press the left key we want the movieclip to show the frame named “left”. And last we want the movieclip to go back to the frame “forward” whenever no key is pressed.

Before we go into the engine and connect your animation to code we need to stop the movieclip from animating through the three frames. On the first frame of the movieclip you need to add the code stop(); on the timeline. We don’t like code on the timeline but this time it’s necessary.

Next up we go into the engine. We first need to change the movePlayer function. The if statement checks which Boolean variable, or flag, is set telling us which key is pressed. Here we need to use gotoAndStop. Change the code like this:

if (rightArrow) {
player.x += speed;
player.gotoAndStop(“right”);
}

What it means to say player.gotoAndStop(“right”) is that we want the movieclip connected to player to go to the frame “right” and stop there. We need the same to happen when we press the left key.

if (leftArrow) {
player.x -= speed;
player.gotoAndStop(“left”);
}

If you run your game now you’ll notice that it works fine except for one thing. When you press the right key the animation changes but it doesn’t go back to normal when you release the right key. The same for the left key. So we need to change keyUpFunction to look like this:

if (event.keyCode == 37) {
leftArrow = false;
player.gotoAndStop(“forward”);
}

This way we go back to the first key frame of the animation when the key is released. Add the line player.gotoAndStop(“forward”); to the else if statement that checks if the keyCode is 39.

So now we have shown how to use gotoAndStop in order to change the frame of a movieclip. There is also a gotoAndPlay which we will look at another time.

And that is how you connect your animation to code. I hope it helps some and that you try it out! Post a comment if you have any questions or suggestions!

2011/03/12 Posted by | Tutorials | | Leave a comment

Zigzag moving enemies

For this tutorial I’m using version 0.1 and adding zigzag moving enemies. Instead of just having the enemies spawn and move straight down (making them very easy to shoot) we want them to move from side to side. We will not make them move in an actual wave this time, since I don’t want to make this overly complicated math-wise. We will look at that later.

The first thing we will do is add these two variables among our other variables:

private var enemyWaveWidth:int = 30;
private var enemySideSpeed:int = 2;

These two variables tells the engine first how far to the side from the enemies spawn point the enemy will move and then how fast the enemy will move sideways. Experiment with other values.

Next up we need to change the newEnemy function. When we spawn an enemy we need to add a few things. We want a direction on each enemy, either right or left. This should be random so not all enemies move the same. After the lines of code when we create the e and change its x and y we add these lines:

if (Math.random() >= 0.5)
e.sideSpeed = enemySideSpeed;
else
e.sideSpeed = enemySideSpeed * -1;

Now that we have added a direction and speed to the enemy we want to add the boundaries to the left and right so the enemy knows how far to zig and zag. This is why we added the enemyWaveWidth variable. I want the boundaries to vary from enemy to enemy so I’ve added randomness to my code. First the basic version:

e.maxRight = e.x + enemyWaveWidth;
e.maxLeft = e.x – enemyWaveWidth;

This only tells the enemy how far to the left and right to move the enemy. Notice that we use the x- and y-value of the enemy.

If we want some randomness we could instead of writing the two lines of code above use the following:

var randomWaveWidth = (enemyWaveWidth/2) * Math.random() + (enemyWaveWidth/2);
e.maxRight = e.x + randomWaveWidth;
e.maxLeft = e.x – randomWaveWidth;

This will give each enemy a unique wave width. In my code above I use the enemyWaveWidth and my enemies will have a wave width somewhere between half enemyWaveWidth and a full enemyWaveWidth.

Now we are almost done. We only need to fix the moveEnemies function. After we have updated the enemy y-value we need to add a line of code to also change the x-value moving the enemy sideways:

enemies[i].x += enemies[i].sideSpeed;

But this will move the enemy in one direction only. In order to change that we add these lines right after:

if ( enemies[i].x >= enemies[i].maxRight || enemies[i].x <= enemies[i].maxLeft )
enemies[i].sideSpeed *= -1;

If the x-value of the enemy is equal or greater than the enemy max value on either the right or left side we switch the direction of the sideSpeed variable by simply switching sign (negative to positive or the other way around).

And thats it! Now you have zigzag moving enemies. Maybe you didn’t want your enemies to move like this, but instead your pickups. You should be able to fix that using this tutorial.

If you have any suggestions or questions just post a comment!

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