Forum Topic: AS3: Rotating with Matrices

(537 views • 2 replies)

This topic is 1 page long.

<< < > >>
None

Paranoia

Reply To Post Reply & Quote

Posted at: 1/6/08 12:35 PM

Paranoia DARK LEVEL 33

Sign-Up: 04/22/05

Posts: 9,692

AS3: Main - The ultimate tutorial reading experience

If anyone saw my last tutorial on rotating around points, this is a much cleaner and faster way to achieve the same effect, now that I actually vaguely know how to use matrices.

I'm working in two dimensions here, but this theory can also be applied to three.

You don't need to know anything about matrices for this tutorial - just take my word for things.

What is a matrix?

A matrix is essentially a rectangular set of data which can be manipulated in various ways. In my feeble attempt to represent them with text alone, they look something like this:

[ 0 5 6 ]
[ 7 4 2 ]
[ 3 4 5 ] // This is supposed to be a single matrix. This one doesn't mean anything - it's just an example.

A brief introduction

Since I'm not going to go through an entire tutorial on further maths here, here are three facts which you should understand if you want to make sense of what follows:

1. An object's position can be expressed by a single matrix:

[ x ]
[ y ] // This is a much more meaningful matrix for our purposes.

If you want, you can also consider that the above example is equal to:

x [ 1 ]
[ 0 ]

+

y [ 0 ]
[ 1 ]

2. A transformation can also be expressed by a matrix.

For example, the following represents a reflection in the x axis:

[ 1 0 ]
[ 0 -1 ]

And a rotation anti-clockwise by n radians is:

[ cos(n) -sin(n) ]
[ sin(n) cos(n) ]

3. Multiplying matrices together is weird.

For a start, the order in which the matrices are placed matters - (A * B) = (B * A) when A and B are numbers, but not for radians.

I don't really want to get into this right now, but to multiply:

[ a b ][ x ]
[ c d ][ y ]

You go along the columns of the first value and rows of the second, multiplying each pair together and adding on, so the result of the above would be:

[ (ax + by) ]
[ (cx + dy) ]

Since we're on the subject of transformations, the last matrix represents the new values of x and y after being transformed by the matrix with a, b, c and d.

A rotational transformation around the origin

As we've already established, the matrix:

[ cos(n) -sin(n) ]
[ sin(n) cos(n) ]

gives us a rotation anti-clockwise by n. This is true of the sort of graphs you may draw in school, with axis pointing in sensible directions. Since Flash features an inverted y axis, though, anti-clockwise equals clockwise, which is convenient for us.

So, let's hurry things along. To rotate an object n radians clockwise, we use:

[ cos(n) -sin(n) ][ x ]
[ sin(n) cos(n) ][ y ]

=

[ x(cos(n)) - y(sin(n)) ]
[ x(sin(n)) + y(cos(n)) ]

=

[ new x ]
[ new y ]

To put that into code:

import flash.events.MouseEvent;

stage.addEventListener(MouseEvent.CLICK, onClick);

function rotateClockwise(vc:DisplayObject, va:Number):void{
	var ma:Number = (va * Math.PI) / 180;  // convert an angle from degrees to radians
	var myx:Number = vc.x;  // we hold onto the x value since it changes before we're through with it
	vc.x = (Math.cos(ma) * vc.x) - (Math.sin(ma) * vc.y);
	vc.y = (Math.sin(ma) * myx) + (Math.cos(ma) * vc.y) ;
}
function onClick(ev:MouseEvent){
	rotateClockwise(mr_rotaty, 10);
}

Try the above code by naming an object 'mr_rotaty'. It should rotate 10 degrees around the top-left corner every time you click.

So far so good

...but what good is just rotating around the origin all the time? We need to add in a couple of options so you can get rotation around any object you choose.

Well, the clip's co-ordinates are relative to the origin, so all we really need to do is subtract the co-ordinates of whatever we want to rotate around before the transformation, then add them back on at the end:

import flash.events.MouseEvent;

stage.addEventListener(MouseEvent.CLICK, onClick);

function rotateClockwise(vc:DisplayObject, va:Number, vx:Number = 0, vy:Number = 0):void{
	var ma:Number = (va * Math.PI) / 180;
	var dx:Number = vc.x - vx;  //  the difference between the clip's x and y 
	var dy:Number = vc.y - vy;  //  values and what you want to rotate around
	vc.x = (Math.cos(ma) * dx) - (Math.sin(ma) * dy) + vx;  //  pretty much the same, except this time we add the
	vc.y = (Math.sin(ma) * dx) + (Math.cos(ma) * dy) + vy;  // difference back on to get us back to the right co-ordinate space
}
function onClick(ev:MouseEvent){
	rotateClockwise(mr_rotaty, 10, mouseX, mouseY);
}

Try that code in the same circumstances as the last one - your clip should now rotate 10 degrees around your mouse every time you click.

And to sing us out...

If you want the actual graphics to rotate around your point as well (I didn't add that into the main tutorial this time since it seemed fairly specific) is pretty straightforward. Just add this line:

vc.rotation += va;

I won't insult your intelligence by telling you where it goes.

One last thing

Flash, and indeed everything, has accuracy problems when it comes small, long or irrational numbers (such as, say, sine or cosine of most things). This shouldn't be a problem for general rotation, but if you're trying to make anything which needs to stay realistic, such as, for example, something that's going to be running for extended lengths of time, it's probably a good idea to store the object's original x and y as variables and base your rotations off of those rather than their values after the last change.

That's about it for this.

Thanks to

dELtaluca - http://deltaluca.newgrounds.com/ - for introducing me to matrices in the first place
Gust - http://gusttheasguy.newgrounds.com/ - for constantly reminding my of how crappy and inaccurate Flash is

So long

Tutorial by
- Eddy Larkin
- Paranoia

BBS Signature

None

GustTheASGuy

Reply To Post Reply & Quote

Posted at: 1/6/08 12:50 PM

GustTheASGuy LIGHT LEVEL 08

Sign-Up: 11/02/05

Posts: 11,329

Wait, what? :P

Pssh, this has hardly any application (apart from getting the idea of skewing by code) and you didn't mention 3d transformation.

#ngprogramming at irc.freenode.net
haXe | Keel imperative | Spyro! | Thru you


None

Paranoia

Reply To Post Reply & Quote

Posted at: 1/6/08 12:58 PM

Paranoia DARK LEVEL 33

Sign-Up: 04/22/05

Posts: 9,692

At 1/6/08 12:50 PM, GustTheASGuy wrote: Wait, what? :P

Pssh, this has hardly any application (apart from getting the idea of skewing by code) and you didn't mention 3d transformation.

It has tonnes of applications for anyone who wants to even approach realistic physics in Flash, not to mention plotting all kinds of motion :P

Besides, anyone who's going to work out a 3D engine in Flash shouldn't have much problem seeing that this can easily be converted to cover a thrid dimension.

BBS Signature

All times are Eastern Standard Time (GMT -5) | Current Time: 04:28 AM

<< Back

This topic is 1 page long.

<< < > >>
You need a Grounds Gold Account to post on the NG BBS! If you don't have one, click here to sign up now! It's fast, free, and easy — and opens up tons of great NG features!