Tutorials

February 10, 2009

AS3 Flash Games for Beginners: Firing Weapons with Delays

More articles by »
Written by: Par
Tags: , , , ,
basics2_tn

Share on TwitterShare on TumblrSubmit to StumbleUponSave on DeliciousDigg ThisSubmit to reddit

So you need to create a weapon, maybe a laser, and you want your character to fire the weapon. At the same time, you want a nice delay between firing each round instead of a crazy Gatling gun effect. Well this Flash tutorial is for you. We’re going to learn to make our Spaceship fire lasers with a nice timeout between each fire. To do this we’re going to use AS3 Timers, so get ready to use a timer and create the perfect delay for your laser.

This article is the fifth in the series: AS3 Flash Games for Beginners.  If you haven’t kept up with the previous tutorials you may want to use the links above and start from the beginning. If you are just wanting to learn this portion of the tutorial, download the source code from the previous tutorial and follow along.

Step 1: Creating a Laser

So in order to fire our weapon, we’re going to need a graphic of what we are firing.  If you wish you create your own graphic or find one somewhere online, feel free.  I’ve took the liberty of making a laser we can use in Photoshop.  It’s a simple 6×19 png of a  2 pixel width white line surrounded by a blue glow with a blue to white gradient over it.  I know if you need a good photoshop tutorial that quick description didn’t help but if you want some photoshop help just drop us a line on the contact page and request it.  Anyway, here’s the png file, just download it to your computer and use it (Right Click and Save As).

PNG file of our laser projectile... because PNGs have transparency it will lay seemlessly in our Flash Game

Now to load a PNG, JPEG, GIF, or any graphical asset into Flash we use  File -> Import -> Import to Library.  Just select our laser file and open it.  Now you will have laserblue.png in your Library (CTRL + L) and likely a Symbol1 file. If you have a Symbol1 of type graphic… delete it.  For this tutorial series we are only going to use MovieClips, so take your laserblue.png drop it on the stage, right click and Convert to Symbol… name it LaserBlue, make it a MovieClip, set the Registration to middle bottom, and go ahead a set the linkage up.  Export it for ActionScript and make the class be com.asgamer.basics1.LaserBlue. Click OK and tell Flash you don’t care that the class isn’t created.  The image below should clear up any confusion.

Creating our blue laser to work with ActionScript

Creating our blue laser to work with ActionScript

Now you can delete our newly created MovieClip of the laser from the stage. Now let’s figure out how we are going to make this laser work.  The goal is to make the laser fire and move forward by a variable amount of pixels at every frame. This should be simple. Create a new file called BlueLaser.as under our com.asgamer.basics1 directory and fill it with this code.

package com.asgamer.basics1
{
 
	import flash.display.MovieClip;
	import flash.display.Stage;
	import flash.events.Event;
 
	public class LaserBlue extends MovieClip
	{
 
		private var stageRef:Stage;
		private var bulletSpeed:Number = 16;
 
		public function LaserBlue (stageRef:Stage, x:Number, y:Number) : void
		{
			this.stageRef = stageRef;
			this.x = x;
			this.y = y;
 
			addEventListener(Event.ENTER_FRAME, loop, false, 0, true);
		}
 
		private function loop(e:Event) : void
		{
			//move bullet up
			y -= bulletSpeed;
 
			if (y < 0)
				removeSelf();
		}
 
		private function removeSelf() : void
		{
			removeEventListener(Event.ENTER_FRAME, loop);
 
			if (stageRef.contains(this))
					stageRef.removeChild(this);
		}
 
	}
 
}

