Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: homing missile  (Read 3335 times)

0 Members and 1 Guest are viewing this topic.

Voroz

  • Full Member
  • ***
  • Posts: 128
    • View Profile
homing missile
« on: August 08, 2011, 10:01:35 pm »
Hi. I'm attempting to make a homing missile, and i managed to get it work quite well except for one thing. So far i have only done the rotation of the missile but the problem is that since i am using atan2 to check for the angle of the missile to the target, when the transition comes from 3.14 to -3.14 the missile will start rotating the other way.

Code: [Select]
missile.targetVectorX = mouseX - Missile.GetPosition().x;
missile.targetVectorY = mouseY - Missile.GetPosition().y;

missile.worldAngle = Missile.GetRotation() * PI / 180;
missile.atanAngle = atan2(cos(missile.worldAngle), sin(missile.worldAngle));
missile.distanceToTarget = sqrt(missile.targetVectorX * missile.targetVectorX + missile.targetVectorY * missile.targetVectorY);
missile.toTargetAngle = atan2(missile.targetVectorY, missile.targetVectorX);
if (missile.atanAngle < missile.toTargetAngle)
    missile.rotation  -= 1;
else
missile.rotation += 1;

Missile.SetRotation(missile.rotation);


Any ideas? maybe a possibility to get a radian 6.28 no minus instead of atan2 on the toTargetAngle?

Thx.

Disch

  • Full Member
  • ***
  • Posts: 220
    • View Profile
homing missile
« Reply #1 on: August 09, 2011, 12:21:00 am »
Assuming you have a missile X/Y velocity, you could greatly simplify this by employing linear algebra.  You could eliminate the atan2 calls altogether and substitute it with perpendicular dot product.

Code: [Select]

template <typename T>
inline T PerpDot(const sf::Vector<T>& A,const sf::Vector<T>& B)
{
  return (A.x * B.y) - (A.y * B.x);
}


Given 2 vectors A and B, PerpDot(A,B) gives you sin( theta ) * length(A) * length(B).  (Where 'theta' is the angle between the vectors)

For example, if A and B are parallel, PerpDot(A,B) would be zero.  You can use this to determine which "side" of a vector another point is on.


You have 3 key points:
i) the missile's current position
ii) Any point along the missile's current trajectory (missile's current position + missile velocity)
iii) The target point

Vector A would be ii - i.
Vector B would be iii - i.

Run a PerpDot on those vectors.  If the result is negative, rotate one way.  Or if it's positive, rotate the other way.

If the result is zero, then the target point is either directly in front of (or directly behind) the missile.  In which case you can do a Dot product to figure out which:

Code: [Select]

template <typename T>
inline T Dot(const sf::Vector<T>& A,const sf::Vector<T>& B)
{
  return (A.x * B.x) + (A.y * B.y);
}


Dot(A,B) gives you  cos(theta) * length(A) * length(B).

The result here is that Dot(A,B) will be positive if the missile is heading towards the target, and negative if the missile is heading away from it.

Voroz

  • Full Member
  • ***
  • Posts: 128
    • View Profile
homing missile
« Reply #2 on: August 09, 2011, 12:29:12 pm »
Thanks for your reply. I could not get it to work though since i didn't fully understand it. However i managed to get it to work with my atan angles by  using a different formula to check for angles depending on if the missile rotation is above or below 0.

Code: [Select]
Missile.SetPosition(Missile.GetPosition().x + sin(missile.worldAngle)*2, Missile.GetPosition().y + cos(missile.worldAngle)*2);

if (missile.atanAngle < 0){
    if (missile.toTargetAngle - missile.atanAngle > 0 && missile.toTargetAngle - missile.atanAngle < PI)
        missile.rotation  -= 2;
        else
            missile.rotation += 2;
}
if (missile.atanAngle >= 0){
    if (missile.toTargetAngle - missile.atanAngle < 0 && missile.toTargetAngle - missile.atanAngle > -PI)
        missile.rotation  += 2;
        else
            missile.rotation  -= 2;
}


This checks for the certain distances between the angles, different ones above 0 and below 0, and decides which direction to go based on that. The key here is that i have to check below 0 and above 0 which formula to use.

And it works perfectly no matter where i put my mouse it will choose the shortest turning path.

However i barely understand myself what i did, maybe someone could explain it better :D.

Edit: Ok well i do kinda understand what i'm doing but it's hard to explain. I change direction depending on if the angle is over or under 180 degrees, and i need a different formula depending on if i am below or above 0, and there's a bit more to it by that. But i was mostly testing alot and getting lucky.

Disch

  • Full Member
  • ***
  • Posts: 220
    • View Profile
homing missile
« Reply #3 on: August 09, 2011, 05:04:31 pm »
Here's an example to show how my approach works.  It really is much simpler (and faster since you don't really need any trig function calls), so I recommend you try it out:



Note I might have the sign backwards on the PerpDot (maybe counter-clockwise is Positive, not Negative), but that'll be easy to figure out if you try it.  If the missile moves away from the target, just flip the sign and it should work.