Today I added homing missiles to my Space Invaders game. This is how I upgraded my code from basic bullets to homing missiles
Lets assume I had the below class for Bullets.
Class bullet
  Field x:float,y:float
  Field a:float
  Field speed:float
  Method update:void()
    x=x+Sin(a)*speed
    y=y+Cos(a)*speed
  end
  Method draw:void()
    DrawOval x-10,y-10,20,20
  end
End
Each bullet has it x and y co-ordinate for the screen, angle it travels at and speed. On each game loop, it will update its position
But thats a simple bullet. How do we turn this into a homing missile?
Well the first step is to add a target
Class bullet
  Field x:float,y:float
  Field a:float
  Field speed:float
  Field tx:float,ty:float
Next we need to find the angle between the current position and the target. 
  Method update:void()
    Local ta:float = ATan2(x-tx,y-ty)
    x=x+Sin(a)*speed
    y=y+Cos(a)*speed
  end
ATan2 will gives the angle into one of the 4 quadrants and return a result between -180 and 180 degrees. We'll now shift that between 0-360 degrees
  Method update:void()
    Local ta:float = ATan2(x-tx,y-ty)
    if ta<0 then ta=ta+360
    x=x+Sin(a)*speed
    y=y+Cos(a)*speed
  end
So now we know the angle of the target from this 'bullet', we also know the angle we are travelling at. If we compare the 2 we can adjust our travelling angle
  Method update:void()
    Local ta:float = ATan2(x-tx,y-ty)
    if ta<0 then ta=ta+360
    if a<ta then a=a+5
    if a>ta then a=a-5
    x=x+Sin(a)*speed
    y=y+Cos(a)*speed
  end
If we ran this we would get homing missiles taking the long way round when turning as the code doesn't recognise the shortest route is sometimes above 360 to get to angles in the lower range and also sometimes below 0 to get tot he top range
Its all about the shortest route......
We can do an extra test and see that if the shortest way is going below 0 back to 360 or the normal way and increasing.
  Method update:void()
    Local ta:float = ATan2(x-tx,y-ty)
    if ta<0 then ta=ta+360
    if a<ta
      ' test for shortest route
      if (a+360-ta) < (ta-a)
        a=a-5
        ' keep angle between 0 and 360
        if a<360 then a=a+360
      else
        a=a+5
      end
    end
    if a>ta then a=a-5
    x=x+Sin(a)*speed
    y=y+Cos(a)*speed
  end
and now lets do the same for above 360...
  Method update:void()
    Local ta:float = ATan2(x-tx,y-ty)
    if ta<0 then ta=ta+360
    if a<ta
      ' test for shortest route
      if (a+360-ta) < (ta-a)
        a=a-5
        ' keep angle between 0 and 360
        if a<0 then a=a+360
      else
        a=a+5
        ' keep angle between 0 and 360
        if a>360 then a=a-360
      end
    end
    if a>ta
      ' test for shortest route
      if (a+360-ta) < (a-ta)
        a=a+5
        ' keep angle between 0 and 360
        if a>360 then a=a-360
      else
        a=a-5
        ' keep angle between 0 and 360
        if a<0 then a=a+360
      end
    end
    x=x+Sin(a)*speed
    y=y+Cos(a)*speed
  end
and there we have it.. obviously we are still drawing a round bullet. Lets make it an angled rectangle
  Method draw:void()
    PushMatrix()
    Translate x,y
    Rotate a
    DrawRect x-5,y-20,10,40
    PopMatrix()
  end
Comments
Post a Comment