Math-Problem: Decide Rotation-Direction
BlitzMax Forums/BlitzMax Programming/Math-Problem: Decide Rotation-Direction
| ||
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 |
| ||
http://blitzbasic.com/Community/posts.php?topic=91937 |
| ||
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 |
| ||
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 |
| ||
Here's an old function I created in Blitz3D that could be converted for thisFunction 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 |
| ||
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. |
| ||
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. |
| ||
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 |
| ||
Here is another one.Function Get_TurnDirection%(a%,b%) Return Abs(Min((b-a),180*Sgn(b-a)))<>180 End Function |
| ||
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 |