Skip to content

Instantly share code, notes, and snippets.

@Kittoes0124
Last active June 9, 2020 13:17
Show Gist options
  • Save Kittoes0124/11f5d68f016f42d3a9201998e4826e00 to your computer and use it in GitHub Desktop.
Save Kittoes0124/11f5d68f016f42d3a9201998e4826e00 to your computer and use it in GitHub Desktop.
/// <summary>
///
/// </summary>
/// <remarks>
/// https://www.redblobgames.com/grids/hexagons
/// </remarks>
public readonly struct HexCoordinate
{
private const double SquareRootOfThree = 1.7320508075688772d;
private const double SquareRootOfThreeHalved = (SquareRootOfThree * 0.5d);
/// <remarks>
/// Oblong: (hex) => (hex.Y == 0)
/// Square: (hex) => (hex.X == 0)
/// </remarks>
public static IEnumerable<HexCoordinate> GenerateTileset(int offset, int count, Func<HexCoordinate, bool> predicate) {
var limit = (offset + count);
for (var hashCode = offset; (hashCode < limit); ++hashCode) {
var hexCoordinate = HexCoordinate.New(hashCode);
if (predicate(hexCoordinate)) {
yield return hexCoordinate;
}
}
}
public static HexCoordinate New(int hashCode) {
var (x, y) = BitwiseHelpers.ElegantUnpair(hashCode);
return HexCoordinate.New(x, y);
}
public static HexCoordinate New(short x, short y) => new HexCoordinate(x, y);
public static bool operator ==(HexCoordinate left, HexCoordinate right) => ((left.X == right.X) && (left.Y == right.Y));
public static bool operator !=(HexCoordinate left, HexCoordinate right) => ((left.X != right.X) && (left.Y != right.Y));
public static HexCoordinate operator +(HexCoordinate left, HexCoordinate right) => New(((short)(left.X + right.X)), ((short)(left.Y + right.Y)));
public static HexCoordinate operator -(HexCoordinate left, HexCoordinate right) => New(((short)(left.X - right.X)), ((short)(left.Y - right.Y)));
public static HexCoordinate operator *(HexCoordinate left, HexCoordinate right) => New(((short)(left.X * right.X)), ((short)(left.Y * right.Y)));
public short X { get; }
public short Y { get; }
public short Z => ((short)((-X) - Y));
private HexCoordinate(short x, short y) {
X = x;
Y = y;
}
private int GetLength() => ((Math.Abs(X) + Math.Abs(Y) + Math.Abs(Z)) >> 1);
public bool Equals(HexCoordinate other) => (this == other);
public override bool Equals(object other) => ((other is null) || ((other is HexCoordinate hexCoordinate) && Equals(hexCoordinate)));
public HexCoordinate GetDiagonalNeighborNorth() => New(((short)(X + 1)), ((short)(Y + 1)));
public HexCoordinate GetDiagonalNeighborNorthEast() => New(((short)(X + 2)), ((short)(Y - 1)));
public HexCoordinate GetDiagonalNeighborNorthWest() => New(((short)(X - 1)), ((short)(Y + 2)));
public HexCoordinate GetDiagonalNeighborSouthEast() => New(((short)(X + 1)), ((short)(Y - 2)));
public HexCoordinate GetDiagonalNeighborSouthWest() => New(((short)(X - 2)), ((short)(Y + 1)));
public HexCoordinate GetDiagonalNeighborSouth() => New(((short)(X - 1)), ((short)(Y - 1)));
public int GetDistance(HexCoordinate other) => (this - other).GetLength();
public override int GetHashCode() => BitwiseHelpers.ElegantPair(X, Y);
public HexCoordinate GetImmediateNeighborEast() => New(((short)(X + 1)), ((short)(Y - 1)));
public HexCoordinate GetImmediateNeighborNorthEast() => New(((short)(X + 1)), Y);
public HexCoordinate GetImmediateNeighborNorthWest() => New(X, ((short)(Y + 1)));
public HexCoordinate GetImmediateNeighborSouthEast() => New(X, ((short)(Y - 1)));
public HexCoordinate GetImmediateNeighborSouthWest() => New(((short)(X - 1)), Y);
public HexCoordinate GetImmediateNeighborWest() => New(((short)(X - 1)), ((short)(Y + 1)));
public (double x, double y) GetPixel(double size) {
var x = X;
var y = Z;
return (
x: (size * (1.5d * x)),
y: (size * ((SquareRootOfThreeHalved * x) + (SquareRootOfThree * y)))
);
}
public HexCoordinate RotateLeft() => New(((short)(-Y)), ((short)(-Z)));
public HexCoordinate RotateRight() => New(((short)(-Z)), ((short)(-X)));
public override string ToString() => $"({X},{Y},{Z})";
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment