# Need some help with homing missiles.

I just discovered how great Polar Coords and I am trying to get homing missies to work. For some reason my missile will occasionally spaz out and continue in the opposite direction. Any ideas why? I’m still trying to get a better understanding of using angles.

``````function setup()
parameter.watch("Distance")
targets = {}
target = nil
x = WIDTH/2
y = 0
length = 5
angle = math.deg(math.atan(y/x))
inc = 4
tAngle = 0
for i=1,5 do
table.insert(targets,{x=math.random(1,WIDTH),y=math.random(1,HEIGHT),select = false,alive = true})
end

missleSelect()
end

function draw()
background(255,255,255,255)
for i=1,#targets do
drawtarget(targets[i])
end
drawMissle()
home()
end

function drawtarget(v)
if v.alive then
pushMatrix()
pushStyle()
translate(v.x,v.y)
if v.select then c = color(60, 254, 1, 255)else c= color(255,0,0,255)  end
fill(c)
ellipse(0,0,25)
fill(214, 213, 213, 255)
ellipse(0,0,15)
fill(c)
ellipse(0,0,10)
popStyle()
popMatrix()
end
end

function drawMissle()
x = x + length * math.cos(math.rad(angle))
y = y + length * math.sin(math.rad(angle))
pushMatrix()
pushStyle()
translate(x,y)
fill(255, 233, 0, 255)
ellipse(0,0,15)
popStyle()
popMatrix()
end