Alright, this code is pretty straight forward… but let’s break it down.

  • First we have a series of imports, the name of our class which extends MovieClip, two class variables that are very familar to things we’ve already done, and then our constructor function.
  • public function LaserBlue (stageRef:Stage, x:Number, y:Number) : void. We’re passing through 3 things. Our stage reference, an x value and a y value.  These x and y values will be used to set our lasers initial x and y position as seen by this.x = x and this.y = y only a few lines down.
  • addEventListener(Event.ENTER_FRAME, loop, false, 0, true); This means we’re going to do something every frame. In our case move our laser by calling the loop function.
  • Our loop function first of all moves the y of the laser up by 16 (bulletSpeed) pixels every frame.  You can change this if you think it’s too slow or too fast.
  • if (y < 0) removeSelf(); So here’s the deal… We really don’t want our laser to leave the stage and continue flying on forever.  I mean, first of all, it’s pointless, but most importantly it’s going to lag our game.  So if our laser has a y less than zero it’s off the screen (because we set our Registration point to the bottom) and we can remove it.   To remove it we call our function removeSelf(), which I’m about to explain.
  • removeEventListener(Event.ENTER_FRAME, loop); Okay we don’t want Flash to continue running the loop function on every enter frame if we are deleting our laser.  So we remove the event listener… However, we did set weak referencing to true when we created the listener and Flash should remove the bullet from memory even if we leave the event listener going.  But let’s avoid the rest and remove it ourselves.
  • if (stageRef.contains(this)). contains is a function that classes inheriting from DisplayObjectContainer can call. You pass a DisplayObject into the function and it returns a Boolean of true if the object is inside it, and false if it is not inside. So we are checking if our laser is contained by the stage, if so run this next line of code.
  • stageRef.removeChild(this); This can be risky… which is why we check to make sure stageRef contains the laser before we run it.  But what if we didn’t add our laser to the stage? What if we wanted to add it to a MovieClip called Game in one case and the stage in another.  Well, if you are going to write code this way, you need to make sure you know where you are going to be using this class always. In our case we are safe, we’ll only drop lasers onto the stage.  So the removeChild() function removes our laser from the stage (because we pass it through by using this)

So great! We made a laser that our ship can fire… but our ship doesn’t know how to fire it yet. Time to enhance our ship!

Step 2: Making Our Ship Fire Laser Projectiles

That just sounds sweet. So let’s make it sweet.  Open our Ship class and let’s make some changes. First we’re going to add, a check for the spacebar being pressed, under where we check for up and down keypresses. If it’s pressed we’ll call a function that fires our laser. We’ll call it fireBullet();.  The new key check will look like this.

			if (key.isDown(Keyboard.SPACE))
				fireBullet();

That’s so simple, I probably don’t need to break it down. Here’s the jist, we press space and fireBullet() gets called! Pie work. One thing though, we need a fire bullet function. Here it is:

		private function fireBullet() : void
		{
				stageRef.addChild(new LaserBlue(stageRef, x+vx, y - 10));
		}

Wow, seriously, this is pretty simple too. Probably so simple, you’re asking me why I even created the fireBullet function.  We’ll we may want to make other ways to fire bullets later so we’ll want to be able to call it… but most importantly we’ve got to add the delay code and we’re going to put it in fireBullet.

Here’s the breakdown of our one line of code:

  • stageRef.addChild. you’ve done this before. We’re just adding our laser to the stage.
  • new LaserBlue(stageRef, x+vx, y – 10). We’re creating a new laser here. Passing it the stage, then if you remember we send in the initial x and y value of our laser.  So it’s initial x needs to be our ships x plus our ships current velocity (this is because velocity isn’t updated when fire laser is called). y – 10 moves the lasers initial position up because our ships registration is in the center.  If we just passed y in, our laser would be coming out of the middle of our ship. Could look good in some instances… but not for my ship.  If you’ve created our own ship you’ll want to adjust your lasers start position accordingly.

So now we run the code and we get this: (SPACE fires lasers, ARROWS move)

Alright so this thing fires lasers like there is no tomorrow. Cool but not what we want. We want a reasonable delay between weapon firing. So we got a lot of code to add…. We’re going to need a Timer. Timer’s allow us to execute code on a delay. I can tell the timer I want a function to run three tenths of a second later and it will wait that long, then run. So if we want our weapon to delay, a great solution is a Timer.

So here’s our new code with all the Timer functions and data in it. Don’t freak out, I’ll break it down afterwards:

