Skip to content

Commit b5b7229

Browse files
committed
Basic hex code
1 parent 00d7f57 commit b5b7229

15 files changed

+442
-0
lines changed

Runtime.meta

+3
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Runtime/HexCoords.cs

+102
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using UnityEngine;
4+
5+
namespace HexEngine {
6+
/// <summary>
7+
/// Representation of hex position or offset.
8+
/// Stores a position as axial coordinates (X, Y), additionally exposing Z value.
9+
/// </summary>
10+
// For reference look at https://www.redblobgames.com/grids/hexagons/#coordinates
11+
[Serializable]
12+
public struct HexCoords : IEquatable<HexCoords> {
13+
public static readonly HexCoords Zero = new HexCoords();
14+
15+
[SerializeField]
16+
private int _x;
17+
[SerializeField]
18+
private int _y;
19+
20+
public int X {
21+
get => _x;
22+
set => _x = value;
23+
}
24+
25+
public int Y {
26+
get => _y;
27+
set => _y = value;
28+
}
29+
30+
public int Z => -X - Y;
31+
32+
public HexCoords(int x, int y) {
33+
_x = x;
34+
_y = y;
35+
}
36+
37+
public static HexCoords operator +(HexCoords a, HexCoords b)
38+
=> new HexCoords(a.X + b.X, a.Y + b.Y);
39+
40+
public static HexCoords operator +(HexCoords a, HexDirection b)
41+
=> a + b.Coords();
42+
43+
public static HexCoords operator -(HexCoords a, HexCoords b)
44+
=> new HexCoords(a.X - b.X, a.Y - b.Y);
45+
46+
public static HexCoords operator -(HexCoords a, HexDirection b)
47+
=> a - b.Coords();
48+
49+
public IEnumerable<HexCoords> Neighbours() {
50+
for (int i = 0; i < 6; i++) {
51+
yield return this + ((HexDirection) i).Coords();
52+
}
53+
}
54+
55+
/// <summary>
56+
/// The offset from the Vector3.zero to the center of the hex.
57+
/// </summary>
58+
public Vector3 Offset() {
59+
return HexDirection.NE.Direction() * X + HexDirection.N.Direction() * Y;
60+
}
61+
62+
/// <summary>
63+
/// Hex distance to the other coords.
64+
/// </summary>
65+
public int DistanceTo(HexCoords other) {
66+
var delta = this - other;
67+
return (Mathf.Abs(delta.X) + Mathf.Abs(delta.Y) + Mathf.Abs(delta.Z)) / 2;
68+
}
69+
70+
/// <summary>
71+
/// Hex distance to the zero coords.
72+
/// </summary>
73+
/// <returns></returns>
74+
public int Magnitude() {
75+
return DistanceTo(Zero);
76+
}
77+
78+
public bool Equals(HexCoords other) {
79+
return other.X == X && other.Y == Y;
80+
}
81+
82+
public override bool Equals(object obj) {
83+
return obj is HexCoords coords && Equals(coords);
84+
}
85+
86+
public override int GetHashCode() {
87+
return Tuple.Create(_x, _y).GetHashCode();
88+
}
89+
90+
public override string ToString() {
91+
return $"({X}, {Y}, {Z})";
92+
}
93+
94+
public static bool operator ==(HexCoords a, HexCoords b) {
95+
return a.Equals(b);
96+
}
97+
98+
public static bool operator !=(HexCoords a, HexCoords b) {
99+
return !(a == b);
100+
}
101+
}
102+
}

Runtime/HexCoords.cs.meta

+3
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Runtime/HexDirection.cs

