Mirrored Circular Motion in AS3
This experiment illustrates the angles of circular movement in Flash, while mirroring those angles on the opposite side of the circle. I have two mirrored movements here. The first movement being a Sprite that mirrors the mouse’s position on the opposite side of the circle, while snapping to the boundaries of that circle. Then a second Sprite, that mirrors the mouse’s position on the opposite side of the circle, but instead shares the same distance of the mouse from the center point.
The first step here is to establish a center point, and determine the angle of the mouse from that center point. To do that, we take the x of the mouse and subtract from the x of the center point. Then do the same with the y coordinates. With those distances, we can then determine the radians by using the Math.atan2 function as:
var dx:Number = mouseX - centerX; var dy:Number = mouseY - centerY; var radians:Number = Math.atan2( dy, dx )
The Math.atan2 function is defined by adobe as:
Computes and returns the angle of the point y/x in radians, when measured counterclockwise from a circle's x axis (where 0,0 represents the center of the circle). The return value is between positive pi and negative pi.
Then we can convert that radian value to degrees by using this formula:
degree = radian * 180 / Math.PI );
So the code would then look like:
var degrees:Number = Math.round( radians * 180 / Math.PI );
So now, the way the Flash coordinate system works, (shown in the illustration above) is we start at zero (from the 3 o'clock position), and move counter clockwise until we get to –180. Once we get to -180, (still going counter-clockwise) we then jump to 180 and count our way back down to zero. So, in order to discover the angle of the opposite side of the mouse, we can actually use the same x/y distance numbers from the center point to the mouse, only all we need to do is change those values to negative and pop back in the Math.atan2. That then looks like:
var oppRadians:Number = Math.atan2( -dy, -dx ); var oppDegrees:Number = Math.round( oppRadians * 180 / Math.PI );
Now, if we want to have a sprite that follows the mouse on the opposite side of the circle, and snaps to that circles boundaries, we can then add a radius var, and use a sine function to position the y, and a cosine function to position the x:
var radius:Number = 100; Sprite1.x = centerX + Math.cos( oppRadians ) * radius; Sprite1.y = centerY + Math.sin( oppRadians ) * radius;
The second Sprite, in which we want to follow the mouse around the circle on the opposite side, while sharing the same distance as the mouse to the center point, we need to add one extra line of code. Since we already have determined the x and y distances from the mouse to the center point, we can the use Pythagorean Theorem (a squared + b squared = c squared) to determine the distance.
var dist:Number = Math.sqrt( dx * dx + dy * dy );
Then pop that distance value in the same equation as Sprite one, but in the place of the radius.
Sprite2.x = centerX + Math.cos( oppRadians ) * dist; Sprite2.y = centerY + Math.sin( oppRadians ) * dist;
The complete code is as follows:
var dx:Number; var dy:Number; var radians:Number; var degrees:Number; var centerX:int = 295; var centerY:int = 125; var oppRadians:Number; var oppDegrees:Number; var radius:Number = 100; var dist:Number; // Add Node1 from library var myNode1:Node = new Node(); addChild( myNode1 ); // Add Node2 from library var myNode2:Node = new Node(); addChild( myNode2 ); // uppdate addEventListener( Event.ENTER_FRAME, onEnterFrame ); function onEnterFrame( e:Event ):void { dx = mouseX - centerX; dy = mouseY - centerY; dist = Math.sqrt( dx * dx + dy * dy ); radians = Math.atan2( dy, dx ); degrees = Math.round( radians * 180 / Math.PI ); oppRadians = Math.atan2( -dy, -dx ); oppDegrees = Math.round( oppRadians * 180 / Math.PI ); // update Node myNode1.x = centerX + Math.cos( oppRadians ) * radius; myNode1.y = centerY + Math.sin( oppRadians ) * radius; // update second node myNode2.x = centerX + Math.cos( oppRadians ) * dist; myNode2.y = centerY + Math.sin( oppRadians ) * dist; // draw line graphics.clear(); graphics.lineStyle( 1, 0x666666, 1 ); graphics.moveTo( centerX, centerY ); graphics.lineTo( mouseX, mouseY ); graphics.lineTo( mouseX, centerY ); graphics.lineTo( centerX, centerY ); graphics.lineStyle( 1, 0xFF0000, 1 ); graphics.lineTo( myNode1.x, myNode1.y ); // populate text degreeTXT.text = unescape( degrees.toString() + "%ba" ); oppositeTXT.text = unescape( oppDegrees.toString() + "%ba" ); }
This is very cool and fancy and all, but tell me this smarty…which Sprite are we mirroring? Classic Sprite or the one with the new, ugly logo??
Comment by Bruce — 2/19/09 @ 3:17 pm
Haha, smartass ;) It would be the classic logo, of course.
Comment by Mike T. Henderson — 2/19/09 @ 5:39 pm
[...] I’m containing the particles within a circular boundary by using the logic from my previous post, Mirrored Circular Motion in AS3, to regenerate particles on the opposite side of the [...]
Pingback by Mike t. Henderson » Perlin Particles within a Circular Boundary in AS3 — 3/6/09 @ 6:31 pm