Sunday, June 30, 2013

Code Snippet : Angle Facings

So, simple enough concept:  "I have an entity facing a certain direction.  I want to turn him to face a target direction.  I want him to turn on the shortest angle possible".

Despite this being what I consider a simple and common problem, I struggled greatly to find somewhere that adequately described the solution.  So here's how I handled it!

Things to note:  
-Angles are in degrees (Most math libraries use radians, but I find degrees easier to assign initial values to, so we'll assume all Math functions we use take and return degrees)

-0 degrees is straight right, and the range of angles is 180 (counter clockwise) -> -180 (clockwise)

First of all, you'll need a helpful function called WrapAngle.  Monogame has this by default in the MathHelper class, but in essence it does the following:

public float WrapAngle(float angle)
   while (angle > 180)
      angle -= 360;
   while (angle < -180)
      angle += 360;
   return angle;

Alright, so whenever we modify an angle, we need to feed it through WrapAngle.

Next step, is to get our compared value.  facingAngle is your current facing, and targetAngle is . . . well, the angle you're turning towards.

float compareAngle = WrapAngle(targetAngle - facingAngle);

We now use this, along with the turningSpeed of the entity to update the facing position.  We do a quick check to make sure this direction is actually the shortest.

facingAngle = facingAngle + Math.Min(turningSpeed, Math.Max(-turningSpeed, compareAngle));

Aaaaand done!  Put this in your update loop, and your entity will always turn to a given angle, taking the shortest

No comments:

Post a Comment