Created
January 2, 2021 11:17
-
-
Save brainwipe/3f7379ff998bec89f8e08fed92041e65 to your computer and use it in GitHub Desktop.
Struct for Managing Coordinates
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* 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