ActionScript.org Flash, Flex and ActionScript Resources - http://www.actionscript.org/resources
Mouse Angle Detection II
http://www.actionscript.org/resources/articles/154/1/Mouse-Angle-Detection-II/Page1.html
Kyle McDonald
This user is yet to take control of their account and provide a biography. If you are the author of this article, please contact us via support AT actionscript DOT org. 
By Kyle McDonald
Published on September 9, 2005
 
Tutorial details:
Written by: Kyle McDonald [email:webmaster@kylemcdonald.com]
Website: www.kylemcdonald.com
Difficulty Level: Advanced

Page 1 of 2
Tutorial details:
Written by: Kyle McDonald [email:webmaster@kylemcdonald.com]
Website: www.kylemcdonald.com
Difficulty Level: Advanced Download FLA



INTRODUCTION

I am writing this tutorial because I feel that the current tutorial on actionscript.org which defines how to detect the angle of a mouse relative to an object on the screen is unnecesarily complex. Instead of going through sine tables, I think that it would be much better if you understand how to do two things in a simpler way:

1.) Detect the angle created by the mouse and a movie clip symbol.
2.) Rotate a movie clip symbol about its vertex based on the position of the mouse.

PART 1: Back to the basics: Trigenometry and Algebra

When you are detecting the angle of the mouse relative to an object, what you are really doing is finding the angle (aka "theta") in the triangle created by the x,y position of the mouse, the 0,0 position of the vertex of the movie clip symbol, and the horizontal line that passes through the vertex of the movie clip symbol.

img

If anybody remembers the pnumatic device "sohcahtoa", then you might remember it means:

sin()=(opposite/hypotenuse)
cos()=(adjacent/hypotenuse)
tan()=(opposite/adjacent)

You can see where "opposite", "adjacent", and "hypostenuse" are by looking at the next picture.

img

Also, just incase you are wondering, "opposite", "adjacent", and "hypostenuse" are lengths of the sides of the triangle. So, since everyone past about 8th grade knows, it takes a little bit more math to find the hypotenuse, and since we already have the length of the adjacent and opposite sides (the x and y of the mouse relative to the movie clip symbol, in this case the mouse) we can just go ahead and use algebra to manipulate this equation to solve for theta:

tan(theta)=(opposite/adjacent) is equal to
theta=inverse-tan(opposite/adjacent) is equal to
theta=tan-1(opposite/adjacent) is equal to
theta=arc-tan(opposite/adjacent)

Really, tan-1(), arc-tan(), and inverse-tan() are all ways of saying the same thing. Hopefully, this clears it up for you, bcause I know I was confused for a while. Flash uses the term "atan" as the function for arc-tan/inverse-tan/tan-1. So, now that we have our understanding of the concept and the equation (theta=arc-tan(opposite/adjacent)), now we can almost start making Flash do the work for us!

PART 2: Stupid Flash Tricks

By now you probably have a good understanding of the trigenometry behind the script we will write, or you just skipped the previous section. Either way, the first thing we need to do is re-define our equation to be used. Like most programming languages, ActionScript computates it's trigenometry functions in Radians. For example, let us say that the mouse is at a 45 degree angle, that means that it is an equal x distance away as it is y distance ((any number / itself)=1). So, the equation we would use to get it's angle is Math.atan(1). Math.atan() is the function with which Flash will do arc-tangent lookups for you. So, to test this out we can make a simple movie with a dynamic text box with the variable name "text", and an actionscript on the frame that says: [as]_root.text=Math.atan(1);
stop();[/as] And then test the movie. But no! Flash seems to have betrayed us and given us the ugly number 0.785398163397448! This is because, like I said, Flash does it's calculations in Radians. So, to convert from Radians to Degrees, you can divide the radians number by a number (pi/180), (aka pi/180). So, now if we try for the actionscript instead: [as]_root.text=Math.atan(1)/(Math.PI/180);
stop();[/as] Then we come up with the answer we were looking for, 45 degrees. Now that we have a good understanding of the way that Flash does geometry, we can finally write some real (more or less) actionscript and actually get the angle dynamically.

Page 2 of 2


