Homing missiles math

BlitzMax Forums/BlitzMax Beginners Area/Homing missiles math

EDIT
Solved it, I found an old B3d file :P

The solution:

Method Homing()
				
	While Dir > 360 Dir:-360 Wend
	While Dir <= 0 Dir:+360 Wend		
						
	Local TE# = RotaryDir( Dir# , iDir)
			
	If TE# < 0 Then Dir:- Turnrate*Delta.Time
	If TE# > 0 Then Dir:+ Turnrate*Delta.Time

EndMethod


This is the function I found that solved the problem. it returns the closest angle to turn to get to target, negative or Positive. Probably taken from the code archives a very long time ago.
Function RotaryDir#(SourceDir#,DestDir#)
Local Diff1#,Diff2#,Dir#
	If SourceDir#>DestDir#
		Diff1#=SourceDir-DestDir
		diff2#=(360.0-SourceDir)+DestDir
		If diff2<diff1
			dir#=diff2
		Else
			dir#=diff1/-1
		EndIf
	Else
		If SourceDir#<DestDir#
			diff1=DestDir-SourceDir
			diff2=(360.0-DestDir)+SourceDir
			If diff2<diff1
				dir#=diff2/-1
			Else
				dir#=diff1
			EndIf
		Else
			dir=0
		EndIf
	EndIf
	Return dir
End Function


<shameless plug>and if you want to do it in 3d :D wander over to my site and check out my quat pointing tutorial</shameless plug>

http://www.blitzbasic.com/Community/posts.php?topic=55665&hl=guided

The example linked by hub is a bit limited in that it doesn't actually include any turn rate limiting, i.e the missile will always point immediately at the target.

I've hacked the two together for a slightly nicer example.

Play with missilespeed and turnrate for some fun. The higher the turnrate the smarter the missile

Grab this image:


Global missile_x#=100.0,missile_y#=100.0, targetx#=100.0, targety#=100.0
Global anglem#=0, anglet#, dist#
Global missilespeed#=4.0, turnrate#=4.0, missile_img

Graphics 640,480

SetMaskColor 255,0,255
AutoMidHandle True

missile_img=LoadImage("Missile.png",MASKEDIMAGE)



While Not KeyHit(KEY_ESC)
  Cls
  SetRotation anglem#
  DrawImage missile_img, missile_x,missile_y 
  SetRotation 0
  movemissile()  
  Flip
Wend

Function movemissile()	
	Local dx, dy

    targetx# = Float(MouseX())
    targety# = Float(MouseY())
	dx=targetx-missile_x
	dy=targety-missile_y
	
	anglet# = ATan2(dy,dx) ' dir between player and target
	dist=Sqr((dx*dx)+(dy*dy))
	Homing()
	
	xs# = Cos(anglem) * missilespeed
	ys# = Sin(anglem) * missilespeed

	missile_x# = missile_x + xs
	missile_y# = missile_y + ys 
	
	If dist < 10.0 
	   missile_x=targetx
	   missile_y=targety
	
	 	DrawText "GOTCHA!",missile_x, missile_y+30
	EndIf 
	
End Function 

Function Homing()
				
	While anglem > 360 anglem:-360 Wend
	While anglem <= 0 anglem:+360 Wend		
						
	Local TE# = RotaryDir( anglem# , anglet)
			
	If TE# < 0 Then anglem:- Turnrate
	If TE# > 0 Then anglem:+ Turnrate
	
EndFunction

Function RotaryDir#(SourceDir#,DestDir#)

	Local Diff1#,Diff2#,Dir#

	If SourceDir# > DestDir#
		Diff1#=SourceDir-DestDir
		diff2#=(360.0-SourceDir)+DestDir
		If diff2<diff1
			dir#=diff2
		Else
			dir#=diff1/-1
		EndIf
	Else
		If SourceDir#<DestDir#
			diff1=DestDir-SourceDir
			diff2=(360.0-DestDir)+SourceDir
			If diff2<diff1
				dir#=diff2/-1
			Else
				dir#=diff1
			EndIf
		Else
			dir=0
		EndIf
	EndIf
	Return dir
End Function



my homing missile code.
and hub, you code is useless for a missile, don't have head and tail.

Strict

Graphics 640,480

SetMaskColor 255,0,255
AutoMidHandle True

Global Image:TImage=LoadImage("Missile.png",MASKEDIMAGE)

Global Angle:Int
Global Acel:Int=3
Global TurnSpeed:Int=5   '0 fast , 5 slow
Global X:Int
Global Y:Int
Global TargetX:Int
Global TargetY:Int

While Not KeyHit(KEY_ESCAPE)
	TargetX=MouseX()
	TargetY=MouseY()
	movemissile()
	Cls
	SetRotation Angle
	DrawImage Image, X,Y
	SetRotation 0
	Flip
Wend

Function movemissile()	
	If Sqr((X-TargetX)^2+(Y-TargetY)^2)>20 Then
		Local GotoAngle:Int = ATan2(Y-TargetY,X-TargetX)

		Local tmpAngle:Int=GotoAngle-Sgn(GotoAngle-Angle)*360
		If Abs(GotoAngle-Angle)>Abs(tmpAngle-Angle) Then GotoAngle=tmpAngle

		If Angle<>GotoAngle Then Angle:-Sgn (GotoAngle-Angle)*(180-Abs(GotoAngle-Angle))/(1+Acel*TurnSpeed)
		If Angle=>360 Then Angle:-360 Else If Angle<0 Then Angle:+360

		X:+Cos(Angle)*acel
		Y:+Sin(Angle)*acel
	EndIf
EndFunction


BlackSp1der's is a far more elegant solution :)