Day 4 - how to beat the invaders with homing missiles


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