1

I am implementing a rotating cannon on a tank. The cannon of the NPC is following the player tank (auto-rotating).

I am calculating:

  • The angle of the vector tank -> enemy (radians)
  • The angle of the cannon (radians)
  • The difference between both (I tried with Math.min and Math.abs after googling)

Tthe problem is that the jump from 0 degrees to 360 or from 360 to 0 makes the cannon "loose" the player-tank and the cannon rotates once all around.

Right now its done like this:

  Vector2 Tank2Enemy = tank.getPosition().sub(closestEnemyTank.getPosition());
  float angleTank2Enemy = Tank2Enemy.angleRad();   // this is the angle of the vector tank -> enemy in radians   
  float angleCannon = tank.cannon.getOwnAngle();   // this is the cannon-angle in radians   
  float diffAngle = Math.min(Math.abs(angleCannon - angleTank2Enemy), MathUtils.PI - Math.abs(angleCannon - angleTank2Enemy));

  if (diffAngle > 0.01f || diffAngle < -0.01f) {   // dead zone

     if (diffAngle > 0.01f) {

        direction = -1;   // this goes to cannon.getBody().setAngularVelocity(cannonAngularVelocity);
     }
     else if (diffAngle < 0.01f) {
        direction = 1;   // this goes to cannon.getBody().setAngularVelocity(cannonAngularVelocity);
     }
  }

  return direction;
flotothemoon
  • 1,882
  • 2
  • 20
  • 37
just4phil
  • 11
  • 4

2 Answers2

1

A good practice is to have an angle always positive for example in order not to mess with different sign in angles. You could notice that an angle 270 will work in the same way as -90 degrees. Your problem might be solved by attaching a simple check like this:

while(angle >= 2*Math.PI) //angle in radians
    angle -= 2*Math.PI;
while(angle < 0)
    angle += 2*Math.PI;

Update: I guess the problem lies in the way you calculate the diffAngle. Could you try the following?

float diffAngle = angleCannon - angleTank2Enemy; // or angleTank2Enemy - angleCannon, depending on the direction of angles in your game
double sign  = Math.signum(diffAngle);
float diffAngle = sign >= 0 ? Math.min(diffAngle, 2*MathUtils.PI - diffAngle) : Math.max(diffAngle, -(2*MathUtils.PI - diffAngle));
Savail
  • 867
  • 10
  • 27
  • thx! i have already done this. my code looks like this now simplified: diffAngle = (angleTank2Enemy - angleCannon); if (Math.abs(diffAngle) > 0.05f) { // dead zone if (diffAngle > 0.05f) direction = -1; else if (diffAngle < -0.05f) direction = 1; } return direction; all my angles range from 0 to 2*PI – just4phil Aug 25 '14 at 09:28
  • thx! i have already done this. all my angles range from 0 to 2*PI. my problem is: if i have diffAngle = (angleTank2Enemy - angleCannon); then i get the "jumps" from 0 to 2*PI => suddenly diff = -6 ... or suddenly diff = +6... and that causes object to rotate one time around.... hope you understand what i mean.... – just4phil Aug 25 '14 at 09:34
  • hmm if your angle ranges from 0 to 2*PI shouldn't you have: 2*MathUtils.PI in your diffAngle? float diffAngle = Math.min(Math.abs(angleCannon - angleTank2Enemy), 2*MathUtils.PI - Math.abs(angleCannon - angleTank2Enemy)); – Savail Aug 25 '14 at 10:31
  • i tried that too but it doesnt solve my issue :( ... i found this but maybe i am not applying it correctly: http://stackoverflow.com/questions/2320986/easy-way-to-keeping-angles-between-179-and-180-degrees – just4phil Aug 25 '14 at 11:37
0

ok i solved it like this:

    if (angleTank2Enemy > angleCannon) {

        diffAngle = angleTank2Enemy - angleCannon;
        if (diffAngle > MathUtils.PI) {
            rotDirRight = true;
        }
        else rotDirRight = false;
    }
    else {
        diffAngle = angleCannon - angleTank2Enemy;
        if (diffAngle > MathUtils.PI) {
            rotDirRight = false;
        }
        else rotDirRight = true;
    }

    if ((diffAngle) > 0.05f) {  // dead zone

        if (rotDirRight)    direction = 1;  // this goes to cannon.getBody().setAngularVelocity(cannonAngularVelocity);
        else                direction = -1; // this goes to cannon.getBody().setAngularVelocity(cannonAngularVelocity);
    }

    return direction;
just4phil
  • 11
  • 4