The next part to making this game is to allow the player to shoot on a click of the mouse. To do this I need a movieclip for the bullet, and I'm going to need a whole lot of variables in the code. Because there can be more than one bullet on screen at a time I'll need arrays to hold all the bullet data. For each bullet I need to know its x and y coordinates, its x and y speeds, its rotation speed (the bullets will rotate), how much damage it does to the enemy, how much it pushes the enemy back, and an ID number which identifies which bullet I'm working with. So I need to create arrays for all of these variables. I'm not sure if there is a more efficient way of doing this, but if there is, let me know in the comments!
The next thing I need is a few functions to control the bullets. I need a function to create bullets, a function to move the bullets every frame, and a function to remove the bullets once they leave the screen.
I'll run through the code function by function:
Function makebullet()
function makebullet(){
//bullet appears at end point of barrell
//bl = barrell length, barrell_rad = barrell angle in radians
bxl = Math.cos(barrell_rad) * bl;
byl = Math.sin(barrell_rad) * bl;
bullet_xs[bulletcount] = gunbarrell._x + bxl;
bullet_ys[bulletcount] = gunbarrell._y + byl;
bulletspeed = 10;
//split bulletspeed into an x and y value
ratio = bulletspeed / bl;
bullet_xspeeds[bulletcount] = bxl * ratio;
bullet_yspeeds[bulletcount] = byl * ratio;
bullet_rspeeds[bulletcount] = 10; //rotation speed
bullet_hps[bulletcount] = 10; //damage
bullet_powers[bulletcount] = 4; //repelling power
bullet_IDs[bulletcount] = nextbulletID;
//attach a new instance of bullet from the library with name bullet_1, bullet_2 etc.
bul = _root.attachMovie("bullet","bullet_"+nextbulletID,_root.getNextHighestDepth());
bul._x = bullet_xs[bulletcount]; //position the movie clip
bul._y = bullet_ys[bulletcount];
nextbulletID++; //increment IDs
bulletcount++; //increment bullet count
}
This function will create a new bullet. It will be called whenever the mouse is clicked. The comments in this function make it pretty self explanatory but I'll run through it quickly.
Lines 4 - 7 are finding the end point of the barrell which is also the start point of the bullet.
Line 8 sets the speed of the bullet
Lines 11 - 13 convert the bullets speed into an x and y value
Lines 14 - 17 set up all the other properties of the bullet
Lines 20 - 22 create the bullet and move it into position
Lines 23 and 24 increment the variables bulletcount and nextbulletID.
You might wonder why I have two variables, bulletcount and nextbulletID. This is because bulletcount will be decremented when a bullet is removed (or goes off) the screen but nextbulletID will always increment.
Function bulletstep()
function bulletstep(){
for (a=0;a<bulletcount;a++){ //step through the array from 0
curID = bullet_IDs[a]
bullet_xs[a] += bullet_xspeeds[a]; //change x and y values based
bullet_ys[a] += bullet_yspeeds[a]; //on xspeed and yspeed
_root['bullet_'+curID]._x = bullet_xs[a]; //apply new positions to
_root['bullet_'+curID]._y = bullet_ys[a]; //relevant bullet on screen
_root['bullet_'+curID]._rotation += bullet_rspeeds[a]; //rotate bullet
bulletcheck(a); //check screen boundaries etc.
}
}
This function will be called every frame, so 30 times a second, and will move the bullets across the screen. Again pretty self explanatory but I'll run through it.
Line 2 - a loop that steps through the array from 0 with the variable a representing position in the array.
Line 3 - Get the ID of the current bullet.
Lines 4 and 5 - change the x and y values of the bullet based on the speed.
Lines 6 and 7 - apply the new position to the bullet on screen.
Line 8 - rotate the bullet, just cos it looks cool.
Line 9 - calls a function which we'll write in a second.
It took me a while to figure out that you can dynamically reference attached movieclips based on variables using the block brackets [ ] like this :
_root['bullet_'+curID]so that's pretty cool. Well it's not cool that it took me a while to figure it out but it's cool that you can do that...anyway on to the next function!
Function bulletcheck(arraypos:Number)
function bulletcheck(arraypos:Number){
cx = _root['bullet_'+bullet_IDs[arraypos]]._x; //get x and y position
cy = _root['bullet_'+bullet_IDs[arraypos]]._y;
//check stage boundaries
if (cx < stagexmin || cx > stagexmax || cy < stageymin || cy > stageymax){
killbullet(arraypos);
}
}
Ok, this one is very simple. For the given array position it checks if the bullet is outside the stage boundaries. If it is it calls a function killbullet(arraypos) which will destroy the bullet.
Function killbullet(arraypos:Number)
function killbullet(arraypos:Number){
removeMovieClip(_root['bullet_'+bullet_IDs[arraypos]]); //remove the bullet
if (!(arraypos == (bulletcount - 1))){ //if its not the end of the array
for (i = arraypos+1;i<bulletcount;i++){ //then move everything in the array
bullet_xs[i-1] = bullet_xs[i]; //above this point down one position
bullet_ys[i-1] = bullet_ys[i];
bullet_xspeeds[i-1] = bullet_xspeeds[i];
bullet_yspeeds[i-1] = bullet_yspeeds[i];
bullet_rspeeds[i-1] = bullet_rspeeds[i];
bullet_powers[i-1] = bullet_powers[i];
bullet_hps[i-1] = bullet_hps[i];
bullet_IDs[i-1] = bullet_IDs[i];
}
}
bulletcount--; //decrement bullet count
}
Again a pretty simple function, this one removes the movieclip from the stage and, if this bullet is not the last one in the array it moves all the higher array elements down once...if that makes sense? LOL it makes sense in my head but I'm getting tired now! ANYWAY, if it IS the last element in the array then you don't need to worry, because the data will be overwritten later.
The last little bit of code we need calls bulletstep every time the gunbarrell enters frame, which is every frame because gunbarrell is attached in the first line of code.
gunbarrell.onEnterFrame = function(){
bulletstep();
}
So the complete code now looks like this, and it works. The barrel will follow the mouse pointer and a projectile will be fired when the mouse is clicked. There is a reload time so the gun won't fire as fast as the mouse is clicked. Test it out below!
_root.attachMovie ("gunbarrell","gunbarrell",_root.getNextHighestDepth())
gunbarrell._x = 275;
gunbarrell._y = 780;
//bullet vars
bullet_xs = new Array()
bullet_ys = new Array();
bullet_xspeeds = new Array();
bullet_yspeeds = new Array();
bullet_rspeeds = new Array(); //rotation speed
bullet_powers = new Array(); //amount the bullet repels enemies
bullet_hps = new Array(); //amount of damage done by the bullet
bullet_IDs = new Array();
bulletcount = 0; //how many bullets exist at the moment
shottimer = 0; //controls shooting speed
stagexmin = 0; //stage boundaries
stagexmax = 550;
stageymin = 0;
stageymax = 800;
nextbulletID = 0;
curID = 0;
reloadspeed = 200; //lower number = faster reload speed
bl = gunbarrell._height;
gunbarrell.onEnterFrame = function(){
bulletstep();
}
onMouseDown = function () { //when the mouse is clicked
timesinceshot = getTimer() - shottimer;
if (timesinceshot >= reloadspeed){
shottimer = getTimer();
makebullet();
}
}
onMouseMove = function () { //when mouse is moved
mouse_xdist = _root._xmouse-gunbarrell._x;
mouse_ydist = _root._ymouse-gunbarrell._y;
// calculate the angle
barrell_rad = Math.atan2(mouse_ydist, mouse_xdist);
// convert to degrees and set rotation
barrell_angle = toDeg(barrell_rad) + 90;
gunbarrell._rotation = barrell_angle;
}
function toDeg(Rad:Number){return (Rad * 180 / Math.PI);}
function makebullet(){
//bullet appears at end point of barrell
//bl = barrell length, barrell_rad = barrell angle in radians
bxl = Math.cos(barrell_rad) * bl;
byl = Math.sin(barrell_rad) * bl;
bullet_xs[bulletcount] = gunbarrell._x + bxl;
bullet_ys[bulletcount] = gunbarrell._y + byl;
bulletspeed = 10;
//split bulletspeed into an x and y value
ratio = bulletspeed / bl;
bullet_xspeeds[bulletcount] = bxl * ratio;
bullet_yspeeds[bulletcount] = byl * ratio;
bullet_rspeeds[bulletcount] = 10; //rotation speed
bullet_hps[bulletcount] = 10; //damage
bullet_powers[bulletcount] = 4; //repelling power
bullet_IDs[bulletcount] = nextbulletID;
//attach a new instance of bullet from the library with name bullet_1, bullet_2 etc.
bul = _root.attachMovie("bullet","bullet_"+nextbulletID,_root.getNextHighestDepth());
bul._x = bullet_xs[bulletcount]; //position the movie clip
bul._y = bullet_ys[bulletcount];
nextbulletID++; //increment IDs
bulletcount++; //increment bullet count
}
function bulletstep(){
for (a=0;a<bulletcount;a++){ //step through the array from 0
curID = bullet_IDs[a]
bullet_xs[a] += bullet_xspeeds[a]; //change x and y values based
bullet_ys[a] += bullet_yspeeds[a]; //on xspeed and yspeed
_root['bullet_'+curID]._x = bullet_xs[a]; //apply new positions to
_root['bullet_'+curID]._y = bullet_ys[a]; //relevant bullet on screen
_root['bullet_'+curID]._rotation += bullet_rspeeds[a]; //rotate bullet
bulletcheck(a); //check screen boundaries etc.
}
}
function killbullet(arraypos:Number){
removeMovieClip(_root['bullet_'+bullet_IDs[arraypos]]); //remove the bullet
if (!(arraypos == (bulletcount - 1))){ //if its not the end of the array
for (i = arraypos+1;i<bulletcount;i++){ //then move everything in the array
bullet_xs[i-1] = bullet_xs[i]; //above this point down one position
bullet_ys[i-1] = bullet_ys[i];
bullet_xspeeds[i-1] = bullet_xspeeds[i];
bullet_yspeeds[i-1] = bullet_yspeeds[i];
bullet_rspeeds[i-1] = bullet_rspeeds[i];
bullet_powers[i-1] = bullet_powers[i];
bullet_hps[i-1] = bullet_hps[i];
bullet_IDs[i-1] = bullet_IDs[i];
}
}
bulletcount--; //decrement bullet count
}
function bulletcheck(arraypos:Number){
cx = _root['bullet_'+bullet_IDs[arraypos]]._x; //get x and y position
cy = _root['bullet_'+bullet_IDs[arraypos]]._y;
//check stage boundaries
if (cx < stagexmin || cx > stagexmax || cy < stageymin || cy > stageymax){
killbullet(arraypos);
}
}
I think I might have to muck around with the size of the stage because it looks a lot bigger on the blog than it does in cs3. Anyway that's enough for tonight, I'm going to have a drink!