Skip to content

Instantly share code, notes, and snippets.

@amulware amulware/angle-basic-setup.cs Secret
Last active Aug 29, 2015

What would you like to do?
Example code snippets for GameDev<T> blog post on binary representations for angles and directions
public struct Angle
// contained value
private readonly float radians;
// private constructor to hide implementation
private Angle(float radians)
this.radians = radians;
// public static construction methods to enforce semantics
public static Angle FromRadians(float radians)
return new Angle(radians);
// radians property used to retrieve value if needed
public float Radians { get { return this.radians; } }
public struct Direction
// conversion constants
const float fromRadians = uint.MaxValue / ((float) Math.Pi * 2);
const float toRadians = ((float)Math.Pi * 2) / uint.MaxValue;
// the integer storing the actual binary representation
private readonly uint data;
// private constructor to hide implementation
private Direction(uint data)
{ = data;
// static constructions methods for strong semantics
public static Direction FromRadians(float radians)
return new Direction((uint)(radians * Direction.fromRadians));
// radians property used to retrieve value if needed
public float Radians { get { return * Direction.toRadians; } }
// substract two directions to get the angle between them
// due to integer overflow this will always return an angle in the interval [-180, 180] degrees
public static Angle operator -(Direction direction1, Direction direction2)
return Angle.FromRadians(( - * toRadians);
// adds an angle to the direction
// again, due to integer overflow no wrapping checks are needed
public static Direction operator +(Direction direction, Angle angle)
return new Direction((uint)( + angle.Radians * fromRadians));
// create direction from vector
public static Direction Of(Vector2 vector)
return Direction.FromRadians((float)Math.Atan2(vector.Y, vector.X));
// get unit vector in direction
public Vector2 Vector
var radians = this.Radians;
return new Vector2((float)Math.Cos(radians), (float)Math.Sin(radians));
// returns a new direction, based on the this one and rotated towards a goal direction
// never overshoots the goal and turns at most the given amount in radians
public Direction TurnedTowards(Direction goal, float maxStepInRadians)
// we don't turn for negative step sizes
if (maxStepInRadians <= 0)
return this;
// we create an Angle representation to use our own operator overloads
var step = Angle.FromRadians(maxStepInRadians);
// calculate the Angle towards the goal
var thisToGoal = goal - this;
// if the allowed step is larger than the actual angular distance, we arrive at the goal and return its value
if (maxStepInRadians > Math.Abs(thisToGoal.Radians))
return goal;
// we have not arrived at the goal yet
// make sure we are turning in the right direction by considering the sign of the angle towards the goal
// and return a new direction
return this + step * Math.Sign(thisToGoal.Radians);
pDir = direction of projectile's velocity
tDir = direction from projectile to target
pDirNew = turn pDir towards tDir,
without overshooting it,
with maximum step maxAngularVelocity * frameTimeStep
set direction of projectile's velocity
to point in direction pDirNew
var pDir = Direction.Of(projectile.Velocity);
var tDir = Direction.Of(target.Position - projectile.Position);
var pDirNew = pDir.TurnedTowards(tDir, maxAngularVelocity * frameTimeStep);
projectile.Velocity = pDirNew.Vector * projectile.Velocity.Length;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.