Skip to content

Instantly share code, notes, and snippets.

@brainwipe
Created January 2, 2021 11:17
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save brainwipe/3f7379ff998bec89f8e08fed92041e65 to your computer and use it in GitHub Desktop.
Save brainwipe/3f7379ff998bec89f8e08fed92041e65 to your computer and use it in GitHub Desktop.
Struct for Managing Coordinates
/* By Rob Lang
MIT License
https://www.youtube.com/roblang
@brainwipe */
/*
Example Use:
Dictionary<Coordinate, GameObject> grid = new Dictionary<Coordinate, GameObject>();
grid[(0,1)] = new GameObject();
grid[new Coordinate(1,1)] = new GameObject();
*/
using System;
using System.Diagnostics;
using UnityEngine;
namespace Lang
{
[DebuggerDisplay("{x},{z}")]
public struct Coordinate : IEquatable<Coordinate>
{
public static Coordinate Default => (0,0);
public static Coordinate North => (0,1);
public static Coordinate East => (1,0);
public static Coordinate South => (0,-1);
public static Coordinate West => (-1,0);
public int x;
public int z;
public Coordinate(int x, int z)
{
this.x = x;
this.z = z;
}
public static Coordinate From(float x, float z) =>
new Coordinate(
Mathf.FloorToInt(x / Tile.Size),
Mathf.FloorToInt(z / Tile.Size)
);
public static Coordinate Rand(int range) =>
new Coordinate(
UnityEngine.Random.Range(-range, range),
UnityEngine.Random.Range(-range, range)
);
public Coordinate[] Neighbours => new Coordinate[]
{
this + North,
this + East,
this + South,
this + West,
};
public bool InBounds(Coordinate origin, int bounds) =>
x < origin.x + bounds &&
x > origin.x - bounds &&
z < origin.z + bounds &&
z > origin.z - bounds;
internal Coordinate[] Spiral(Coordinate bounds)
{
var current = this + North;
var squares = (bounds.x + bounds.z + 1) * (bounds.x + bounds.z + 1);
var result = new Coordinate[squares];
result[0] = this;
result[1] = current;
var workingXBound = 1;
var workingZBound = 1;
int x = current.x;
int z = current.z;
for (int i = 2; i < result.Length; i++)
{
if (z == workingZBound && x < workingXBound)
{
x++;
}
else if (x == workingXBound && z > -workingZBound)
{
z--;
}
else if (z == -workingZBound && x > -workingXBound)
{
x--;
}
else if (x == -workingXBound && z < workingZBound)
{
z++;
}
result[i] = new Coordinate(x,z);
if (x == -workingXBound && z == workingZBound && i < result.Length-1)
{
workingXBound++;
workingZBound++;
i++;
z++;
result[i] = new Coordinate(x,z);
}
}
return result;
}
public static implicit operator Coordinate((int x, int z) value) => new Coordinate(value.x, value.z);
public static Coordinate operator +(Coordinate a, Coordinate b) => new Coordinate(a.x + b.x, a.z + b.z);
public static Coordinate operator -(Coordinate a, Coordinate b) => new Coordinate(a.x - b.x, a.z - b.z);
public static Coordinate operator *(Coordinate a, int b) => new Coordinate(a.x * b, a.z * b);
public static bool operator ==(Coordinate a, Coordinate b) => a.x == b.x && a.z == b.z;
public static bool operator !=(Coordinate a, Coordinate b) => a.x != b.x || a.z != b.z;
public static bool operator >(Coordinate a, Coordinate b) => a.x > b.x && a.z > b.z;
public static bool operator <(Coordinate a, Coordinate b) => a.x < b.x && a.z < b.z;
public Coordinate Invert => new Coordinate(-x, -z);
public override bool Equals(object obj) => obj is Coordinate location && Equals(location);
public bool Equals(Coordinate location) => location.x == x && location.z == z;
public override int GetHashCode()
{
unchecked
{
int hash = 17;
hash = hash * 23 + x.GetHashCode();
hash = hash * 23 + z.GetHashCode();
return hash;
}
}
public override string ToString() => $"({x},{z})";
public void Deconstruct(out int x, out int z)
{
x = this.x;
z = this.z;
}
public Vector3 ToVector3() => new Vector3(x * Tile.Size, 0, z * Tile.Size);
public Coordinate[] Area(Coordinate size)
{
var result = new Coordinate[size.x * size.z];
int resultIndex = 0;
for(int ix = x; ix < x + size.x; ix++)
{
for (int iz = z; iz < z + size.z; iz++)
{
result[resultIndex] = (ix,iz);
resultIndex++;
}
}
return result;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment