AS Reference  :  Notes Index  :  Resources  :  About/Contact  :  Downloads

Dart Shooter


Stage Setup

In this tutorial, we'll make a shooter movieclip (the red snorkel thing above) that can be dragged horizontally, a dart movieclip that is 'shot' when the mouse is released on the shooter, and several instances of a bubble movieclip that float by and pop when hit by the dart. Because the x and y positions of the shooter, dart, and bubbles will all need to be controlled with actionscript, we'll make each one with an upper left registration point. This ensures that values reported in the Properties panel (which returns the distance between the movieclip container's registration point and the upper left corner of the movieclip, regardless of its registration point) match the _x and _y values of the movieclip (which is always the distance from the movieclip container's registration point to the movieclip's own registration point).

The popping bubble does not lend itself to being programmed in actionscript, so we'll set that up as a movieclip of several frames duration, where the first frame holds the bubble in its normal state and has a stop action in it, and frame 2 is labelled "explode" and starts the tweened pop, in which the bubble is shape tweened to expand and fade away (with a stop action in the final frame).

The stage is set up with 5 copies of the bubble (instance named bubble1, bubble2,... bubble5) staggered off the left side of the stage, a layer with the shooter in it (instance name shooter) and a layer with the dart (instance name dart) below that. Both the shooter and the dart are under a mask which is not at all essential to the game, but I added to make it look like the shooter was moving along a wavy path partly underwater.

Actionscript to drag the shooter and make the dart follow

We'll use the standard startDrag/stopDrag commands to make the shooter draggable, but we also need to make the dart 'draggable', that is, follow the shooter. We can't drag two things at once, so instead we'll use the onMouseMove event handler within the shooter's onPress handler so that we can control what happens when the mouse is both pressed down on the shooter and being moved. Here is the code to drag shooter and have dart follow underneath:

var STAGEWIDTH:Number = 500;

shooter.onPress = function() {
   this.startDrag(false, 0, this._y, STAGEWIDTH-this._width, this._y);
   this.onMouseMove = function() {
      dart._x = this._x + 4;
   }
}

shooter.onRelease = shooter.onReleaseOutside = function() {
   this.stopDrag();
   delete this.onMouseMove;
}
	

Notice that we've constrained the shooter to a horizontal drag by setting T and B to the same value (this._y, which is its current y location on stage), as described on the drag and hit page. We also used a variable STAGEWIDTH (capitalized to show that it's actually a constant which will not change throughout the movie) to contain the value of the movie's width and used that as the R value for the constraint.

The dart is 'dragged' along with the shooter by setting its x position 4 pixels to the right of the shooter's (as it is when the movie starts) whenever the shooter is dragged (ie, whenever the mouse moves while pressed over shooter). Notice that we delete the onMouseMove handler when the mouse is released since it would take unnecessary processing to keep checking it then.

Actionscript to make the dart shoot

In this game, the dart shoots out whenever the mouse is released after dragging (or just pressing and not dragging) the shooter. So the code to do the shooting needs to be in the onRelease/onReleaseOutside handler. This is what that handler looks like, revised to include shooting:

var DARTSPEED:Number = 20;
var DARTSTART:Number = dart._y;		// save dart start position

shooter.onRelease = shooter.onReleaseOutside = function() {
   this.stopDrag();
   delete this.onMouseMove;

   dart.onEnterFrame = function() {
      // if the dart is still onstage, move it upwards a defined number of pixels per frame
      if (this._y > 0-dart._height) {
         this._y -= DARTSPEED;
      // if it has gone off the top of the stage, reset it to its original position
      // and stop the enterFrame to wait for the next release of shooter
      } else {
         this._y = DARTSTART;
         delete this.onEnterFrame;
      }
   }
}

Again, we've set up some constants at the start of the movie to store information we'll need later (and may want to have easy access to, to change as we develop the game): the number of pixels to move the dart each frame, and the dart's starting y position, so we can reset it after it goes offstage. The code to shoot the dart is inside an onEnterFrame loop because it needs to happen continuously (until the dart goes offstage, ie, when this._y > 0-dart._height). While it's onstage, it's continuously bumped upwards DARTSPEED number of pixels every frame. When it goes off, it's reset to its start position and the enterFrame is killed (to keep the dart from shooting all over again).

Actionscript to move the bubbles across the stage

To make one of the bubbles, eg, bubble1, move across the stage and then put it back at in a position that's just to the left of the stage when it goes off the right side, we would use this code:

bubble1.onEnterFrame = function() {
   if (this._x < STAGEWIDTH) {
      this._x += BUBBLESPEED;
   } else {
      this._x = 0-this._width;
   }
}

To assign the same handler function to all five bubbles, we can do

bubble1.onEnterFrame = 
bubble2.onEnterFrame = 
bubble3.onEnterFrame = 
bubble4.onEnterFrame = 
bubble5.onEnterFrame = function() {
   if (this._x < STAGEWIDTH) {
      this._x += BUBBLESPEED;
   } else {
      this._x = 0-this._width;
   }
}

Adding random changes to the balloons when they are reset

