Thursday, November 6, 2008

AS3 08 - Shooting Bullets

Continuing from the previous tutorials… Now that we got the clownShip moving about, we are going to make it shoot bullets. (Remember if you rename the main AS07.fla to AS08.fla and AS07.as to AS08.as, you need to re-link the class to the main document under the document properties to AS08.as… also… since the AS07.as is now AS08.as, you need to alter the public class name from ‘public class AS307 extends MovieClip’ to ‘public class AS308 extends MovieClip’.. and also… the constructor from ‘public function AS307()’ to ‘public function AS308()’. Please keep all these in mind)

Let’s create the bullet now. This is how my bullet look like… with 800 times magnification.


Yup… a simple circle. Convert it into a symbol and named it ‘myBullet’. Create a class for the bullet… myBullet.as. I hope these all makes sense or suffer the consequences for not reading my last tutorial… because I have already explain how to do all these in the previous tutorial. Now what we need to do is whenever the bullet is created :

It will start from the clownShip
It will move upward from the clownShip
Delete the bullet when going out of screen

So if you already have guessed it correctly, it needs the coordinates of the clownShip and then speed / direction it will move. Moving it upwards should be a loop event so we use the ENTER_FRAME event listener to trigger a function to move it upwards after the bullet has been created. When the bullet reaches beyond the top of the screen, we need to delete it. (The coordinate of a flash document starts from the top left corner and increases as it moves horizontal, x and vertical, y. So basically the top would be when y=0, the bottom would be when y = height of the document.). Then whenever we delete the bullet, we need to end it’s listener too. Don’t forget or you will let it loop to eternity and beyond!

A question arises on how do we manage so many bullets at one time? I mean how do we keep track of each bullet whenever it has been created / shoot? And the answer isssss….. array. Now what’s an array? Googling it would be a good idea as I can’t really explain that well due to my lack of wisdom. Create and array as a placeholder and push in a reference to each bullets to build up the array. Why do we need this? Well… it’s actually part of the next tutorial to loop through the bullet array to check for collision with the enemy object... I thought I would explain it here for easier understanding later on… but… well.. just remember that we put in an array to hold the reference to each bullet for the time being. Anyway the array should be in the main AS08.as class since it will be shared with other objects later on. The myBullet.as file should look like this.

Filename : myBullet.as

package {
import flash.display.*;
import flash.events.*;
import flash.utils.getTimer;

public class myBullet extends Sprite{

private var timeVal:int;
private var myspeed:Number;

public function myBullet(x,y,speed){
this.x = x;
this.y = y;
timeVal = getTimer();
myspeed = speed;
addEventListener(Event.ENTER_FRAME,moveBullet);

}

public function moveBullet(event:Event) {
var timeDiff:int = getTimer()-timeVal;
timeVal += timeDiff;

this.y += myspeed*timeDiff/1000;

if (this.y < 0) {
deleteBullet();
}
}

public function deleteBullet() {
MovieClip(parent).removeBullet(this);
parent.removeChild(this);
removeEventListener(Event.ENTER_FRAME,moveBullet);
}

}

}


I guess it’s pretty much self explanatory as most of the codes are seen on the previous tutorial except this little bugger one… parent.removeChild(this); It’s actually calling a function on the main parent class which is the AS08.as called removeChild… the part


if (this.y < 0) {
deleteBullet();
}



tells the flash player to call the deleteBullet function which takes it out of the array “MovieClip(parent).removeBullet(this)” and remove the bullet from screen “parent.removeChild(this)” and actually remove the listeners which are are not going to use anymore for that bullet “removeEventListener(Event.ENTER_FRAME,moveBullet)” since it’s deleted.

Anyway, the AS08.as look like this…

Filename : AS08.as

package {
import flash.display.*;
import flash.events.*;

public class AS308 extends MovieClip{

var leftdown,rightdown:Boolean = false;
var clownShip:myShip;
var mybullets:Array;

public function AS308(){

stage.addEventListener(KeyboardEvent.KEY_DOWN, listenKeyDown);
stage.addEventListener(KeyboardEvent.KEY_UP, listenKeyUp);

clownShip = new myShip(stage.stageWidth/2,stage.stageHeight - 40);
addChild(clownShip);
mybullets = new Array();
}

public function listenKeyDown(event:KeyboardEvent)
{
if (event.keyCode == 37) { //Left arrow
leftdown = true;
}
if (event.keyCode == 39) { //Right arrow
rightdown = true;
}
if (event.keyCode == 32) { //Spacebar
shootBullet();
}
}


public function listenKeyUp(event:KeyboardEvent)
{
if (event.keyCode == 37) { //Left arrow
leftdown = false;
}
if (event.keyCode == 39) { //Right arrow
rightdown = false;
}
}

public function shootBullet() {
var b:myBullet = new myBullet(clownShip.x,clownShip.y-20,-250);
addChild(b);
mybullets.push(b);
}

public function removeBullet(mybullet:myBullet) {
for(var i in mybullets) {
if (mybullets[i] == mybullet) {
mybullets.splice(i,1);
break;
}
}
}

}
}


I have declared


var clownShip:myShip;
var mybullets:Array;


at the base class because I am using them for the coordinates of the bullet and adding bullets into the array. Note the new


if (event.keyCode == 32) { //Spacebar
shootBullet();
}


.. is for the spacebar key… and also the new functions… shootBullet and removeBullet. shootBullet pass in the x and y-20 (why y-20? Because we want it to shoot from the tip of the front, not the middle of the ship…) coordinates of the clownShip along with the speed and direction of the bullet. Negative being moving up. 250 being moving 250 pixels per second. The removeBullet actuualy removes the bullet from the array via the splice function and breaks the loop once the item is found and removed seeing no point to go further after Neo is actually killed in the Matrix right?.

Test run the movie and see what happens. Hitting the spacebar should release the bullets from the ship. Looks nice?



Download SOURCECODE

Well, still think game programming is easy nice to dive in? Read on… err… next we will look into adding an enemy and check for collision detection with the bullets… that’s when you see why I put the array for… hohohoh… until then, kudos to The Empire of the Rising Sun for such wonderfully feeble looking tsunami tank…

No comments: