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

Dragging and Collision Detection

startDrag and stopDrag

To allow a movieclip to be dragged while the mouse is pressed (only), you assign a function which executes the startDrag method to the movieclip's onPress event, and a function which executes the stopDrag method to the movieclip's onRelease and onReleaseOutside events. The reason for assigning stopDrag to both the onRelease and onReleaseOutside events is that if the mouse is moved too quickly while dragging, it will not be over the movieclip when it's released, and if no stopDrag has been assigned to onReleaseOutside, the object will continue to be dragged even when the mouse is not pressed.

If no constraints on the drag are required, a simple startDrag with no parameters may be issued. If the draggable movement of the object is to be constained within a rectangle, or along a horizontal or vertical line, parameters must be supplied to the startDrag to specify these things. Here's the general syntax to make a movieclip with an upper left registration point draggable within a rectangle:

In the code above, the first parameter (lockCenter) is set to false to keep the mouse from jumping to the middle of the object on press, then the parameters for left, top, right and bottom constraints (in pixels relative to the registration point of the timeline the movieclip is in) are specified. Here's an example, where the bluegreen square is a draggable movieclip, constrained within the rectangle shown:

This is the code in frame 1 of that movie:

square_mc.onPress = function() {
	this.startDrag(false, 40, 50, 260, 150);
}
square_mc.onRelease = square_mc.onReleaseOutside = function() {
   this.stopDrag();
}
square_mc.onRollOver = function() {
   this.gotoAndPlay("tooltip");
}
where the parts relevant to dragging are the onPress and onRelease parts. (The onRollOver part activates a sequence within square_mc to show a tooltip that displays for a couple seconds and then fades). Notice that because the movieclip being dragged has an upper left registration point, its width (20) must be subtracted from the right (280) and bottom (170) positions of the rectangle to make sure the square stays completely inside it (ie, with its right edge touching the right edge of the constraining rectangle, or its bottom edge touching the bottom edge of the rectangle).

Dragging along a horizontal or vertical line

To make a movieclip draggable along a horizontal line, just pass the same parameters for T and B to startDrag. These can be the same numeric value, or, if you want the drag to happen in the same position the movieclip is already in (the usual case), pass this._y for T and B. For a vertical drag, pass the same values for L and R (either this._x or a number value). That is:

// horizontal drag
square_mc.onPress = function() {
	this.startDrag(false, 40, this._y, 260, this._y);
}
// vertical drag
square_mc.onPress = function() {
	this.startDrag(false, this._x, 50, this._x, 150);
}

Collision detection

Ok, now we have a draggable movieclip, but how to tell when it hits something else? For that, we'll use hitTest, a method of the MovieClip class that can detect a collision either between the bounding edges of two movieclips, or between a specified point on the stage and the actual shape content of a movieclip. The syntax for both is shown here. The code at the top is for checking a collision between the bounding edges of "instancename" and the bounding edges of "otherinstance". The code at the bottom checks for a collision between the content (the actual shape of) "instancename" and a point on the stage defined by x and y (x pixels from the left edge of the stage and y pixels down).

The movie at the top of the page has an example of both. If a collision occurs between the squiggle and the smiley, frame "ow" of the smiley is displayed. Notice though, that a collision is detected when any part of the bounding box of squiggle_mc touches any part of the bounding box of smiley_mc, not when the actual shapes touch each other (and the bounding box of smiley_mc includes the area around its mouseover voice balloons too, even though they are not in the first frame). In the second example though, a more precise detection is done, between the actual content of the squiggle and a point (actually, two points) on the stage. In this case, frame "myeye" of smiley_mc is displayed and it happens only when the squiggle is directly touching either point. Check the code below to see the difference between the parameters in each case:

// start the squiggle dragging when the mouse is pressed over it
squiggle_mc.onPress = function() {
   this.startDrag();
}

// stop the squiggle dragging when the mouse is released
squiggle_mc.onRelease = squiggle_mc.onReleaseOutside = function() {
   this.stopDrag();
}

// do this every frame for a continuous check
smiley_mc.onEnterFrame = function() {

   // check for a collision between either point (middle of each eye) 
   // and a shape (squiggle) ( || means "or" )
   // if one occured, show "ow, my eye" frame in smiley_mc
   if (squiggle_mc.hitTest(195, 78, true) || squiggle_mc.hitTest(222, 78, true)) {
      this.gotoAndStop("myeye");
	  
   // if no collision between squiggle and an eye,
   // check for a collision between the bounding edges of two movieclips
   // if one occurred, show "ow" frame in smiley_mc
   } else if (squiggle_mc.hitTest(this)) {
      this.gotoAndStop("ow");
	  
   // if no collision occurred at all, send back to frame 1
   } else {
      this.gotoAndStop(1);
   }
}
	

Notice that both collision checks are done within an onEnterFrame function, because they must be checked for continuously. The onEnterFrame does not necessarily have to be defined for smiley_mc -- it could be defined instead for the main timeline or squiggle_mc; I just chose it because it seemed the most logical here. You can download the source flas for both examples from the class directory (in asbasics.zip).

Using calculated points instead of hardcoded numbers

Instead of using numbers to show the position of the center of each eye, it would be better to let the program calculate that position, so that the same code could be used even after moving the smiley mc to a new place on stage, or moving the eyes within the face.

To do that, we need to calculate and save the position of each eye relative to the main movie. In order to calculate the position of something in a movie, it needs to be a movieclip (in order to be addressable). So we'll first convert one of the eye shapes to a movieclip with a top center registration point. Remember, the registration point is the point that is used as a point of reference for any actionscript, so it will determine what are the _x and _y values for a movieclip. If the registration point is set to top center of the eye movieclip, then smiley_mc.eye_mc._x and smiley_mc.eye_mc._y will return the values of that point, relative to the registration point of smiley_mc itself. Here's a picture:

And here are the changes to the code to calculate each position and use it to detect collisions:

var p1x:Number = smiley_mc._x + smiley_mc.eye1._x;
var p1y:Number = smiley_mc._y + smiley_mc.eye1._y;
var p2x:Number = smiley_mc._x + smiley_mc.eye2._x;
var p2y:Number = smiley_mc._y + smiley_mc.eye2._y;

// do this every frame for a continuous check
smiley_mc.onEnterFrame = function() {

   // check for a collision between a point and a shape
   if (squiggle_mc.hitTest(p1x, p1y, true) || squiggle_mc.hitTest(p2x, p2y, true)) {
      this.gotoAndStop("myeye");

   // etc	  
}

You can also use the localToGlobal method to calculate the collision point of each eye relative to the main stage. Check the Help files for more about localToGlobal and globalToLocal.

Detecting 'collisions' with the mouse

Another use of hitTest is to find out when the mouse has 'hit' (passes over) an object on stage. For this example, we'll use a modified version of smiley_mc which just has a background face and two eye movieclips in it. Each eye movieclip has a two-keyframe structure in which one keyframe contains the open eye (frame label="open") and the other contains a squinting eye (frame label="squint"). The movieclip also has a layer to define the active area of the movieclip so that the mouse doesn't have to be exactly over part of the squint for this to work. Here is what the innards of the eye movieclip look like:

and here is the code to make the movie shown above work:

// do this every frame for a continuous check
smiley_mc.eye1.onEnterFrame = 
smiley_mc.eye2.onEnterFrame = function() {

   // check for a collision between mouse and any part of an eye
   if (this.hitTest(_xmouse, _ymouse, true)) {
      this.gotoAndStop("squint");
   } else {
      this.gotoAndStop("open");
   }
}

To see an example of dragging and collision detection in action (with a free fla), check the Dart Shooter example.

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