2D rotation interpolation
BlitzMax Forums/BlitzMax Programming/2D rotation interpolation
| ||
I'm trying to figure out a nice way to interpolate rotation without it flipping. I have a working code for it, but just have this nudging feeling that there is a better way to do it. Here is what I have now. Method AngleBetween:Float( x1:Float, y1:Float, x2:Float, y2:Float ) Local xd:Float = (x1-x2) Local yd:Float = (y1-y2) Local m:Float = 90 If xd < 0 Then m = 270 Local Angle:Float = ATan(yd/xd) + m If Angle = "nan" Then Return 0 Else Return Angle End Method ' And elsewhere in the code Method Update( Rotation:Int = 0) If Rotation And (Abs(Goal-Value)) > 180 Then If Value > 360 Then Value:- 360 If Value < 0 Then Value:+ 360 If Goal > 180 Then Goal:- 360 Else Goal:+ 360 End If Local Distance:Float = Goal - Value Local Acceleration:Float = (Distance - Vel*Lag)*2/(Lag*Lag) Vel:+ Acceleration Value:+ Vel End Method The Rotation input variable on the second method is just a flag to tell it if rotation is being interpolated, so that it can do some stuff to avoid flipping. The Update method take any number and moves it towards a goal with a physics like lag. Is there a cleaner way to do this? The "If Angle = "nan" feels a bit hacky, and the whole thing that flips the rotation with lots of If's in the second Method too. Cheers, Ragnar |
| ||
Check out these codes in the code archives |
| ||
Thanks for the pointer. The code samples there are basically doing the same thing, subtracting or adding 360 when the angle goes beyond 360 or under 0. Guess that's the way to do it then. :-) Ragnar |
| ||
use ATan2(). It gives the angle from -180 to 180 with 0 pointing right. Just add 360 if the result is less than 0Angle = ATan2(yd,xd) 'notice that yd is first parameter ' |-90 ' | ' -180 | 0 '------+------ ' 180 | 0 ' | ' |90 If Angle < 0 then Angle :+ 360 ' |270 ' | ' 180 | 360 '------+------ ' | 0 ' | ' |90 |
| ||
It's better to keep the original output of the ATan2 cause you will utomatically know if it's pointing upwards or downwards by signe ( - , + ). This will help you better to find which way (left or right) you have to turn to get at a desired angle. |
| ||
Hmmm. What would I do (mathematically) if I wanted the Atan2() output to generate 0 for screen-up (North) with positive angles being screen-right (East) and negative angles being screen-left (West)? |
| ||
Haramanai: I usually keep the ATan2 values, simply because that's the way I've always dealt with polar coordinates. But SetRotation expects 0-360, so you will need to correct for that. The r0nin: Angle = Atan2(yd,xd) + 90 If Angle > 180 then Angle :- 360 |
| ||
TomToad you are not right about that. You can use negative values for the SetAngel. Check out this : Strict Graphics 640 , 480 While Not KeyDown(KEY_ESCAPE) Cls Local dx = MouseX() - 320 Local dy = MouseY() - 240 Local angle = ATan2( dy , dx ) SetRotation angle DrawLine 320 , 240 , 340 , 240 SetRotation 0 DrawText angle , 10 , 10 Flip Wend Edit: Funny. We posted allmost the same example to defferent topics in the forum. |
| ||
From the docs Function SetRotation( rotation# ) Description Set current rotation. Information rotation is given in degrees and should be in the range 0 to 360. It might work now, but we can't rely on it to always work like that. |
| ||
OH. Simple (duh!). Thanks, TomToad! |