package com.asgamer.basics1
{
 
	import flash.display.MovieClip;
	import flash.display.Stage;
	import com.senocular.utils.KeyObject;
	import flash.ui.Keyboard;
	import flash.events.Event;
	import flash.utils.Timer;
	import flash.events.TimerEvent;
 
	public class Ship extends MovieClip
	{
 
		private var stageRef:Stage;
		private var key:KeyObject;
		private var speed:Number = 0.5;
		private var vx:Number = 0;
		private var vy:Number = 0;
		private var friction:Number = 0.93;
		private var maxspeed:Number = 8;
 
		//fire related variables
		private var fireTimer:Timer; //causes delay between fires
		private var canFire:Boolean = true; //can you fire a laser
 
		public function Ship(stageRef:Stage)
		{
			this.stageRef = stageRef;
			key = new KeyObject(stageRef);
 
			//setup your fireTimer and attach a listener to it.
			fireTimer = new Timer(300, 1);
			fireTimer.addEventListener(TimerEvent.TIMER, fireTimerHandler, false, 0, true);
 
			addEventListener(Event.ENTER_FRAME, loop, false, 0, true);
		}
 
		public function loop(e:Event) : void
		{
			//keypresses
			if (key.isDown(Keyboard.LEFT))
				vx -= speed;
			else if (key.isDown(Keyboard.RIGHT))
				vx += speed;
			else
				vx *= friction;
 
			if (key.isDown(Keyboard.UP))
				vy -= speed;
			else if (key.isDown(Keyboard.DOWN))
				vy += speed;
			else
				vy *= friction;
 
			if (key.isDown(Keyboard.SPACE))
				fireBullet();
 
			//update position
			x += vx;
			y += vy;
 
			//speed adjustment
			if (vx > maxspeed)
				vx = maxspeed;
			else if (vx < -maxspeed)
				vx = -maxspeed;
 
			if (vy > maxspeed)
				vy = maxspeed;
			else if (vy < -maxspeed)
				vy = -maxspeed;
 
			//ship appearance
			rotation = vx;
			scaleX = (maxspeed - Math.abs(vx))/(maxspeed*4) + 0.75;
 
			//stay inside screen
			if (x > stageRef.stageWidth)
			{
				x = stageRef.stageWidth;
				vx = -vx;
			}
			else if (x < 0)
			{
				x = 0;
				vx = -vx;
			}
 
			if (y > stageRef.stageHeight)
			{
				y = stageRef.stageHeight;
				vy = -vy;
			}
			else if (y < 0)
			{
				y = 0;
				vy = -vy;
			}
 
		}
 
		private function fireBullet() : void
		{
			//if canFire is true, fire a bullet
			//set canFire to false and start our timer
			//else do nothing.
			if (canFire)
			{
				stageRef.addChild(new LaserBlue(stageRef, x + vx, y - 10));
				canFire = false;
				fireTimer.start();
			}
 
		}
 
		//HANDLERS
 
		private function fireTimerHandler(e:TimerEvent) : void
		{
			//timer ran, we can fire again.
			canFire = true;
		}
 
	}
 
}

Alright let’s break it down:

  • First of all we added two new imports. flash.utils.Timer and flash.events.TimerEvent.  These are the classes we need to work our timer.
  • Next, two new class variables fireTimer:Timer and canFire:Boolean. fireTimer is the timer we will use to delay our bullet fire and canFire if true will let us fire a bullet, when it’s false we can’t fire. We’ll get to how that works later.
  • fireTimer = new Timer(300, 1); Here we create our new Timer.  The first parameter it excepts is the milisecond delay between each time the timer fires. We’ve set it to 300 miliseconds… or 3 tenths of a second. Second is how many times we want the timer to repeat. If we don’t set it, it will repeat infinitely, every 300 miliseconds the timer would fire.  We’re setting it to fire once because we want it to work one timer after our delay is over only.
  • fireTimer.addEventListener(TimerEvent.TIMER, fireTimerHandler, false, 0, true); This is our event listener. Each time our timer fires, the fireTimerHandler function is called.  It’s also weak referenced because we set the last parameter to true.
  • Now we update our fireBullet function. We wrap our creating a new LaserBlue in an if statement, if (canFire). So if canFire is true we create our laser, set canFire to false, and start our fireTimer.  Since canFire is set to false we won’t be able to fire again until canFire is set back to true. To do this we start our fireTimer with fireTimer.start(). So after our delay occurs (300 miliseconds in our case)  fireTimerHandler will be ran because we set it with our listener above.
  • private function fireTimerHandler(e:TimerEvent) : void. This is our function that get’s called when our timer fires.  We catch the event in the variable e (we don’t need it in this case, but we have to catch it).  All this function does is set canFire back to true so we can fire another laser.

All that put together sets us up perfectly to fire lasers with a delay. Compile your script and you’ll get something like this:

Alright this tutorial is complete. Download the source here: Firing Weapons with Delays

And jump on over to the next tutorial in the series:
Learn How to Make Enemies with Basic AI!!!

Similar Posts:


Share on TwitterShare on TumblrSubmit to StumbleUponSave on DeliciousDigg ThisSubmit to reddit


About the Author

Par
Hey! Don't be surprised, I'm a flash developer. While Flash is definitely one of my favorite languages to develop in, most of all I just like making games. If you want to see the games I've developed so far head over to my website, DigitallyBold, in the link below. If you want to know more about what I'm working on now and in the future be sure to follow me on twitter.




