190 lines
4.8 KiB
C#
190 lines
4.8 KiB
C#
using System;
|
|
using System.Diagnostics;
|
|
using System.Linq;
|
|
using Godot;
|
|
using Array = Godot.Collections.Array;
|
|
|
|
public class HexCell : Resource
|
|
{
|
|
public static readonly Vector2 size = new Vector2(1, Mathf.Sqrt(3) / 2);
|
|
public static readonly Vector3 DIR_N = new Vector3(0, 1, -1);
|
|
public static readonly Vector3 DIR_NE = new Vector3(1, 0, -1);
|
|
public static readonly Vector3 DIR_SE = new Vector3(1, -1, 0);
|
|
public static readonly Vector3 DIR_S = new Vector3(0, -1, 1);
|
|
public static readonly Vector3 DIR_SW = new Vector3(-1, 0, 1);
|
|
public static readonly Vector3 DIR_NW = new Vector3(-1, 1, 0);
|
|
|
|
public static readonly Array DIR_ALL = new Array()
|
|
{ DIR_N, DIR_NE, DIR_SE, DIR_S, DIR_SW, DIR_NW };
|
|
|
|
public HexCell()
|
|
{
|
|
}
|
|
|
|
public HexCell(float cubeX, float cubeY, float cubeZ)
|
|
{
|
|
CubeCoords = RoundCoords(new Vector3(cubeX, cubeY, cubeZ));
|
|
}
|
|
|
|
public static bool operator==(HexCell cellA, HexCell cellB)
|
|
{
|
|
return cellA.AxialCoords == cellB.AxialCoords;
|
|
}
|
|
|
|
public static bool operator!=(HexCell cellA, HexCell cellB)
|
|
{
|
|
return cellA.AxialCoords != cellB.AxialCoords;
|
|
}
|
|
|
|
public HexCell(Vector3 cubeCoords)
|
|
{
|
|
CubeCoords = cubeCoords;
|
|
}
|
|
|
|
public HexCell(float axialX, float axialY)
|
|
{
|
|
AxialCoords = new Vector2(axialX, axialY);
|
|
}
|
|
|
|
public HexCell(Vector2 axialCoords)
|
|
{
|
|
AxialCoords = axialCoords;
|
|
}
|
|
|
|
public HexCell(HexCell other)
|
|
{
|
|
CubeCoords = other.CubeCoords;
|
|
}
|
|
|
|
public static HexCell FromOffsetCoords(Vector2 offsetCoords)
|
|
{
|
|
HexCell result = new HexCell();
|
|
result.OffsetCoords = offsetCoords;
|
|
|
|
return result;
|
|
}
|
|
|
|
private Vector3 _cubeCoords;
|
|
|
|
public Vector3 CubeCoords
|
|
{
|
|
get { return _cubeCoords; }
|
|
set
|
|
{
|
|
if (Mathf.Abs(value.x + value.y + value.z) > 0.0001)
|
|
{
|
|
GD.Print("Warning: Invalid cube coordinates for hex (x + y + z != 0): ", value.ToString());
|
|
}
|
|
|
|
_cubeCoords = RoundCoords(value);
|
|
}
|
|
}
|
|
|
|
public Vector2 AxialCoords
|
|
{
|
|
get => new Vector2(CubeCoords.x, CubeCoords.y);
|
|
|
|
set { CubeCoords = AxialToCubeCoords(value); }
|
|
}
|
|
|
|
public Vector2 OffsetCoords
|
|
{
|
|
get
|
|
{
|
|
int x = (int)CubeCoords.x;
|
|
int y = (int)CubeCoords.y;
|
|
int off_y = y + (x - (x & 1)) / 2;
|
|
return new Vector2(x, off_y);
|
|
}
|
|
|
|
set
|
|
{
|
|
int x = (int)value.x;
|
|
int y = (int)value.y;
|
|
int cube_y = y - (x - (x & 1)) / 2;
|
|
AxialCoords = new Vector2(x, cube_y);
|
|
}
|
|
}
|
|
|
|
public Vector3 AxialToCubeCoords(Vector2 axialCoords)
|
|
{
|
|
return new Vector3(axialCoords.x, axialCoords.y, -axialCoords.x - axialCoords.y);
|
|
}
|
|
|
|
public Vector3 RoundCoords(Vector2 coords)
|
|
{
|
|
Vector3 cubeCoords = AxialToCubeCoords(coords);
|
|
|
|
return RoundCoords(cubeCoords);
|
|
}
|
|
|
|
public Vector3 RoundCoords(Vector3 cubeCoords)
|
|
{
|
|
Vector3 rounded = new Vector3(
|
|
Mathf.Round(cubeCoords.x),
|
|
Mathf.Round(cubeCoords.y),
|
|
Mathf.Round(cubeCoords.z));
|
|
|
|
Vector3 diffs = (rounded - cubeCoords).Abs();
|
|
if (diffs.x > diffs.y && diffs.x > diffs.z)
|
|
{
|
|
rounded.x = -rounded.y - rounded.z;
|
|
}
|
|
else if (diffs.y > diffs.z)
|
|
{
|
|
rounded.y = -rounded.x - rounded.z;
|
|
}
|
|
else
|
|
{
|
|
rounded.z = -rounded.x - rounded.y;
|
|
}
|
|
|
|
return rounded;
|
|
}
|
|
|
|
public HexCell GetAdjacent(Vector3 dir)
|
|
{
|
|
return new HexCell(this.CubeCoords + dir);
|
|
}
|
|
|
|
public HexCell[] GetAllAdjacent()
|
|
{
|
|
return new[]
|
|
{
|
|
GetAdjacent(DIR_NE),
|
|
GetAdjacent(DIR_SE),
|
|
GetAdjacent(DIR_S),
|
|
GetAdjacent(DIR_SW),
|
|
GetAdjacent(DIR_NW),
|
|
GetAdjacent(DIR_N)
|
|
};
|
|
}
|
|
|
|
public int DistanceTo(HexCell target)
|
|
{
|
|
return (int)(
|
|
Mathf.Abs(_cubeCoords.x - target.CubeCoords.x)
|
|
+ Mathf.Abs(_cubeCoords.y - target.CubeCoords.y)
|
|
+ Mathf.Abs(_cubeCoords.z - target.CubeCoords.z)
|
|
) / 2;
|
|
}
|
|
|
|
public HexCell[] LineTo(HexCell target)
|
|
{
|
|
HexCell nudgedTarget = new HexCell();
|
|
nudgedTarget.CubeCoords = target.CubeCoords + new Vector3(1.0e-6f, 2.0e-6f, -3.0e-6f);
|
|
int steps = DistanceTo(target);
|
|
|
|
HexCell[] path = new HexCell[steps + 1];
|
|
|
|
foreach (int dist in Enumerable.Range(0, steps))
|
|
{
|
|
path[dist] = new HexCell();
|
|
path[dist].CubeCoords = CubeCoords.LinearInterpolate(nudgedTarget.CubeCoords, (float)dist / steps);
|
|
}
|
|
|
|
path[steps] = target;
|
|
|
|
return path;
|
|
}
|
|
} |