Math-Problem: Decide Rotation-Direction

BlitzMax Forums/BlitzMax Programming/Math-Problem: Decide Rotation-Direction

maverick69(Posted 2010) [#1]
Hi,

I have a small math problem.

I have an angle of an object. Then I'm calculating a new destination angle. Now I want to decide in which direction the object should start to rotate (I want the shortest way) and how much steps I require at a give deltaValue.

Here is a small code exmaple which illustrates my problem:

Graphics 640,480

Type TObject
	Field angle:Double = 0
	Field x:Int, y:Int
	
	Field destStep:Int = 0
	Field destDirection:Int = 0
End Type

Local o:TObject = New TObject
o.x = 300
o.y = 200
While (1)
	Cls
		SetColor (0,255,0)
		DrawLine o.x, o.y, MouseX(), MouseY()
		SetColor (255,0,0)
		DrawLine o.x, o.y, o.x + Sin(o.angle) * 50, o.y + Cos(o.angle + 180) * 50
		If MouseHit(1) And o.destStep = 0
			Local destAngle:Double = ATan2(MouseX() -o.x, o.y - MouseY())
			'
			' How can I decide the direction here???
			' The following routine doesn't work :(
			'
			If (destAngle - O.angle) > 0
				o.destDirection = 1
			Else 
				o.destDirection = -1
			End If
			o.destStep = Abs(destAngle - o.angle)
		End If
		
		If o.destStep > 0
			o.angle :+ o.destDirection
			o.destStep :- 1
		End If
	Flip
Wend

End



Czar Flavius(Posted 2010) [#2]
http://blitzbasic.com/Community/posts.php?topic=91937


maverick69(Posted 2010) [#3]
sorry - didnt' found the post above. thank you! here is the code how it works for me:

Graphics 640,480

Type TObject
	Field angle:Double = 0
	Field x:Int, y:Int
	
	Field destStep:Int = 0
	Field destDirection:Int = 0
End Type

Local o:TObject = New TObject
o.x = 300
o.y = 200
While (1)
	Cls
		SetColor (0,255,0)
		DrawLine o.x, o.y, MouseX(), MouseY()
		SetColor (255,0,0)
		DrawLine o.x, o.y, o.x + Sin(o.angle) * 50, o.y + Cos(o.angle + 180) * 50
		If MouseHit(1) And o.destStep = 0
			Local destAngle:Double = (ATan2(MouseX() -o.x, o.y - MouseY()) + 360) Mod 360
			Local angleDiff:Double = Abs((o.angle + 180 - destAngle) Mod 360 - 180)
			If angleDiff > 180 Then angleDiff = Abs(angleDiff - 360) 
			If ((o.angle + angleDiff) = destAngle) Then o.destDirection = 1 Else o.destDirection = -1
			o.destStep = Abs(angleDiff)
		End If
		
		If o.destStep > 0
			o.angle :+ o.destDirection
			o.destStep :- 1
		End If
	Flip
Wend



Jesse(Posted 2010) [#4]
There is a flaw in the code. After making it go 360 degrees counter clockwise if you try to reverse the direction it still keeps on going counter clockwise.

the link posted above works if you log into blitzbasic
but if you log in to blitzmax then you need to change blitzbasic to blitzmax:
http://blitzmax.com/Community/posts.php?topic=91937


_Skully(Posted 2010) [#5]
Here's an old function I created in Blitz3D that could be converted for this

Function rotarydir#(Asource#,Adest#,smooth#) ;Taken from the Code Archives on blitzbasic.com,
	If Asource#>Adest# ;Thanks Skully!
		Diff1#=Asource-Adest
		diff2#=(360.0-Asource)+Adest
		If diff2<diff1
			dir#=diff2/smooth
		Else
			dir#=diff1/smooth*-1
		EndIf
	Else
		If Asource#<Adest#
			diff1=Adest-Asource
			diff2=(360.0-Adest)+Asource
			If diff2<diff1
				dir#=diff2/smooth*-1
			Else
				dir#=diff1/smooth
			EndIf
		Else
			dir=0
		EndIf
	EndIf
	Return dir
End Function


of course it will need tweeking to ensure the input angles are >=0 and <360


slenkar(Posted 2010) [#6]
basically , as i said in the other thread, if the difference between your angle and the desired angle is more than 180
then rotate in the opposite direction.


Mark1nc(Posted 2010) [#7]
Here's a function I wrote a while back.

cx,cy - the center point of your object/ship

dx,dy - a point in the direction you are going (ie cx+velocityx, cy+velocityy)

tx,ty - a point you want to face towards.


Function TurnToFace:Int(cx#, cy#, dx#, dy#, tx#, ty#)

Local angle1#, angle2#, ret:Int

angle1 = ATan2(ty-cy, tx-cx)
angle2 = ATan2(dy-cy, dx-cx)

ret = angle1-angle2
If ret >= 180
ret = -(360 - ret)
Else
If ret <= -180
ret = ret + 360
EndIf
EndIf

If Abs(ret) < 1 Then ret = 0

Return ret

End Function

It returns the angle you should rotate your ship to face the target.


GW(Posted 2010) [#8]
Function Get_TurnDirection%(StartA%, EndA%) '// start angle and end angle: returns the shortest turn direction 0,1
	Local tmp0%
	Local tmp2%
	Local cond%

	tmp0:-starta
	tmp0:+EndA
	cond=(tmp0 < tmp2)
	tmp0:*tmp0
	tmp0=-tmp0
	tmp0:/180.0
	tmp2:-tmp0
	If (cond) tmp0 = tmp2
	tmp0:-starta
	tmp0:+EndA
	Return tmp0>0
End Function



GW(Posted 2010) [#9]
Here is another one.
Function Get_TurnDirection%(a%,b%)
	Return Abs(Min((b-a),180*Sgn(b-a)))<>180
End Function



Jesse(Posted 2010) [#10]
and a working example :
SuperStrict
Local Missiles% 	= 20
Local Missile:TMisile[Missiles] ' create missiles


Graphics 800,600,32,60
'create an image
DrawLine 0,0,15,5
DrawLine 0,10,15,5
DrawLine 0,0,0,10
Global image:TImage = CreateImage(15,11)
GrabImage image,0,0
SetImageHandle image,7,5

SeedRnd MilliSecs()
For Local i% = 0 To Missiles-1
	Missile[i] = TMisile.Create(Rand(700)+50,Rand(500)+50,Rand(360))
Next

Repeat
	Cls
	SetColor 20,200,40
	SetRotation 0
	DrawText "Press (esc) to exit",300,30
	
	For Local i% = 0 To Missiles-1
		Missile[i].update(MouseX(),MouseY())
		missile[i].draw()
	Next
	Flip
Until KeyHit(key_escape)

Type TMisile 	
	Field x#,y#
	Field Direction#

	Function Create:TMisile(x#,y#,dir#)
		Local s:TMisile = New TMisile
		s.x = x
		s.y = y
		s.Direction = Dir 
		Return s
	End Function
	
	Method draw() ' used to draw missile
		SetRotation direction
		DrawImage image,x,y
	End Method
	
	Method Update%(targetX%,targetY%,speed:Float=1.0,turnSpeed:Float = 1.0)
		Local dx:Float = Cos(direction)
		Local dy:Float = Sin(direction)
		x:+dx* speed
		y:+dy* speed
		Local TargetAngle# = (ATan2(targetY-y,targetX-x)+360)Mod 360.0
		Local difference# = Abs(TargetAngle-Direction)
		
		'turn toward target
		If TargetAngle < Direction				
			If difference > 180.0 Then direction :+ turnSpeed Else direction :- turnSpeed
		ElseIf TargetAngle > Direction
			If difference > 180.0 direction :- turnSpeed Else direction :+ turnSpeed
		EndIf
		Direction = (direction + 360) Mod 360
		
	EndMethod
End Type