_xscale & _yscale

2008-07-12 15:10:54 by mike
Updated

In Flash, throw a movie clip on the stage and give it an instance name of "clip". Go to Modify -> Transform -> Flip Horizontal. Then do a trace(clip._xscale); 100 is traced, even though you might expect -100. What gives?

Short Answer:
Flipping horizontally is the same as flipping vertically and rotating 180 degrees. This means that _xscale and _yscale can either be positive or negative. Flash can't really tell which you've done, so it assumes positive.

Long Answer:
The position info of every graphic in Flash is stored as a 3x3 homogeneous matrix:

[[ a b tx ]
[ c d ty ]
[ 0 0 1 ]]

This is a combination of a scale, rotation, skew, and translation.

A scale transformation looks like:
[[ x 0 0 ]
[ 0 y 0 ]
[ 0 0 1 ]]
where x and y are the amount of scaling on the x and y axis. Note that _xscale = x*100

A rotation transform is:
[[ cos(t) sin(t) 0 ]
[ -sin(t) cos(t) 0 ]
[ 0 0 1 ]]
where t is the amount of rotation.

Combine these by matrix multiplication, and you get:

[[ x*cos(t) x*sin(t) 0 ]
[ -y*sin(t) y*cos(t) 0 ]
[ 0 0 1 ]]

Flash only knows the final values (a, b, c, d). We know a = x*cos(t) and b = x*sin(t). You can start to see the sign ambiguity appear already -- whenever you multiply two values, you lose some information about the signs of those values.

To calculate _xscale, Flash has to solve for x. Your first thought might be x = a/cos(t), but that requires you to find out t. A more elegant way to solve this is to realize that the ( x*cos(t), x*sin(t) ) in the first row is just a vector x units long, in the direction of t. So x is just the length of the vector:

x = sqrt( a^2 + b^2 )

This makes sense intuitively, too -- because a scale transformation just scales a basis vector, (1, 0), by x. Rotation changes this more, but it doesn't affect vector length! So getting the magnitude of this vector tells you the amount of scaling.

You can chug through the math to see that this identity holds:
sqrt( a^2 + b^2 ) = sqrt( (x * cos(t))^2 + (x * sin(t))^2 )
= sqrt( x^2 * cos^2(t) + x^2 * sin^2(t) )
= sqrt( x^2 * ( cos^2(t) + sin^2(t) ) )
= sqrt( x^2 * 1 );
= +/- x

Since _xscale and _yscale are the result of a square root, we get two solutions, either + or -.

When you do _xscale = -100 in ActionScript, why does Flash trace(_xscale) as -100 then? Because whenever you set _rotation, _xscale, _yscale, Flash actually caches the value you passed and returns that, instead of wastefully recalculating it!


Comments

You must be logged in to comment on this post.


KupaManKupaMan

2008-07-12 15:44:43

Whoa, that just melted my mind.


PhilPhil

2008-07-12 16:13:40

