00:00
00:00
Newgrounds Background Image Theme

cflash19 just joined the crew!

We need you on the team, too.

Support Newgrounds and get tons of perks for just $2.99!

Create a Free Account and then..

Become a Supporter!

AS3: Rotating objects around points

22,816 Views | 3 Replies
New Topic Respond to this Topic

AS3: MAIN

I remember about a year ago trying to work this out and messing it up completely. Well, I made another attempt about five minutes ago in AS3 and did it with no problems whatsoever, so I must have been on a bad day or something.

This is basically a tutorial on how to get your object to rotate around a custom reference point. I'll feel like a real idiot if something like this already exists in Flash, but lots of searching through the documentation yielded no results, so here's how to do it manually. This should be pretty much mandatory for any more complex physics engines.

In true AS3 style, here is is laid out in a class. Anyone uncomfortable with classes should still be able to extract the important information from this one:

package{
	import flash.display.MovieClip;
	import flash.geom.Point;

Just importing the necessary classes for this...

public class FreeObject extends MovieClip{
		public function FreeObject(){
			super();
		}

The constructor function. Force of habit.

public function rotateAboutPoint(vx:Number, vy:Number, vr:Number = 1):void{
			var radianangle:Number = vr * Math.PI / 180;
			var nowangle:Number = Math.atan2(y - vy, x - vx);
			var nowlength:Number = Point.distance(new Point(vx, vy), new Point(x, y));
			var newangle:Number = nowangle + radianangle;
			var newpos:Point = Point.polar(nowlength, newangle);
			
			rotation += vr;
			x = vx + newpos.x;
			y = vy + newpos.y;
		}
	}
}

The actual function for doing the rotation. Let's take a look at this line - by - line:

public function rotateAboutPoint(vx:Number, vy:Number, vr:Number = 1):void{

Sets up a function with three parameters - the x co-ordinate to rotate around, the y co-ordinate to and the angle in degrees. You replace the vx an vy parameters with a Point object if you prefer.

var radianangle:Number = vr * Math.PI / 180;
			var nowangle:Number = Math.atan2(y - vy, x - vx);
			var nowlength:Number = Point.distance(new Point(vx, vy), new Point(x, y));
			var newangle:Number = nowangle + radianangle;
			var newpos:Point = Point.polar(nowlength, newangle);

Right! These are the variables we'll be using in our function.

radianangle is a representation of our degree - angle in radians, since Flash's geometric functions generally use radians as inputs and outputs.

nowangle is the current angle between the point we'll be rotating around and the object's actual reference, also in radians.

nowlength is the current distance between those two points. You could always use good ol' Pythagorean distance formula, but the Point class looks cooler :P

newangle is what the angle between the point we're rotating around and the clip will be once the rotation is complete. It's obtained simply by adding the original angle to our rotation's angle in radians.

newpos, finally, is a point representing where our object will end up once the rotation is complete. It's obtained by using a pretty cool (IMO) method of the point class, where a vector represented by a distance and an angle (radians) is converted into a vector represented by x and y values. In cases or rotation like this, converting between the two is important.

rotation += vr;
			x = vx + newpos.x;
			y = vy + newpos.y;
		}
	}
}

This adds our rotation value to the clip we're rotating. If you're doing something like a pendulum which doesn't require the actual object to rotate, you can skip this bit.

It also sets our clips new x and y values. Since the newpos point is based from the origin and not our centre of rotation, we need to add it to the vx and vy values representing the point we're rotating around.

Congratulation! You now have a class which you can assign to a DisplayObject, with this method:

rotateAboutPoint(point x, point y, angle)

Which you can access to rotate your object.

Want to see it in action? Name the file FreeObject, create a new Flash (AS3) document in the same folder and draw something. Convert it to a MovieClip, click on it in the library and in Linkage, select to export for ActionScript, type FreeObject as its base class and you should be good to go. You can set it as its main class, but then you'll only be able to link it to one object, so have the main class as something unique.

Give your object on the stage the instance name rotaty. Then just add this code to the main timeline:

import flash.events.MouseEvent;
import flash.events.Event;

stop();

var dwn:Boolean = false;

stage.addEventListener(Event.ENTER_FRAME, upd);
stage.addEventListener(MouseEvent.MOUSE_DOWN, ondown);
stage.addEventListener(MouseEvent.MOUSE_UP, onup);

function upd(ev:Event):void{
	if(dwn){
		rotaty.rotateAboutPoint(mouseX, mouseY, 2);
	}
}
function onup(ev:MouseEvent):void{
	dwn = false;
}
function ondown(ev:MouseEvent):void{
	dwn = true;
}

And you should be good to go. You may want to draw something in the background, since the mouse events won't register if they're over an unfilled area.

Here it is in action. Click anywhere and your object will rotate around it.

As a function, this isn't that complex. You should be able to adapt it to work with different co-ordinate spaces and things. As far as theory goes, I like to think of it in terms of a circle. You have your point you're rotating around in the middle, and your object on the circumference. So long as you know the radius and the angle around the circle at which your object is located, you know all you need to in order to express its position.

That's all, folks! Have fun!


BBS Signature

Response to AS3: Rotating objects around points 2007-09-30 15:35:24


My god, this looks fantastic with the new code tags, it makes it so easy on the eyes :D. Anyway, great tut, i might have a shot at this. Well explained and commented.


BBS Signature

Response to AS3: Rotating objects around points 2007-09-30 15:53:58


sorry about this mate, just think people should see the alternative

rather than using a geometrical method, you can use simple linear algebra to do the exact same thing with less operations, to execute faster and with less round-off errors.

basicly, you take the displacent of the clip from the point of rotation, rotate this vector using matrix algebra, and modify the clip position approptiately using this rotated vector

note the angle to rotate 'P' is obviously in radians here

var toDeg:Number = 180/Math.PI;
function rot(m:Sprite,rx:Number,ry:Number,P:Number):void
{	
	var dx:Number = m.x-rx;
	var dy:Number = m.y-ry;
	var cos:Number = Math.cos(P);
	var sin:Number = Math.sin(P);

	m.rotation += P*toDeg;
	m.x = rx+dx*cos-dy*sin;
	m.y = ry+dy*cos+dx*sin;
}

another point to bring up with is to do with flash's rounding of clip coordinates, and my suggestion is to use variables to store a clip position intially, then only modify that, then update the physical coordinate appropiately, that way you will never suffer from flash's rounding of clip coordinates and youll get noticable better looking rotations as you will notice if you hold mouse down on the edge of the graphic, you will see it moving out and around the point, rather than rotating properly around it - thats all to do with flash rounding off coordinates

Response to AS3: Rotating objects around points 2007-09-30 16:17:40


Hey, I'm always open to improvements :P Like I said, I just threw this together for demonstration purposes. If I had a specific purpose intended I could probably really do with greater efficiency.


BBS Signature