function missleSelect()
if #targets ~= 0 then
local rnd = math.random(1,#targets)
targets[rnd].select = true
target = rnd
tAngle = math.deg(math.atan2(targets[rnd].y - y,targets[rnd].x - x))
end

end

function home()

if #targets ~= 0 then
tAngle = math.deg(math.atan2(targets[target].y-y,targets[target].x - x))
Distance = (targets[target].y-y) +(targets[target].x - x)

--if angle - tAngle < -180 then angle = angle + 180 end
if angle < tAngle then
angle = angle + inc
else
angle = angle - inc
end

if x< targets[target].x +15 and x > targets[target].x -15 and
y < targets[target].y +15 and y> targets[target].y - 15 then
-- print("hit")

table.remove(targets,target)
missleSelect()

end
end
end

``````

@Briarfox Put a watch in for tAngle. I noticed when you have the problem, tAngle goes positive and negative around 180 but doesn’t seem to get beyond -170 or 170. Hard to explain, but it might be easier to see it happening.

Nice little program!

As @dave1707 says, the problem is that tAngle can oscillate between just over -180 and just under 180 which makes a big difference to what happens next. One solution is to ensure that tAngle is always near to its previous value.

``````function setup()
parameter.watch("Distance")
parameter.watch("tAngle")
parameter.watch("angle")
targets = {}
target = nil
x = WIDTH/2
y = 0
length = 5
angle = math.deg(math.atan(y/x))
inc = 4
tAngle = 0
for i=1,5 do
table.insert(targets,{x=math.random(1,WIDTH),y=math.random(1,HEIGHT),select = false,alive = true})
end

missleSelect()
end

function draw()
background(255,255,255,255)
for i=1,#targets do
drawtarget(targets[i])
end
drawMissle()
home()
end

function drawtarget(v)
if v.alive then
pushMatrix()
pushStyle()
translate(v.x,v.y)
if v.select then c = color(60, 254, 1, 255)else c= color(255,0,0,255)  end
fill(c)
ellipse(0,0,25)
fill(214, 213, 213, 255)
ellipse(0,0,15)
fill(c)
ellipse(0,0,10)
popStyle()
popMatrix()
end
end

function drawMissle()
x = x + length * math.cos(math.rad(angle))
y = y + length * math.sin(math.rad(angle))
pushMatrix()
pushStyle()
translate(x,y)
fill(255, 233, 0, 255)
ellipse(0,0,15)
popStyle()
popMatrix()
end

function missleSelect()
if #targets ~= 0 then
local rnd = math.random(1,#targets)
targets[rnd].select = true
target = rnd
tAngle = math.deg(math.atan2(targets[rnd].y - y,targets[rnd].x - x))
end

end

function home()

if #targets ~= 0 then
local oa = tAngle
tAngle = math.deg(math.atan2(targets[target].y-y,targets[target].x - x))
if tAngle - oa < -180 then
tAngle = tAngle + 360
end
if tAngle - oa > 180 then
tAngle = tAngle - 360
end
Distance = (targets[target].y-y)^2 +(targets[target].x - x)^2

--if angle - tAngle < -180 then angle = angle + 180 end
if angle < tAngle then
angle = angle + inc
else
angle = angle - inc
end

if x< targets[target].x +15 and x > targets[target].x -15 and
y < targets[target].y +15 and y> targets[target].y - 15 then
-- print("hit")

table.remove(targets,target)
missleSelect()

end
end
end
``````

Thanks guys, I was so close. when checking if the angle was ±180 I was then ± 180 and not 360.

Here’s another homing missiles example with physics moving the targets.

``````function setup()
displayMode(FULLSCREEN)
parameter.watch("Distance")
parameter.watch("#targets")
targets = {}
bodies = {}
target = nil
x = WIDTH/2
y = 0
length = 5
angle = math.deg(math.atan(y/x))
inc = 15
tAngle = 0
for i=1,25 do
--table.insert(targets,{x=math.random(1,WIDTH),y=math.random(1,HEIGHT),select = false,alive = true})
--create the physics object

local p_img = physics.body(CIRCLE,25) --physics bodies use radius not diameter
p_img.x = math.random(2,WIDTH-2) -- choose a random position
p_img.y = math.random(2,HEIGHT-2) -- same for the y position
p_img.angle=math.random(0,360)
p_img.gravityScale = 0 -- no gravity
p_img.restitution = 1.0 -- this image is not so bouncy
p_img.friction = 0.0 -- the amount of friction to be applied to the image
p_img.linearVelocity = vec2(math.random(500),math.random(500))  -- velocity
p_img.select = false
p_img.alive = true
--p_img.info="mine" --so when collisions occur, we can figure out which object was involved
table.insert(targets,p_img)
end
CreateWalls()

missleSelect()
end

function draw()
background(0, 0, 0, 255)
for i=1,#targets do
drawtarget(targets[i])
end
drawMissle()
home()
--moveTargets()
end

function drawtarget(v)
if v.alive then
pushMatrix()
pushStyle()
translate(v.x,v.y)
if v.select then c = color(60, 254, 1, 255)else c= color(255,0,0,255)  end
fill(c)
ellipse(0,0,25)
fill(214, 213, 213, 255)
ellipse(0,0,15)
fill(c)
ellipse(0,0,10)
popStyle()
popMatrix()
end
end

function drawMissle()
x = x + length * math.cos(math.rad(angle))
y = y + length * math.sin(math.rad(angle))
pushMatrix()
pushStyle()
translate(x,y)
fill(255, 233, 0, 255)
ellipse(0,0,15)
popStyle()
popMatrix()
end

function missleSelect()
if #targets > 4 then
local rnd = math.random(1,#targets-4)
targets[rnd].select = true
target = rnd
tAngle = math.deg(math.atan2(targets[rnd].y - y,targets[rnd].x - x))
end

end

function home()

if #targets > 4 then
tAngle = math.deg(math.atan2(targets[target].y-y,targets[target].x - x))
Distance = (targets[target].y-y) +(targets[target].x - x)

--if angle - tAngle < -180 then angle = angle + 180 end
if angle - tAngle < -180 then angle = angle + 360 end
if angle - tAngle > 180 then angle = angle - 360 end
if angle < tAngle then
angle = angle + inc
else
angle = angle - inc
end

if x< targets[target].x +15 and x > targets[target].x -15 and
y < targets[target].y +15 and y> targets[target].y - 15 then
-- print("hit")
targets[target]:destroy()
table.remove(targets,target)
x = WIDTH/2
y = 0
--length = 5
angle = 0--math.deg(math.atan(y/x))
missleSelect()

end
end
end

function CreateWalls()
leftWall = CreateWall(1,1,1,HEIGHT-1,1.0)
rightWall = CreateWall(WIDTH-1,0,WIDTH-1,HEIGHT-1,1)
bottomWall = CreateWall(1,1,WIDTH-1,1,1)
topWall = CreateWall(1,HEIGHT-1,WIDTH-1,HEIGHT-1,1)
end
--this function creates one wall (actually just a line)
function CreateWall(x,y,x1,y1,r)
local w = physics.body(EDGE,vec2(x,y),vec2(x1,y1)) -- vec2
w.restitution=r --see comment above
table.insert(targets,w) --keep track of body so we can destroy it later if we want
return w
end

``````

Lol! When i watch this, I feel pityful for the green ball… Not a chance!