My mind blew up. x(


DobermanDoberman

2008-07-12 16:34:39

is this basically an easier process in flash then or. . . .?


Kart-ManKart-Man

2008-07-12 17:16:17

...Has anyone ever told you that you should become a math teacher?


Wingle-FlotzWingle-Flotz

2008-07-12 17:33:54

I have NO idea what you just said, but i'm gonna try and figure it out. Or, my brain'll shrivel up and die in the process. That was a useless comment, wasn't it?


TjATjA

2008-07-12 19:07:33

thats pretty smart how flash does that, how did you find that out?


Atgod88Atgod88

2008-07-12 19:13:25

What do you think I am, a freakin' rocket surgeon?


WholyishWholyish

2008-07-12 22:02:40

wow... that actually made sense to me, though ive never dealt with the scenario. thanks for that, ill keep it in mind. (you might want to explain the matrices and trig a little more for the typical newgroundser)


WiiporterWiiporter

2008-07-13 00:40:25

*pop*


Matt475Matt475

2008-07-13 00:48:34

Yeah I understood that


SirkowskiSirkowski

2008-07-13 01:19:18

...and that's why I only make drawings. x_X


KidlazarusKidlazarus

2008-07-13 01:45:46

I understand the mathematical lingo but you lost me in the ActionScript...


WolfBlitz2WolfBlitz2

2008-07-13 03:25:27

I think my brain broke


Drift-And-DieDrift-And-Die

2008-07-13 06:44:07

what


The-Super-Flash-BrosThe-Super-Flash-Bros

2008-07-13 07:34:48

Flash is smart sometimes, but sometime not so helpful. You can see exactly how it stores the transform if you have the transform window open - type in -100% for width, then reselect the clip, you'll see it actually counts as a skew of 180 degrees

Try this one! Its a problem with AS3, I'm not sure if it used to do it in AS2. Bear in mind that height and width of a movieclip are always relative to its parent's x/y axis, not the clips own internal axis (unlike xScale and yScale)

Add a 100x100 square MovieClip to the timeline, call it mc and add this to the stage timeline:

mc.rotation = 90;
mc.width = 50;
trace(mc.width);
trace(mc.height);

You'll see that it completely scews up which way it scales! then try this:

mc.rotation = 90;
mc.width = 50;
mc.width = 50;
trace(mc.width);
trace(mc.height);

It seems like the first time it uses width (same goes for height) it hasn't updated the rotation on the clip, but the second time it has! Crazy Flash...

Tom-


vai90vai90

2008-07-13 09:28:05

I understood the main message, but I've never used a flash program. It'd be freaking awesome to have the skills of Adam Phillips, Michael Swain or Jeff Bandelin, but sadly I know not one thing about it and I'm afraid of these mathematical bullshit you seem to have to go through. I hate math. :|

Any advice?
xx Martin xx


ace210493ace210493

2008-07-13 09:29:03

i understand the maths
but i fell swamped out by actionscript


JonBroJonBro

2008-07-13 12:53:13

I have more problems with _height and _width acting as positive when I try making them negative than I have with _xscale and _yscale.


UberCreamUberCream

2008-07-13 14:04:43

I think my brain just popped... Painfully...


I-smelI-smel

2008-07-13 14:25:50

I think the point of this is:

Flash uses a square root function to flip things horizontally or vertically
the square root of any number is allways positive
so flipping something will allways give you a positive _xscale

I could be wrong there. Well done for finding out though.


ParanoiaParanoia

2008-07-13 14:42:20

Hehe, you certainly learn new stuff from your posts. I always wondered what that third column was for... Thanks for that link :P


WeirdoWeirdo

2008-07-13 15:02:04

All I know is that Flash applies trigonometry into it's programming. Except the plane is upside down and I think backwards.


MindChamberMindChamber

2008-07-13 15:12:14

my girlfriend_flipped when I X_scaled into her mouth


super-sensesuper-sense

2008-07-13 15:26:30

God I wish I understood action script. The only thing vaguely familiar to me is cos and sin. And it's been ages since i've done that.


VincoidVincoid

2008-07-13 15:42:07

My brain was about to die out, but Mindchamber's comment fixed that problem :P


mongoidmongoid

2008-07-13 16:13:56

Fascinating. Where did you learn this? Adobe forums?


SecretClockSecretClock

2008-07-13 16:36:50

0.99999 (repeating) = 1 because

1/3 = 0.33333333333333333333333

1/3 X 3=1 or 1/3 X 3= 0.9999999999999999999999999999999


SecretClockSecretClock

2008-07-13 16:51:04

Steven Hawking could explain better!

http://spamtheweb.com/ul/upload/13070 8/60172_bob2.mp3


gankrogankro

2008-07-13 16:58:12

I never liked trig anyway... I can code just about anything without looking something up except when trig comes up... I really shoulda paid better attention during that unit :/ ... Also: why does flash not have an _xskew/_yskew option yet?


Listen2ReasonListen2Reason

2008-07-13 17:23:55

Heh, interesting stuff! I didn't know Flash was actually using a complete 3x3 transformation matrix, but now that I do it all makes sense. ;)


Junky2005Junky2005

2008-07-13 18:05:48

lolwut?


KingKombatKingKombat

2008-07-13 20:22:10

..what the fu--?
*head explodes all over computer*


P-I-NP-I-N

2008-07-14 00:10:17

Great, someone give him a Nobel!!!

¬¬ I accept it; Impressing for teenagers.


ageofthoughtsageofthoughts

2008-07-14 00:52:31

I cannot comprehend what the fuck you just said back there...How did you get all this down in your head?


NyubisNyubis

2008-07-14 03:24:29

BOOOOOOMM!!!!
That was my head when reading the second part.
I'll stick to the short version...


DjmrDjmr

2008-07-14 04:34:30

When you flip the x axis in flash that way, the xscale is 100 since that is the new shape's scale. If you wanted to flip it in an .swf, flash records the old position, so that a scale of 100 would return the object to scale.

Flipping horizontally is different than changing the _xscale. Although it would do the same thing, these are two seperate functions. Its more common sense than having to look at the math of it, although I did understand that dreadfully, hated learning that stuff last year.


Alexman159Alexman159

2008-07-14 14:15:27

Thats wierd... Are you using flash CS3 because i'm pretty sure that flash cs3 was supposed to be the ultimate calculating system. (and you would think it wouldn't do something like that.)


GhostdemonGhostdemon

2008-07-14 20:56:41

If my mind was a Nuclear Power Plant,then you just set off another "Chernobyl"


04973351190497335119

2008-07-15 05:52:15

Ok , the mathematics are ok , but the actionscript are problematic :p


mranarchymranarchy

2008-07-15 21:42:05

Conclusion: I suck


jamesb1995jamesb1995

2008-07-16 08:53:03

AAAAAAAAAGGGH!! MY BRAIN EXPLODED!!!! AGGHHGHHH (foams at the mouth) *gag *blurb


BentRainbowsBentRainbows

2008-08-17 17:05:48

What.


EntropicOrderEntropicOrder

2011-06-29 12:09:32

Thanks for the thorough post Mike. I'm trying to create a solution that automatically sets scaleX to -1 if the stage placed instance is horizontally flipped, so that going forward I can just assume all left facing mc's are properly represented by scaleX being negative (otherwise I've been making them all face right and then flipping them programmatically as needed, which I'd rather not have to do).

I get that -scaleY and 180 rotation is equivalent to -scaleX. However, Flash CS3 is setting both scaleY and scaleX to positive and rotation to 180. Perhaps that's because of the sign ambiguity, I didn't take the time to fully understand the math here. However, if all I do is set the transform.matrix back to itself, then scaleY all of a sudden goes negative, so that it now works as I would expect, and I can then convert 180 rotation negative scaleY to negative scaleX as needed. Since all I did was set the matrix to what it currently is (the a,b,c,d values it already knew), this seems like a Flash bug that scaleY is not getting set to negative initially.

Here's the solution I came up with:
obj.transform.matrix = obj.transform.matrix; //resets scaleY to expected value
if(obj.scaleX > 0 && obj.scaleY < 0 && Math.abs(obj.rotation) > 90){
obj.scaleX *= -1;
obj.scaleY *= -1;
obj.rotation -= 180;
}