Well MatrixTransformer provides an easy way for you to do this with 1 line of code! In the fewest lines possible, here is how you can rotate a movie clips 45 degrees around the mouse position:
import flash.geom.Matrix;
import fl.motion.*;
var mat:Matrix = clip.transform.matrix;
MatrixTransformer.rotateAroundExternalPoint(mat,mouseX,mouseY,45);
The code above gets the clip's current matrix, modifies it, and reapplies it back to the clip. Pretty slick! The MatrixTransformer class provides a few other useful methods. The only thing that I find a bit odd is that it takes degrees instead of radians.
Here is a more practical example use of this code. (Practical from a game programmer's point of view.) Just click and hold on an object. It will hold that point it place as the object simulates a realistic rotation.
26 comments:
Cool blog, i just randomly surfed in, but it sure was worth my time, will be back
Deep Regards from the other side of the Moon
Biby Cletus
Cool to know. 30 minutes? I can recall more like 3-5 hours once but to be fair I was trying to fit it into an existing architecture and, it was was Flash 8. (If this was in Flash 8/AS2 I think I'd be embarrassed right about now.)
Thanks, Phillip
Hi Jobe,
Where is the fl.motion package? Is this something you have written that is available?
Cheers,
Adrian
Hi,
I did not create those classes. They come installed with Flash where ever Flash installs the classes (differs per OS).
Great Work.. love it
Hey, that looks really good and is helping along with what I'm doing.
A couple of questions though: Firstly, I can't find fl.motion, it seems to throw up an error for no reason. It's listed in Flash CS3 on the left hand side, but no clue as to the whereabouts ...
Secondly - I'm trying to pre-render however many rotations are required for a particular image, and making sure that they are always rotated around the center for obvious reasons. What would be the best way to achieve this? I'm struggling to find a high-quality and glitch-free way to get this working!
Good stuff - thanks! :-)
Hi,
If you wanted to precache rotations then you can use the snapshot function I talke about in this post:
http://jobemakar.blogspot.com/2007/05/taking-movieclip-snapshot.html
If you cache 1 shot per degree, then you'd have an array with 360 elements per image. You can precache this in the beginning of your applicaiton. Or you can check to see if it has been cached when it is time to render that rotation. If no, then cache it. That would mean your app starts off a little slow and speeds up the more it is used.
Hi Jobe,
Thanks for your help - I was planning on doing something just like that, and will certainly look at that link in detail - cheers!
What about the lack of being able to get fl.motion.* imported, or anything like that for that matter? (As in, I've tried without ".*", tried .MatrixTransform, etc etc...)
It is an ActionScript 3 package. If you're trying to do this in AS2, then that is your problem. If you're doing it in AS3 then it sounds like for some reason you might be missing that package, or have a typo.
Hey,
It is AS3, using the Flex compiler (not compiling with Flash CS3 or anything as it's only a trial version and don't want to get into that habbit!). Also not a typo, as I've tried variations, and have copied directly from you.
So, how could I be missing that package? Does it not all come with the normal install? If not, I'll go forth and try and find out where to obtain said package!
Cheers!
Okay so I've figured out the problem - I think...
Flex does not have fl.motion - only Flash does. (!?!). So, now the important question - is there any way to actually get fl.motion working on Flex? I've read somewhere about bringing it across using XML but from what I can tell this is just a bridging mechanism - or, is there any alternative, given that rotation is my biggest concern here?
Thanks - appreciate any help! :-)
Hey Jobe,
I've been following your blog (silently) and I have a situation that relates to this post.
I'm making an interface for a website that will be similar to www.leoburnett.com . I first did it by placing the entire site within a container and then offsetting the site within the container to in effect change the registration point.
I do not like this method.
I would prefer to have the site complete controlled mathematically. It seems less prone to glitches and hacks, and all around more flexible and dynamic ( ie. no hacks required for clicking on a link, while another one is already zooming in ).
So here's the problem: the method you posted is only for relative angles. It is great for an exponential (or elastic in your specific example) implementation.
ie. rotation += (goal - rotation)/10;
Now instead of adding the rotation directly, just replace the deltaAngle parameter of the rotateAroundExternalPoint function with "(goal - rotation)/10" or something of the sort.
The problem with this is that its hard to control the timing and finishing. It's great for something like you showed: a physics simulation which is constantly updating and exact timing is not important, but it is not so great for something that has a definitive start and end (namely a website's navigation animation).
So my proposed solution is to create a tween for a "temporary" rotation variable using the fl.transitions package and finding the difference in the value of the tweened property after each Tick passing that deltaTempRotation to rotateAroundExternalPoint.
This seems like it would not function "perfectly" though. I'm worried that the final value may not be exactly the final value that you passed to the tween's constructor. This is very important. If it is not exact pixel fonts may not align properly. It has to be as accurate as Flash allows!
So what do you think of this method? Can you lead me in a better direction?
Thanks,
Martin Munoz
munozm@mcmaster.ca
Hi Jobe, I wrote the fl.motion package; it's cool to see you found MatrixTransformer.
Martin, if you want absolute rotation around a point, you can easily edit the rotateAroundExternalPoint() method. The original code is fairly simple:
public static function rotateAroundExternalPoint(m:Matrix, x:Number, y:Number, angleDegrees:Number):void
{
m.tx -= x;
m.ty -= y;
m.rotate(angleDegrees*(Math.PI/180));
m.tx += x;
m.ty += y;
}
The logic is simply "shift to the origin, rotate, then shift back".
You can change the middle line of code to:
setRotation(m, angleDegrees);
If you prefer radians, you can do this instead:
setRotationRadians(m, angleRadians);
Here's the code for setRotationRadians:
public static function setRotationRadians(m:Matrix, rotation:Number):void
{
var oldRotation:Number = getRotationRadians(m);
var oldSkewX:Number = getSkewXRadians(m);
setSkewXRadians(m, oldSkewX + rotation-oldRotation);
setSkewYRadians(m, rotation);
}
Oh boy, now you need the code for the skew as well:
public static function setSkewXRadians(m:Matrix, skewX:Number):void
{
var scaleY:Number = getScaleY(m);
m.c = -scaleY * Math.sin(skewX);
m.d = scaleY * Math.cos(skewX);
}
public static function setSkewYRadians(m:Matrix, skewY:Number):void
{
var scaleX:Number = getScaleX(m);
m.a = scaleX * Math.cos(skewY);
m.b = scaleX * Math.sin(skewY);
}
The docs for MatrixTransformer are
here.
Oh right, the skew methods call the scale methods. Here they are:
public static function getScaleX(m:Matrix):Number
{
return Math.sqrt(m.a*m.a + m.b*m.b);
}
public static function getScaleY(m:Matrix):Number
{
return Math.sqrt(m.c*m.c + m.d*m.d);
}
Hey penner, what you are you doing here?! :)
Does anyone know if the entire MatrixTransformer class exist anywhere for AS2?
Thanks!
thanks a lot for this post! is verry helpfull!! thanks!
Great post thank you!
but i have a question. How do you get the bitmapData to stay smooth?
When i do it, the bitmap rotates but it looks jagged and not anti-aliased.
Can you please post that part of the code?
thank you!
Hi,
Find the bitmap in the library, double-click it, select 'allow smoothing'.
Hi, Jobe!
Your sample doesn't seem to include the gravitational physics code. For example if you click the lower-right side of an object it swings down from the upper left and oscillates until stopping.
If that code is proprietary then could you at least point us in the direction of something like it, thanks!
Hi,
Thanks for the example... is it available for download so I can see how you get the realistic movement?
Whenever I apply the code it just seems to jump from one position (eg.zero rotation) to the specified rotation (eg.200 degrees). it doesn't do the tweening in between.
ThankyouThankyouThankyou
Great idea, but I am having a problem using it. This demo also illustrates the problem.
Click a corner pixel and let it swing. The corner pixel wanders away from it's original position. It seems to be due to the gradual summation of rounding errors. How can I fix this?
John McCormack
This was perfect, thank you SO much. I had a 3d engine I'd stopped working on which this tip has revived. Thanks again!
Thanks a lot. I was googling this issue and came across many unnecessarily complicated solutions.
Thanks! I was doing it manually the whole time by moving the movieClip by a distance I had to work out with a Cos and Sin call - I'm hoping this is less expensive!
Post a Comment