Now we have code to drag the shooter, fire the dart, and make all five bubbles move across the stage and reset themselves at a position just off the left side of the stage when they go off the right. We still need to react to a collision between the bubbles and the dart, and to make the bubbles appear a little more randomly each time. To do the latter, we can apply the Math.random() function to change the _x, _y, _xscale and _yscale of the bubbles randomly whenever they are reset. Math.random() returns a random decimal amount between 0 and 1, which means that Math.random()*50, for example, will return a random (decimal) number between 0 and 50. More about Math.random and other methods of the Math class can be found on the Math class page. For now, it is enough for us to know that Math.random()*n will return a random number between 0 and n, and, by extension (come on, turn on your math brains, you can do this!) -n + Math.random()*2*n will return a random number between -n and +n. This will allow us to either shrink or grow the balloon by up to 10%, for example, by adding -10 + Math.random()*20 to the current scale values. This is the code to randomly set the balloon's x, y and size:

bubble1.onEnterFrame = 
...
bubble5.onEnterFrame = function() {
   if (this._x < STAGEWIDTH) {
      this._x += BUBBLESPEED;
   } else {
      // reposition on left, between 0 and 50 pixels to the left of the stage
      this._x = 0-this._width - Math.random()*50;
      // randomly move up or down, up to 20 pixels
      this._y += -20 + Math.random()*40;
      // randomly change size +/- up to 10%
      this._xscale = this._yscale = -10 + this._xscale + Math.random()*20;
   }
}

(Note that in order to keep the random values from going wildly out of range, a few if/then checks should be added to make sure the bubbles stay on stage, eg, and that they don't eventually become enormous or invisibly small. I didn't want to add that extra level of complication to this example though, so I picked some not-too-large variations on the original values.)

Reacting to collisions between a balloon and the dart

We have three choices for attaching a handler to check for balloon-dart collisions: to the main timeline, to the dart, or to the balloon instances. If we choose either of the first two, we'd need to set up a loop to check the dart against each of the five balloon instances. To avoid this unnecessary complication, we'll go with the third option, attaching the handler to the balloon instances. That way, each balloon can check to see whether it has collided with the dart and respond accordingly, without any code loops being needed. We already have code in the onEnterFrame handler for each balloon, so we'll just add the collision detection code to that:

// define the bubbles' behavior
bubble1.onEnterFrame = 
...
bubble5.onEnterFrame = function() {
   // while bubble is still onstage:
   if (this._x < STAGEWIDTH) {
      this._x += BUBBLESPEED;
      // easier to check here against dart rather than vice versa
      // MUST check if in frame 1 or command may be executed repeatedly
      if (this.hitTest(dart) && this._currentframe==1) {
         this.gotoAndPlay("explode");
      }
   // when bubble goes offstage:
   } else {
      // same code as above to reset, plus
      // set back to normal (unexploded) view
      this.gotoAndStop(1);   
   }
}

In that code this.hitTest(dart) is used to check whether a collision has occurred, and if so (and if the balloon is currently in frame 1, meaning not already exploded), make it explode. _currentframe is a read-only property of the MovieClip class which shows what frame the playhead of that movieclip is currently in. In the code above, we also issue a command to send the balloon back to frame 1 to reset it graphically for its next trip across the stage.

All of the code above can then be combined and put in its own .as file (for easier editing in the Flash IDE) and then included in the fla with this command:

#include "dartshooter.as"

You can download a zip of the fla and as file to examine here.

Intro
Flash: What & How
Example Sites
Create
Draw, Edit Shapes
Gradients
More Drawing Tips
Import
A Sample
Animate
Frames, Keyframes
Motion Tweens
More Motion Tweens
Shape Tweens
Masks
Control
Stop/Replay
Movieclips Intro
Movieclip Reference
Site Structure 1
Slideshow Movieclip
Contact Form
Scroll Resume
Preloader
Site Structure 2
Publish
Display Options
Player Detection
Optimize
AS 2.0 Basics
Intro to Syntax
Playhead Commands
Playhead Cmds 2
Coded Tween
onEnterFrame
Intro to Classes
Declare/Assign
Comments, Trace
Simple Data Types
Arrays & Objects
Code Blocks
Operators
Beyond Buttons
Code Structure
Toggle Controls
Group of Buttons
Drag and Hit
Distort Magnifier
Scroll Text
Bee Game
Dart Shooter
Sound Control
Easing Slider
Easing Slider 2
Components Intro
Timers & Delays
Dynamic Content
Intro
Drawing API
Create Text
Attach Movieclips
Easing Slider 3
Easing Slider 4
Load jpg/swf
Sliding Viewer
Preload swf
XML
Easing Slider 5
Server Comm
LoadVars (w/ PHP)
AS - PHP Lookup
Text File
Database 1:LoadVars
Database 2:Remoting
Read from directory
AS 2.0 Classes
Intro
Math
Key
Date
Color
EventDispatcher
New Samples
Pie Chart
Event-model Emailer
Tween Sequence
Fuse Sequence
SVG in Flash
Bitmap Topo
SWF as Data Holder
Two-level Menu
Yahoo! Flash Maps
Class-based Game
ASTB Samples
Disclaimer
3D Outlines
Bounce Collide
Address Book
Save Drawings
Home  :  Notes Index  :  Resources  :  About/Contact  :  Downloads