28 Comments


  1. Brent

    Love the site so far, keep it up! You have a few subtle differences in your programming style that helped me learn a few things I didn’t know about, I’m fairly new to the OOP approach and found it very useful.

    If you don’t mind, I’d like to request that after you have the gameplay elements tutorials finished, you could flesh this out to encompass menus, level selection, preloaders…all the code needed to wrap around and polish a game. Lots of tutorials are good about getting into the nuts and bolts of AS3 gameplay, but I haven’t seen much to help folks out with with organizing their classes in such a way that they can expand the game and produce a finished product while avoiding putting code into the timeline. I think you have the opportunity here to produce the most complete as3 game creation tutorial I’ve managed to find. You could probably package the final product up into an ebook or something and make a few bucks, this is off to a better start than all of the examples in the FlashGameU book.


  2. Thanks a lot for a good tutorial. I walked through it from the start and found it understandable and meaningful. I even managed to customize it slightly. though, i didn’t seem to have the skill to incorporate some new ideas that I had.

    first I wanted to do as you suggest after the first chapter, and import the background by AS. when I do this It places it self on top of the shooting stars. I know there is some system of ranking the objects in a layer like system, but I’m not successful in finding out how.

    second I would like to manipulate the direction of the bullets on the x axis. so when the ship rotates slightly to one side it also shoots this direction. this would add a great deal to a finished shooting game.

    do you have any suggestions for this?

    thanks again for making AS3 accessible for a brick-wall-brain like my self.


  3. Par

    Great suggestions guys. We’ll definitely be looking into and writing tutorials on both of them. Seriously, both comments are GREATLY appreciated.

    Jonas, your stars being behind the background problem is likely a simple one. Each time you call addChild that child gets added to the top of the display list. When we call addChildAt… it gets dropped where we tell it. You need your background to be on the absolute bottom. So add it first before anything else.

    Second… your stars we’re using addChildAt to make sure they appear under the ship. So instead of calling addChildAt(1) let’s add them under our ship

    for (var i:int = 0; i < numStars; i++)
    {
    stage.addChildAt(new Star(stage), stage.getChildIndex(ourShip));
    }

    the stage.getChildIndex(ourShip); should return us a good index to add the stars at.

    ———-

    As for making a bullet manipulate in x. I’ll write a tutorial on it very soon.


  4. Andy

    Just wanted to say thanks for a fantastic tutorial. The expanations here have been really helpful to me and you have even managed to make following the tutorials pretty good fun!

    Nice work, looking forward to the next ones in the series.


  5. Very nice tutorial thank you for your post very useful.


  6. Roger

    Great tutorials very easy to understand keep up the great work


  7. sergio

    hi, i juste wanted to know if it is possible to download your tutorials in pdf format?
    i travel a lot by bus and so I could read them while traveling.

    thanks for answering,

    Sergio Marques Dias


  8. Par

    ah, I wish you could. At the moment no. But I’ll look into making it a possibility in the future.


  9. Joseh Climber

    Hi, first thanks for this series of tutorials, they really are openning my eyes to AS3 Game Programming.

    I’d like to ask you about the senocular classes. I noticed that when you are firing and moving you ship at the same time, the ship will move only in one direction.
    For example, if i let the spacebar pressed and press at the same time LEFT and DOWN, the ship will move only to the left or down, but not both ways. But, if the direction is UP+RIGHT, it works.
    Maybe its because the “if” sequence for those keys.

    Do you know who to solve for this problem?


  10. Par

    Joseh,

    You can move in multiple directions at the same time. Check the SWF Demonstration at the bottom of this tutorial. It’s likely because you don’t have your ifs setup right. Just double check them and see if they are what is causing the problem.


  11. Joseh Climber

    Hi Par, yes, I can move simultaneosly in multiple directions but only if i’m not pressing the fire button (spacebar). Even in your example, if you try to move to the bottom left while keeping pressing the spacebar, the ship moves only in one direction. Maybe its a processor issue (but my PC has a Dual Core 3.2Ghz Processor, 2GB RAM and Geforce 7900GT)


  12. Sean

    I keep getting an error in regards to line 111 of the Ship.as file. I’m not quite sure what I missed and why I am getting this (must less how to correct it).

    1136: Incorrect number of arguments. Expected 0.


  13. Weird

    I was getting error 1136 as well, there is just a little typo above, we are told to make BlueLaser.as, but it’s actually LaserBlue.as.

    this is totally a rad tutorial, seriously blowing my mind.

    thanks!


  14. B

    Hey Par, I’m seeing the same problem as Joseph. If I start moving diagonal upward left (up/left keys at the same time) then press and hold spacebar no firing comes out. All other directions work perfect. This happens in your example as well on this page. The weird thing is that Joseph says down/left doesn’t work for him and I say up/left doesn’t work for me (on your example on this page), so what could be the problem? It must not be a programming error if we’re having different results with the same code (your version on this page), or Joseph could have just typed down/left on accident.


  15. Aro

    Hi Joseh and B, your problem is not the swf but your keyboard! Some keyboards (my laptop does this) have a limited number of keys that can be pressed at the same time within a group of keys. I don’t have to worry about this on my desktop keyboard though… I guess more powerful keyboards handle more keys?…

    -Aro


  16. Maelyn

    I am getting the same problem with moving up+left and shooting at the same time, though every other direction combination + shoot work as well. And I tested by swapping the y up and down in the if statements.

    HOWEVER, this is only an issue with using the arrow keys. Using the numpad arrows (8,4,6,3) allows movement Up+left and shooting at the same time.

    Also, when I try and use Keyboard.Z for shoot instead of space…. nothing happens, running Test Movie doesn’t draw the ship or the stars…


  17. Par

    Aro is correct. It’s not the swf with the problem it’s your computer :(


  18. kingram

    hello everyone,

    First of all i am new to this section so i want to thank you for the tutorial and all the questions answers from everybody…! which is helping a lot for my learning experience of AS3.
    But i have a “dumb” question if i may, as i never used ActionScript before! How you “Create a new file under directory and fill it with the code”.I am a bit confused and it is not making sense for so far…! I am having headaches learning for the moment but i believe it is for the better…!
    Thank you so much to every on and keep up the good work…!

    Happy Christmas to you guys.


  19. sumit

    hey, im up to the bit with the timer and when i put the timer code on to my ship.as, it gives me an error

    it says

    ship.as LINE 115 1158:Syntax Error: missing left brace ({) before the function body and its on the private function fireTimerHandler(e:TimerEvent) : void.

    it still happens if i copy the code from the website and do it, so it couldnt be a mistake i made or sometthing but im confused help please guys?


  20. Confuzzled

    Hello!
    Congratulations on a fantastic tutorial! Have been trying to tweak things to match my idea but am having trouble making something work and wondered if would be able to advise?
    Im trying to add to the code to make the ship point at the mousepointer, Ive added the following to the loop event handler but rather than facing the pointer my movieclip just behaves incredibly erraticly (moves fine but rotates really randomly):

    var distanceX : Number = mouseX – x;
    var distanceY : Number = mouseY – y;
    var angleInRadians : Number = Math.atan2(distanceY, distanceX);
    var angleInDegrees : Number = angleInRadians * (180 / Math.PI) + 90;
    rotation = angleInDegrees;

    Any advice you could give me would be massivley appreciated :)

    Thanks in advance!


  21. Confuzzled

    fixed this problem now, needed to add stageRef to my mouse coords call, sorry for the wasted message!


  22. caina

    awsome! this site is great! god job :)


  23. Kyle

    First I’d like to thank you for making the most comprehensive beginners tutorial for AS3 that I’ve been able to find. I’ve been searching hard and getting very frustrated, but this is without a doubt the best I’ve found.

    With that said, I’m stuck. I’ve just finished the part of the tutorial where you get your ship to fire lasers, and mine isn’t firing any lasers. Everything else works perfectly. I’ve quadruple checked my code and unless my bleeding eyes deceive me, it’s identical to yours. Obviously this must be wrong if I’m having an issue, right?

    The weird thing about this situation is that I receive no compiler errors but rather…

    Argument Error #1063: Argument count mismatch on com.asgamer.basics1::Star(). Expected 1, got 0.

    at flash.display::Sprite/constructChildren()
    at flash.display::Sprite()
    at flash.display::MovieClip()
    at com.asgamer.basics1::Engine()

    Any ideas? Not sure if this is even being monitored still…


  24. hi,

    got that one through too, cant wait to get to the next page. this still and obvious is one of the best tutorials i found. i learned more things than expected, like keeping code clean and expendable and important things about all the commands you used, cause you are explaining it ;)

    i will search the whole page after finishing the whole package ;) keep it on, as i said, its just great how you serve the material.

    peace
    jesta


  25. user01

    thanks dude nice clear instructions and breakdown.


  26. Adebayor

    Does anyone know how to fire the bullets sideways. e.g. not upwards but bullets flying to the left side of the screen?


  27. Gamma Gamer

    Despite that these tutorials can’t be copy-pasted anymore because of being enormously outdated, I’m managing to adapt the basic game programming logic to my own!

    Thank you very much for keeping these online!



Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre lang="" line="" escaped="" highlight="">


Advertisement