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.
Notes: There is a flaw in the programming - the four cardinal compass points (0, 90, 180, 270) don't work! Every other angle works and since for my purposes this is going to work just fine I am stopping spending time on this. If you can figure out what part of my programming is flawed I'd be glad to hear from you!
Trig Refresher [as] //Comment: ---------------------------------------------- //Comment: Manually Set Movie Center //Comment: ---------------------------------------------- //Comment: also set the origin of the line object movie clip to this number Set Variable: "scr_ctr_x" = 200 Set Variable: "scr_ctr_y" = 200 //Comment: ---------------------------------------------- //Comment: lookup table for sine values //Comment: ---------------------------------------------- Set Variable: "sine_lookup_table" = "0.000/.0175/.0349/.0523/.0698/.0872/ .1045/.1219/.1392/.1564/.1736/.1908/.2079/.2250/.2419/.2588/.2756/.2924/ .3090/.3256/.3420/.3584/.3746/.3907/.4067/.4226/.4384/.4540/.4695/.4848/ .5000/.5150/.5299/.5446/.5592/.5736/.5878/.6018/.6157/.6428/.6561/.6691/ .6820/.6947/.7071/.7193/.7314/.7431/.7547/.7660/.7771/.7880/.7986/.8090/ .8192/.8290/.8387/.8480/.8572/.8660/.8746/.8829/.8910/.8988/.9063/.9135/ .9205/.9272/.9336/.9397/.9455/.9511/.9563/.9613/.9659/.9703/.9744/.9781/ .9816/.9848/.9877/.9903/.9925/.9945/.9962/.9976/.9986/.9994/.9998/1.000" [/as] Above is the "variable" frame on the main timeline. In it, we need to set the 0,0 point of the effect. The reason is, Flash's 0,0 point is at the top left hand corner of the movieboard. Since my movie is 400x400 the point 200,200 is a convenient point to centre the effect on. The 0,0 point of the "pointer line" is also at 200,200. Notice the way that movie clip is built. You will see that the little "plus" sign (the origin) is at the point of the artwork around which the rotation will occur. We will use these variables later.
The other important thing you need is a sine lookup table. Why? You need to do some trig! Since Sin(Theta)=O/Hyp and since this relationship is always constant (in other words, it doesn't matter what length 'O' and 'Hyp' are, their proportions will always be the same when the angle between them is the same.) Hey. I may not be the best at explaining this stuff.
So once you understand how to find an angle from two measurements, then look what to do--- break it down into programming components: [as] //Comment: ---------------------------------------------- //Comment: get mouse location //Comment: ---------------------------------------------- Set Variable: "mouse_x" = GetProperty("",_x) - ..:scr_ctr_x Set Variable: "mouse_y" = GetProperty("",_y) - ..:scr_ctr_y [/as] There is a movie clip on the main timeline in the "Controller" layer. It serves three purposes... it holds all the actionscript that makes this work, it is dragged so we can determine the mouse x,y coordinate, and it holds the objects which follow the mouse telling you useful information.
Page 2 of 2
Why do we need to know the mouse location? Since the 0,0 coordinate in this demonstration never moves, all we need to know to do some Trigonometry is the length of two sides of the triangle. Since we do know two sides (the x and y value of the mouse are distances... and are the two sides of the triangle) we can calculate the third side of the triangle (the hypotenuse) using the formula (a^2 + b^2 = c^2). More on that: [as] //Comment: ---------------------------------------------- //Comment: determine hypotenuese length //Comment: ---------------------------------------------- //Comment: a squared plus b squared = c squared... (c=hypotenuse) so what is c? Set Variable: "input" = (mouse_x * mouse_x) + (mouse_y * mouse_y) Call ("sqrt") Set Variable: "hyp" = output [/as] For now, let's just say you set a variable "input" call "sqrt" and it sends back a variable "output", which is the square root of the number you sent.
Now we know the length of the hypotenuse. 'Hyp'. Since the x position of the user's mouse is "A" and the y position of the user's mouse is "O" we now have more than enough information to determine the angle "Theta".
[as] //Comment: ---------------------------------------------- //Comment: determine sin(theta) //Comment: ---------------------------------------------- //Comment: now we know "c" (the hypotenuse) how do we find the angle? Sine(Theta) is Opposite over Hypotenuse, then lookup the Sine value in the lookup table. Set Variable: "sin_theta" = mouse_y/hyp If (sin_theta<0) Set Variable: "sin_theta" = sin_theta+(sin_theta*-2) End If [/as] How To Find The Mouse Location [as] //Comment: ---------------------------------------------- //Comment: lookup angle in table //Comment: ---------------------------------------------- Set Variable: "counter" = 0 Set Variable: "found" = 0 Loop While (not(found)) If (sin_theta>=Substring (..:sine_lookup_table,(counter*6)+1,5)) Comment: this counter will only increase if sin(Theta) is greater than or exactly the angle match in the lookup table. This way, if the sine value has no exact match then the counter will point to the angle closest (less than) the correct answer. Set Variable: "angle" = counter+1 Else Set Variable: "found" = 1 End If Set Variable: "counter" = counter+1 End Loop [/as] What does this loop do? It starts a counter at 0. It looks at the first sine value in the table. If that sine value is less than the calculated vale for our angle, then nothing happens. we increase "angle" by one because it obviously isn't this low. This goes on until our calculated value for our angle becomes LESS than the lookup value in the table. Than means the actual angle we are at is less than the one the counter is at. In that case, we don't increase "angle", we set a variable "found" to "1" (another way of saying "found is true") and now the Loop While (not(found)) statement is false. Loops continue endlessly until the condition in the brackets is true. Since found starts out as "0" (false), not(found) can also be read as "not false". In other words, not(false)=true. So the loop reads (Loop while true). As soon as it the condition changes to "false" it quits the loop, stopping any further calculations because we've found the angle we are looking for.
This is just a fancy way to make the loop read more English-like. [as] Comment: ---------------------------------------------- Comment: add back full circle values Comment: I also change the "0" point on the compass to the right hand side, with angle increasing counter clockwise. Comment: ---------------------------------------------- If (mouse_x>=0 and mouse_y<0) Set Variable: "angle" = angle End If If (mouse_x<0 and mouse_y<0) Set Variable: "angle" = (90-angle)+90 End If If (mouse_x<0 and mouse_y>=0) Set Variable: "angle" = angle+180 End If If (mouse_x>=0 and mouse_y>=0) Set Variable: "angle" = (90-angle)+270 End If [/as] Why do we need this? Hey. There is probably a more efficient way to make this whole code work. I'm certainly no programmer. But remember that the angle we calculated is between 0 and 90 degrees. Well, a full circle has 360 degrees. So how do we tell when to add 90, 180, or 270 degrees? Easy. Which quadrant was the mouse in? If the x and y values were both positive, then it was in the bottom right hand corner. (Flash coordinates start in the top left corner and increase down to the right.) So why is there a 90-angle phrase in the math there? I don't know. It's probably obvious to a mathematician. I just found that the numbers worked perfectly only by adding that in there.
Closing Thoughts Download the ".FLA" and remove those bits to see what I mean. [as] //Comment: ---------------------------------------------- //Comment: redraw pointer line //Comment: ---------------------------------------------- Set Property ("../line", Rotation) = -angle+90 [/as] Okay, so except for the bad programming, and the flawed logic (for some reason "0", "90", "180", and "270" don't show up ever in the calculations) it works! And this is the first trigonometry I've done in YEARS.