PART 3: Detecting the Mouse Angle

Now we have the hard parts behind us, from here on out is me explaining Flash.

1.) Open up flash and make a nice square stage, around 300x300, just to make it easy when you try to visualize things.

2.) Make a new movie clip object with the name "script".

3.) Go back to Scene 1, your main stage, and drag the "object" movie clip onto the stage. (You should see a little circle with a white fill to represent the symbol). If you want, you can turn on the grid and snap to the grid so that you have a centered detector. Make sure you change the grid settings to 15px 15px, though.

4.) Create a text box in the bottom right corner of the stage.

5.) Change the properties of this text box in the "Character" window under the "text Options" set so that it is "Dynamic Text" with the variable "angletext" assigned to it.

6.) Right click on it and select "Actions". Now we are going to write the actionscript that will tell us what the angle of the mouse is. Type this into the actionscript area:

[as]onClipEvent (mouseMove) {
x = this._xmouse;
y = this._ymouse*-1;
angle = Math.atan(y/x)/(Math.PI/180);
if (x<0) {
angle += 180;
}
if (x>=0 && y<0) {
angle += 360;
}
_root.angletext = angle;
updateAfterEvent();
}[/as] And that is all we have to do. Unless you want to understand this script, you can skip the next portion of this tutorial.

REFERENCE:
1.) onClipEvent (mouseMove) {
2.) x=this._xmouse;
3.) y=this._ymouse*-1;
4.) angle = Math.atan(y/x)/(Math.PI/180);
5.) if(x<0){angle+=180}
6.) if(x>=0&&y<0){angle+=360}
7.) _root.angletext=angle;
8.) updateAfterEvent();}

Line 1: Do the following whenever the mouse is moved.
Line 2: Define the variable "x" to mean the mouse x position relative to the movie clip.
Line 3: Define the variable "y" to mean the mouse y position relative to the movie clip, except reverse the number from + to - or - to + so that the actual angle cartesian coordinates for the mouse are used.
Line 4: Compute the angle of the mouse, and put it into the variable "angle".
Line 5 and 6: If you just take the current variable "angle", the angle that is returned is only good for the first quadrant within which you move the mouse. So, these lines are to fix the number that you get so it is good for all the quadrants.
Line 7: This line allows you to see the final number for the angle of the mouse by placing it into the textbox.
Line 8: Update the screen so you can see the results.

PART 4: Rotating something based on the mouse angle

Right now we have a very useful script, but it is kind of hard to see because there is nothing to show us that flash is doing something for us except that the text box is reporting the mouse angle. So, in this section we will make an arrow that rotates and points to the mouse, similar to the first mouse detection tutorial.

1.) Create a new movie clip symbol called "arrow".

2.) Draw an arrow in this fashion (I edited the grid settings to be 8px by 8px):

img

3.) Go back to the main stage and drag the arrow symbol into onto the stage. Make sure the vertex of the arrow symbol is aligned with the "script" symbol.

4.) Give the instance name to the symbol "arrow", "arrow". (open the instance window by clicking on the img in the bottom right corner of Flash).

5.) Almost done! Click on the script symbol on the stage (the little circle) and open up it's actions. Add to the end, right before UpdateAfterEvent(), the line: [as]_root.arrow._rotation=angle*-1;[/as] 6.) That is all!

If you even took the time to read that last line, hopefully you noticed the *-1 and want to know why that is there. Well, that is actually something else that is weird about Flash. Flash counts 0 as 0, 90 as either -90 or 270, 180 as 180 and 270 as either 90 or -270. Now if you consider the other difference between Flash and Cartesian coordinates, this makes perfect sense, because all Flash does is flip the 4 quadrants along the x axis. Anyway, in the end we have an accurate cartesian reading of the angle of the mouse. In the end your script should look like this: [as]onClipEvent (mouseMove) {
x = this._xmouse;
y = this._ymouse*-1;
angle = Math.atan(y/x)/(Math.PI/180);
if (x<0) {
angle += 180;
}
if (x>=0 && y<0) {
angle += 360;
}
_root.angletext = angle;
_root.arrow._rotation = angle*-1;
updateAfterEvent();
}[/as]