Circle movement.

Blitz3D Forums/Blitz3D Programming/Circle movement.

spriteman(Posted 2008) [#1]
Hi All,

I have a little problem with a program I have created to move a sprite in a circle around a centre point. When the angle reaches 360 degrees I would lile the angle to reset to 0 and start again. Adjusting the speed of the rotation sometimes causes the If condition to be missed due to floating point inacuracy.

i,e If S\SA#=360 Or S\SA#=360 Then S\SA#=0

Function below usng types, any Ideas,

Function updateships()
For s.ship = Each ship

Local shipx#, shipz#

;update shipangle# and maintain speed at different distances
S\SA#=S\SA#-(S\SP#/S\SD#)
If S\SA#=360 Or S\SA#=-360 Then S\SA#=0

;Update position around radius using the sin/cos functions
shipx# = S\SCX# + ( Cos#(S\SA#) * S\SD# )
shipz# = S\SCZ# + ( Sin#(S\SA#) * S\SD# )

;draw the ship
PositionEntity S\SIMAGE,shipx#,S\SY#,shipz#
RotateEntity S\SIMAGE,0,(S\SA#-90),0

If S\SID%=0 Then
SNAME1=S\SNAME
SA1#=S\SA#
SX1#=shipx#
SZ1#=shipz#
SSP1#=S\SP#
End If

Next
End Function


Gabriel(Posted 2008) [#2]
Replace

If S\SA#=360 Or S\SA#=360 Then S\SA#=0

With

If S\SA#>=360
S\SA=S\SA-360
End If

Or if you could possibly go more than one rotation in a go ( perhaps if the program is minimized during use and then maximized again ) then you could do this

While S\SA>360
S\SA=S\SA-360
Wend


I don't really understand why you have an Or in that If statement at all, since both conditions are the same. So if they were supposed to be different, then you may need to adjust the answer, but that's the principle, and it will even deal with situations where you go through more than one turn in a single frame ( eg: when your app is minimized for a while. )


Jasu(Posted 2008) [#3]
There's basically no need to "normalize" an angle, since Sin() and Cos() functions work without it. But I agree that if this ship exists long enough, the angle starts to lose accuracy so that it becomes visible.

The normalizing should be done both ways if object can rotate clockwise too.
Function NormalizeAngle#(ang#)
   If ang >= 360.0 Then 
      return ang Mod 360.0
   ElseIf ang < 0.0 Then
      While ang < 0.0
         ang = ang + 360.0
      Wend
   EndIf
   Return ang
End Function



Stevie G(Posted 2008) [#4]
I use this function to WRAP a value , should be faster than using MOD.

Function WRAP#( value#,lo#,hi#)

	If value < lo Then value = hi + ( value - lo )
	If value >= hi Then value = lo + ( value - hi )
	Return value
	
End Function


So ..
S\SA#=S\SA#-(S\SP#/S\SD#)
If S\SA#=360 Or S\SA#=-360 Then S\SA#=0


Would be ..
S\SA#= WRAP( S\SA#-(S\SP#/S\SD#) , 0 , 360 )