I think I worked something out. Essentially wrote a curve value routine to interpolate the angle towards the destination. It was a little tricky getting it to rotate either left or right (depending on which rotation was shorter), but a dot product solved that. Only issue I have now is there can be instances where the missile simply cannot hit the target because it can't turn fast enough and ends up just orbiting the target. I don't think this'll be an issue in the long run, we shall see.
// target
tx = getRawMouseX()
ty = getRawMouseY()
// missile position
mx = getSpriteXByOffset(missile)
my = getSpriteYByOffset(missile)
// target angle
ta# = wrapAngle(atanfull(tx - mx, ty - my)-90)
// Kill missile if within range of target (10px)
if (mx-tx)^2 + (my-ty)^2 <= 100
turrents[i].fire = 0
playSound(boom)
setSpriteVisible(missile, 0)
endif
// Unit direction vector from missile to target
max# = cos(ta#)
may# = sin(ta#)
// Unit vector of missile's current direction
// Technically this points perpendicular to the gun
ma# = getSpriteAngle(missile)
mbx# = cos(ma#+90)
mby# = sin(ma#+90)
// dot product between current direction and target direction
dp# = max#*mbx# + may#*mby#
// If dot product is greater than 0, rotate clockwise
// If less than 0 rotate counter-clockwise
// This method works independently of the gun's rotation and avoids the problem
// of angles wrapping to 360
if abs(ta#-ma#) > 2
if dp# > 0
ma# = ma# + 2
else
ma# = ma# - 2
endif
endif
// Update angle
ma# = wrapAngle(ma#)
setSpriteAngle(missile, ma#)
// Update position
fx# = cos(ma#)*5
fy# = sin(ma#)*5
x# = getSpriteXByOffset(missile) + fx#
y# = getSpriteYByOffset(missile) + fy#
setSpritePositionByOffset(missile, x#, y#)