Angles-Rotation-Limits?

BlitzMax Forums/BlitzMax Beginners Area/Angles-Rotation-Limits?

Amon(Posted 2005) [#1]
I have a spinning ball that spins about it's center. I use this code to prevent the angle increasing forever but it has a snag. Whenever I want to change the direction the ball spins it locks up or skips.

If RotAngle >=360 then RotAngle = 0
If RotAngle <=0 then RotAngle = 360

Now the problem is that if any of the balls have an angle of 0 it's changed to 360 and if any have an ang;e of 360 it's changed to 0. This is where the problem is. The two lines of code fight eachother when checking the Max angle.

I thought I would try and leave the angle for one direction and not check it but it just goes in to negative and increases.

What would be the best method to make sure that the positive and negative values never go beyond 360/-360 and bringing them to 0 safely without conflicts?

Thanks :)


(tu) ENAY(Posted 2005) [#2]
This is a bit better.
If RotAngle >359 then RotAngle :- 360
If RotAngle <0 then RotAngle :+ 360


[edit]
Besides, just follow your code:-

RotAngle = 380
If RotAngle >=360 then RotAngle = 0

RotAngle = 0
If RotAngle <=0 then RotAngle = 360

RotAngle = 360
If RotAngle >=360 then RotAngle = 0

RotAngle = 0
If RotAngle <=0 then RotAngle = 360

RotAngle = 360
If RotAngle >=360 then RotAngle = 0

RotAngle = 0
If RotAngle <=0 then RotAngle = 360

RotAngle = 360


Can you see the problem yet? ;)

Remember there is no such thing as the 360th degree, only 0-359.


Amon(Posted 2005) [#3]
Hahah, Thanks Enay. It works perfect. Now make me a cheese sandwich :)


PetBom(Posted 2005) [#4]
I usually solve these ping-pong behaviours of values by adjusting the value with an operator and keeping it in range with min max values.

Example:
Global angle:Int = 0
Global maxAngle:Int = 360
Global minAngle:Int = -360
Global operator:Int = 1

Repeat
  
  angle:+operator
  
  If angle > maxAngle or angle < minAngle Then

    'Here's the trick! You invert the operator
    'when you reach min or max! 
    operator = - operator

  End If

Forever


The advantage of adjusting the angle value with the operator is that you only get one place in the code where you actually modify the angle value. The 'direction' of the adjustment is handled by the operator and the min/max values. Encapsulation and separation of concerns!

EDIT: Ooops! I just realized that you did not want a ping-ponging value... You wanted to wrap it! Sorry.


//PetBom


Oddball(Posted 2005) [#5]
Remember there is no such thing as the 360th degree, only 0-359.
What an odd statement. Most of the Max commands return angle ranges of -180<=angle<180. And 360 degrees works exactly the same as 0 degrees in almost all situations. Also if you cap angles at 359 you'll never be able to have an angle of 359.5


Shagwana(Posted 2005) [#6]
would this be of any use?

RotAngle :+ Alter 'alter by a minus or a posative number

While RotAngle<0.0 ; RotAngle:+720.0 ; Wend 'Ensure its a posative number
RotAngle = RotAngle Mod 360.0 'Limit it from 0.0 to 360.0


It will let the number wrap around.


Oddball(Posted 2005) [#7]
And here's a much better way(IMO) to roll over angles.
While RotAngle>=180
  RotAngle:-360
Wend
While RotAngle<-180
  RotAngle:+360
Wend



PetBom(Posted 2005) [#8]
Ehhhh...You guys mean If/EndIf and not While/Wend, right?


Oddball(Posted 2005) [#9]
Ehhhh...You guys mean If/EndIf and not While/Wend, right?
No.

To explain a little more. The While/Wend method allows for large angle jumps of 360 degrees or more. Using If/Endif in this situation would still leave your angle out of the desired range.

To make the code a little more usable I would make a function from it so it is reusable in many situations.
Function WrapAngle:Float(ang:Float)
  While ang>=180
    ang:-360
  Wend
  While ang<-180
    ang:+360
  Wend
  Return ang
End Function
And then you could use it thus.
RotAngle=WrapAngle(RotAngle)



(tu) ENAY(Posted 2005) [#10]
I think my way is most efficient, ;)
Although admittedly there will be a problem is you move more than 360 degrees in either direction in any one frame.

> What an odd statement. Most of the Max commands return angle
> ranges of -180<=angle<180.

I'm talking in the literal sense, because there are only 360 degrees in a circle. To go lower or higher is simply wrapping around the other side. Sure you can have -70 and 700, but mathematically speaking they're still variants of 0-359.999999etc. That's what I was saying. :)


Nelvin(Posted 2005) [#11]
Value = Value Mod 360
If Value < 0 Value :+360


ImaginaryHuman(Posted 2005) [#12]
I was going to say, why hasn't anyone mentioned Mod yet? But Nelvin got to it finally.


Shagwana(Posted 2005) [#13]
I was going to say, why hasn't anyone mentioned Mod yet? But Nelvin got to it finally.
Is my post invisable!


FlameDuck(Posted 2005) [#14]
I was going to say, why hasn't anyone mentioned Mod yet? But Nelvin got to it finally.
Except unlike Shagwanas version, his doesn't compensate for very large fluctuations in "negative" angles.


Nelvin(Posted 2005) [#15]
It does of course, there's just no reason to use any loops at all (introducing an O(n) complexity where O(1) does the job)


TomToad(Posted 2005) [#16]
Wow, did mark fix the mod command? I remember in Blitz3D, MOD being so slow that if..endif and when...wend was preferable. Just did some tests on max and MOD wa 5x faster.


Shagwana(Posted 2005) [#17]
Nelvin wins, his way is best :o)


ImaginaryHuman(Posted 2005) [#18]
You could do:

Value = Value Mod (360*Sgn(Value))