2d game : fire at a moving target by predicting intersection of projectile and unit

后端 未结 11 763
庸人自扰
庸人自扰 2020-11-28 22:26

Okay, this all takes place in a nice and simple 2D world... :)

Suppose I have a static object A at position Apos, and a linearly moving object B at Bpos with bVeloci

11条回答
  •  粉色の甜心
    2020-11-28 22:50

    Following is polar coordinate based aiming code in C++.

    To use with rectangular coordinates you would need to first convert the targets relative coordinate to angle/distance, and the targets x/y velocity to angle/speed.

    The "speed" input is the speed of the projectile. The units of the speed and targetSpeed are irrelevent, as only the ratio of the speeds are used in the calculation. The output is the angle the projectile should be fired at and the distance to the collision point.

    The algorithm is from source code available at http://www.turtlewar.org/ .

    
    // C++
    static const double pi = 3.14159265358979323846;
    inline double Sin(double a) { return sin(a*(pi/180)); }
    inline double Asin(double y) { return asin(y)*(180/pi); }
    
    bool/*ok*/ Rendezvous(double speed,double targetAngle,double targetRange,
       double targetDirection,double targetSpeed,double* courseAngle,
       double* courseRange)
    {
       // Use trig to calculate coordinate of future collision with target.
       //             c
       //
       //       B        A
       //
       // a        C        b
       //
       // Known:
       //    C = distance to target
       //    b = direction of target travel, relative to it's coordinate
       //    A/B = ratio of speed and target speed
       //
       // Use rule of sines to find unknowns.
       //  sin(a)/A = sin(b)/B = sin(c)/C
       //
       //  a = asin((A/B)*sin(b))
       //  c = 180-a-b
       //  B = C*(sin(b)/sin(c))
    
       bool ok = 0;
       double b = 180-(targetDirection-targetAngle);
       double A_div_B = targetSpeed/speed;
       double C = targetRange;
       double sin_b = Sin(b);
       double sin_a = A_div_B*sin_b;
       // If sin of a is greater than one it means a triangle cannot be
       // constructed with the given angles that have sides with the given
       // ratio.
       if(fabs(sin_a) <= 1)
       {
          double a = Asin(sin_a);
          double c = 180-a-b;
          double sin_c = Sin(c);
          double B;
          if(fabs(sin_c) > .0001)
          {
             B = C*(sin_b/sin_c);
          }
          else
          {
             // Sin of small angles approach zero causing overflow in
             // calculation. For nearly flat triangles just treat as
             // flat.
             B = C/(A_div_B+1);
          }
          // double A = C*(sin_a/sin_c);
          ok = 1;
          *courseAngle = targetAngle+a;
          *courseRange = B;
       }
       return ok;
    }
    
    

提交回复
热议问题