+148
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using UnityEngine;
4+
5+
namespace HexEngine {
6+
/// <summary>
7+
/// Enum representation of six direction in hex space.
8+
/// </summary>
9+
public enum HexDirection
10+
{
11+
N,
12+
NE,
13+
SE,
14+
S,
15+
SW,
16+
NW
17+
}
18+
19+
public static class HexDirectionExtension {
20+
21+
#region Readonly Arrays
22+
private static readonly HexCoords[] _coords = new[] {
23+
new HexCoords(0, 1),
24+
new HexCoords(1, 0),
25+
new HexCoords(1, -1),
26+
new HexCoords(0, -1),
27+
new HexCoords(-1, 0),
28+
new HexCoords(-1, 1),
29+
};
30+
31+
private static readonly float[] _angles = new[] {
32+
0f, 60f, 120f,
33+
180f, 240f, 300f
34+
};
35+
36+
private static readonly Vector3[] _directions = new[] {
37+
Quaternion.Euler(0f, _angles[0], 0f) * Vector3.forward,
38+
Quaternion.Euler(0f, _angles[1], 0f) * Vector3.forward,
39+
Quaternion.Euler(0f, _angles[2], 0f) * Vector3.forward,
40+
Quaternion.Euler(0f, _angles[3], 0f) * Vector3.forward,
41+
Quaternion.Euler(0f, _angles[4], 0f) * Vector3.forward,
42+
Quaternion.Euler(0f, _angles[5], 0f) * Vector3.forward,
43+
};
44+
45+
private static readonly Vector3[] _vertexDirections = new[] {
46+
Quaternion.Euler(0f, _angles[0] - 30f, 0f) * Vector3.forward,
47+
Quaternion.Euler(0f, _angles[1] - 30f, 0f) * Vector3.forward,
48+
Quaternion.Euler(0f, _angles[2] - 30f, 0f) * Vector3.forward,
49+
Quaternion.Euler(0f, _angles[3] - 30f, 0f) * Vector3.forward,
50+
Quaternion.Euler(0f, _angles[4] - 30f, 0f) * Vector3.forward,
51+
Quaternion.Euler(0f, _angles[5] - 30f, 0f) * Vector3.forward,
52+
};
53+
54+
private const float VertexFactor = .5f * HexMath.InToOutRadius;
55+
private static readonly Vector3[] _vertices = new[] {
56+
Quaternion.Euler(0f, _angles[0] - 30f, 0f) * Vector3.forward * VertexFactor,
57+
Quaternion.Euler(0f, _angles[1] - 30f, 0f) * Vector3.forward * VertexFactor,
58+
Quaternion.Euler(0f, _angles[2] - 30f, 0f) * Vector3.forward * VertexFactor,
59+
Quaternion.Euler(0f, _angles[3] - 30f, 0f) * Vector3.forward * VertexFactor,
60+
Quaternion.Euler(0f, _angles[4] - 30f, 0f) * Vector3.forward * VertexFactor,
61+
Quaternion.Euler(0f, _angles[5] - 30f, 0f) * Vector3.forward * VertexFactor,
62+
};
63+
#endregion
64+
65+
/// <summary>
66+
/// HexCoords of the direction.
67+
/// </summary>
68+
public static HexCoords Coords(this HexDirection direction) => _coords[(int) direction];
69+
70+
/// <summary>
71+
/// Angle in degrees from 0 for HexDirection.N, increasing clockwise.
72+
/// </summary>
73+
public static float Angle(this HexDirection direction) => _angles[(int) direction];
74+
75+
/// <summary>
76+
/// Normalized vector of direction in 3D space for HexDirection, where HexDirection.N is Vector3.forward.
77+
/// </summary>
78+
public static Vector3 Direction(this HexDirection direction) => _directions[(int) direction];
79+
80+
/// <summary>
81+
/// Normalized vector of direction to the left corner of the hex edge in given direction.
82+
/// </summary>
83+
public static Vector3 LeftCornerDirection(this HexDirection direction) => _vertexDirections[(int) direction];
84+
85+
/// <summary>
86+
/// Normalized vector of direction to the right corner of the hex edge in given direction.
87+
/// </summary>
88+
public static Vector3 RightCornerDirection(this HexDirection direction) => _vertexDirections[((int) direction + 1) % 6];
89+
90+
/// <summary>
91+
/// Vector from the center of the hex to the left corner on the edge in given direction.
92+
/// </summary>
93+
public static Vector3 LeftCorner(this HexDirection direction) => _vertices[(int) direction];
94+
95+
/// <summary>
96+
/// Vector from the center of the hex to the right corner on the edge in given direction.
97+
/// </summary>
98+
public static Vector3 RightCorner(this HexDirection direction) => _vertices[((int) direction + 1) % 6];
99+
100+
/// <summary>
101+
/// Iterates through all hex directions starting from this direction and going clockwise.
102+
/// </summary>
103+
public static IEnumerable<HexDirection> Loop(this HexDirection direction) {
104+
var startIndex = (int) direction;
105+
for (int i = 0; i < 6; i++) {
106+
yield return (HexDirection) ((startIndex + i) % 6);
107+
}
108+
}
109+
110+
/// <summary>
111+
/// Returns HexDirection rotated clockwise.
112+
/// </summary>
113+
public static HexDirection Rotate(this HexDirection direction, int rotation) {
114+
var value = (int) direction + rotation;
115+
value = ((value % 6) + 6);
116+
return (HexDirection) (rotation % 6);
117+
}
118+
119+
/// <summary>
120+
/// Returns HexDirection rotated clockwise once.
121+
/// </summary>
122+
public static HexDirection Right(this HexDirection direction) {
123+
return (HexDirection) (((int) direction + 1) % 6);
124+
}
125+
126+
/// <summary>
127+
/// Returns HexDirection rotated counter-clockwise once.
128+
/// </summary>
129+
public static HexDirection Left(this HexDirection direction) {
130+
return (HexDirection) (((int) direction + 5) % 6);
131+
}
132+
133+
/// <summary>
134+
/// Returns the opposite HexDirection.
135+
/// </summary>
136+
public static HexDirection Opposite(this HexDirection direction) {
137+
return (HexDirection) (((int) direction + 3) % 6);
138+
}
139+
140+
/// <summary>
141+
/// If given HexCoords are coords of any HexDirection, it returns given HexDirection.
142+
/// Otherwise it throws an error.
143+
/// </summary>
144+
public static HexDirection ToDirection(this HexCoords coords) {
145+
return (HexDirection) Array.IndexOf(_coords, coords);
146+
}
147+
}
148+
}

