views:

576

answers:

4

Hi,

I have created a flash app in which there is a circle with circles plotted along it's circumference, it is rotated when the mouse is moved up or down. The rotation is drawn directly from the y position of the mouse pointer. What I would like to do is grade the movement some how so that the further down the mouse pointer goes the less impact on rotation the movement has.

My current code is like this:

myCircle.rotationZ = e.localY;

Is there some form of math formula I could use which would reduce the amount of rotation the greater the y position of the mouse position?

Thanks,

eb_dev

A: 

There are any number of ways to do what you want. Basically it sounds like you're trying to take the linear Y coordinate and turn it into a curve.

Something like this might do what you want (I'm a bit rusty at AS3 so it will need some tweaking but it should give you the idea - YMMV):

var distance:Number = (Stage.Height - e.localY) / Stage.Height;
distance = distance * distance;
myCircle.rotationZ = distance * 2 * 3.1415927;

It's converting the distance into a number from 0 to 1 where 0 is at the bottom and 1 is at the top.

Distance is then adjusted from a linear to parabolic curve.

Finally we convert the value from the range 0 - 1 to 0 to 2PI (the rotation angle).

Aaron
...and you can replace the hardcoded PI value with Math.PI for increased code beauty. :)
Niko Nyman
Hi Aaron, thanks for your speedy reply, this is the kind of thing I was looking for, though my maths not being great why do you multiply that distance by itself?
eb_Dev
@eb_Dev - distance is multiplied by itself (squared) to turn it from a linear relationship to a curved relationship between the input and output. That way the movement is slower at the bottom than the top.
Aaron
+1  A: 

Well, it depends on how fast you want to decay the rotation angle. You can use simply use linear decay.

rot = ((Rmax - Rmin) / (Ymax - Ymin)) * y + ((Rmin * Ymax) - (Rmax * Ymin)) / (Ymax - Ymin)
Above expression will change the rotation angle 'rot' linearly from Rmax to Rmin depending on 'y' value from Ymax to Ymin. The same thing you can do using exponential decay.
Maths behind it:
rot = a * y + b //(where a,b are constants)
first boundary condition
Rmax = a * Ymax + b
second boundary condition
Rmin = a * Ymin + b
Solve above 2 equations to find out a and b.
a = (Rmax - Rmin) / (Ymax - Ymin)
b = ((Rmin * Ymax) - (Rmax * Ymin)) / (Ymax - Ymin) 

bhups
thanks bhups, that's great, is this quite a common expresssion? Just wondering if there is an explanation for it somewhere?
eb_Dev
I have added the maths behind it.
bhups
Thanks that's great.
eb_Dev
A: 

bhups is right. Here is the Exponential version Please don't be scared by the name,read the comments and visit wikipedia for a visual representation :)

var scale:int=360;

var val:Number;

//From the exponential graph I chose the interval [-5,0]

//Consult http://en.wikipedia.org/wiki/Exponential%5Ffunction , the image on the top-right

//corner for visual

/*For a value of 0 Math.exp returns 1;While going down to -5 it returns

values closer and closer to 0

*/

var intervalMaxValue:Number=0;

/* Warning! if you change the intervalMaxValue to something different than 0 you have to revise the formula */

var intervalLength:Number=5;

stage.addEventListener(Event.ENTER_FRAME,handlerEnterFrame);

function handlerEnterFrame(e:Event):void{

/* intervalMaxValue-intervalLength -> we start at -5

1-(stage.mouseY/stage.stageHeight)) * intervalLength -> and gradually add a number between 5 and 0 as the mouse goes down

Math.exp -> transforms it into something between 0 and 1 for this interval that ends with 0

scale -> Multiply it by scale to get the full 0-360 interval*/

val=Math.exp(intervalMaxValue-intervalLength+((1-(stage.mouseY/stage.stageHeight)) * intervalLength))*scale;

myCircle.rotation=val;

}

Oliver
Hi Oliver, thanks for your reply this is very informative, I have come across the exp function before but not really known what to do with it. The formula that goes in the exp function...is there an explanation for this somewhere? I'm struggling to visualise how it works.Also slightly off topic, could you recommend a good book to learn about this stuff?
eb_Dev
You are welcome!Please see my next answer for a detailed explanation of the formulaA book that can guide you trough animation using math isFoundation Actionscript 3.0 Animation: Making Things Move! but I must warn you it doesn't say anything about using the exponential function.Still it has a lot of interesting stuff and it's quite easy to follow by beginers.I could explain the formula better over Skype if you want toCheers
Oliver
A: 

alt text

The above graph is from -4 to 4 on the x axis , it's easy to figure out the y value for x=-5 - it's almost 0 - so please consider this when reading the following.

Please see the above graph, it's the graph of the exponential function. See how it grows for x values from -5 to 0? It's not a linear growth but rather it's a bigger and bigger growth while it reaches 0. This is exactly what you need for your animation.

val=Math.exp(intervalMaxValue-intervalLength+((1-(stage.mouseY/stage.stageHeight)) * intervalLength))*scale;

intervalMaxValue-intervalLength is actually 0-5 which would be -5

So we start with -5!

Next

stage.mouseY/stage.stageHeight = 0 when your mouse is at the top of the stage(as stage.MouseY would be 0) and 1 when the mouse is at the Bottom of the stage ( stage.mouseY is then equal to stage.stageHeight so you divide stage.stageHeight by stage.stageHeight which will be 1)

For your effect you want it to be inverted, 1 when you are at the top and 0 when you are at the bottom so that's why you have to use (1-(stage.mouseY/stage.stageHeight))

Now when the mouse is at the top the above formula returns 1 and when it's at the bottom returns 0 ( exactly like you want it to behave , a big spin when it's at the top and a small one when it reaches the bottom )

Let's now take only the Math.exp part and see how it behaves

val=Math.exp(intervalMaxValue-intervalLength+((1-(stage.mouseY/stage.stageHeight)) * intervalLength);

When your mouse is at the TOP the above formula would be -5+((1-(0))*5(<-- 5 is here the intervalLength); this would return 0. Take a look at the graph now, for 0 on the x axis you get 1 on the y axis.

Now let's see what happens when the mouse is at the BOTTOM -5+(1-(1))*5; this would return -5. For -5 on the x axis you get something very close to 0 on the y axis as you can see in the image above.

Let's see what happens when the mouse is at the MIDDLE -5+(1-(0.5))*5; this would return -5+2.5 which would be -2.5.For -2.5 on the x axis you have something more closer to 0 on the y axis rather than on 1.This is what the exponential function does.

As you can see, on this interval [-5,0] the exponential function generates a y value from 0 to 1 and this value's growth is bigger as it approaches the x value of 0.

Considering that it generates a value from 0 to 1, that drops a lot while going to -5, you now multiply this value with 360 so you will get an angle value out of it.

At the TOP, the angle value is 1*360;

MIDDLE: the Math.exp for -2.5 returns a value somewhere near 0.1, multiply this by 360 and you get 36.If you compare it to the 360 for the TOP of the stage you observer that it sharply fell while the mouse reached the middle.

BOTTOM: Math.exp for -5 returns a value very close to 0. Multiply 0 with 360 and you get no angular movement. So when mouse is at the bottom of the stage the rotation value is extremely close to 0.

Hope this is clear, it was written at 6:53 AM, after a night in the club and a few shots of whiskey :)

Cheers.

Oliver
Wow thanks for taking the time to write all that out and after you'd been to a club aswell! I'm going to have a good read and digest this now, may well be back with more questions! Cheers.
eb_Dev
If you you're stuck somewhere don't forget to ask :)
Oliver