Runtime/HexDirection.cs.meta

+3
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Runtime/HexEngine.asmdef

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
{
2+
"name": "HexEngine",
3+
"rootNamespace": "HexEngine",
4+
"references": [],
5+
"includePlatforms": [],
6+
"excludePlatforms": [],
7+
"allowUnsafeCode": false,
8+
"overrideReferences": false,
9+
"precompiledReferences": [],
10+
"autoReferenced": true,
11+
"defineConstraints": [],
12+
"versionDefines": [],
13+
"noEngineReferences": false
14+
}

Runtime/HexEngine.asmdef.meta

+7
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Runtime/HexMap.cs

+49
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
using System.Collections.Generic;
2+
using System.Linq;
3+
using UnityEngine;
4+
5+
namespace HexEngine {
6+
public abstract class HexMap {
7+
public abstract IEnumerable<IHexTile> AllBaseTiles { get; }
8+
public abstract bool HasTile(HexCoords coords);
9+
public abstract IHexTile GetTile(HexCoords coords);
10+
}
11+
12+
/// <summary>
13+
/// Simple class for storing hexes in dictionary.
14+
/// </summary>
15+
public class HexMap<T> : HexMap where T : IHexTile<T> {
16+
private Dictionary<HexCoords, T> _tiles = new Dictionary<HexCoords, T>();
17+
18+
public IEnumerable<T> AllTiles => _tiles.Values;
19+
public override IEnumerable<IHexTile> AllBaseTiles => AllTiles.Cast<IHexTile>();
20+
21+
/// <summary>
22+
/// Tries to return a tile on given coords, returns null if no tile exists.
23+
/// </summary>
24+
public T this[HexCoords coords]
25+
{
26+
get
27+
{
28+
if (_tiles.TryGetValue(coords, out var result)) {
29+
return result;
30+
}
31+
32+
return default;
33+
}
34+
set
35+
{
36+
if (value == null) {
37+
Debug.LogError($"Overriding tile({coords})!");
38+
_tiles.Remove(coords);
39+
}
40+
else {
41+
_tiles[coords] = value;
42+
}
43+
}
44+
}
45+
46+
public override bool HasTile(HexCoords coords) => _tiles.ContainsKey(coords);
47+
public override IHexTile GetTile(HexCoords coords) => this[coords];
48+
}
49+
}

Runtime/HexMap.cs.meta

+3
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)