121 lines
4.0 KiB
C#
121 lines
4.0 KiB
C#
using System.Numerics;
|
|
using PlayFab.Internal;
|
|
using UnityEngine;
|
|
using Vector3 = UnityEngine.Vector3;
|
|
|
|
// 项目中主要采用的是尖顶的 pointy-top ,平顶的 Flat-top 后续在考虑
|
|
namespace HexGrid.Math
|
|
{
|
|
public static class HexMath {
|
|
|
|
//
|
|
private static float _gridSize;
|
|
private static Vector3 _originPos = Vector3.zero;
|
|
|
|
// size = hex radius (distance center->corner)
|
|
// pointy-top axial coordinates on XZ plane
|
|
// Arial坐标 ->World
|
|
public static Vector3 AxialToPixel(int q, int r )
|
|
{
|
|
var x = _gridSize * Mathf.Sqrt(3f) * (q + r / 2f);
|
|
var z = _gridSize * 1.5f * r;
|
|
return new Vector3(x, 0, z) + _originPos;
|
|
}
|
|
//Arial -> World
|
|
public static Vector2Int PixelToAxial(Vector3 pos)
|
|
{
|
|
var posRelative = pos - _originPos;
|
|
Debug.Log($"posRelative->{pos}-> {posRelative}");
|
|
var q = (Mathf.Sqrt(3f) / 3f * posRelative.x - 1f / 3f * posRelative.z) / _gridSize;
|
|
var r = (2f / 3f * posRelative.z) / _gridSize;
|
|
return HexRound(q, r);
|
|
}
|
|
private static Vector2Int HexRound(float q, float r)
|
|
{
|
|
float x = q;
|
|
float z = r;
|
|
float y = -x - z;
|
|
|
|
int rx = Mathf.RoundToInt(x);
|
|
int ry = Mathf.RoundToInt(y);
|
|
int rz = Mathf.RoundToInt(z);
|
|
|
|
float x_diff = Mathf.Abs(rx - x);
|
|
float y_diff = Mathf.Abs(ry - y);
|
|
float z_diff = Mathf.Abs(rz - z);
|
|
|
|
if (x_diff > y_diff && x_diff > z_diff)
|
|
{
|
|
rx = -ry - rz;
|
|
}
|
|
else if (y_diff > z_diff)
|
|
{
|
|
ry = -rx - rz;
|
|
}
|
|
else
|
|
{
|
|
rz = -rx - ry;
|
|
}
|
|
return new Vector2Int(rx, rz);
|
|
}
|
|
|
|
public static Vector3 HexToWorld(HexCoord h, float size, float height=0f) {
|
|
float x = size * (Mathf.Sqrt(3f) * h.q + Mathf.Sqrt(3f) / 2f * h.r);
|
|
float z = size * (3f/2f * h.r);
|
|
return new Vector3(x, height, z);
|
|
}
|
|
// worldPos: arbitrary world point (x,y,z). We project onto XZ plane and compute axial coords.
|
|
public static HexCoord WorldToHexXZ(Vector3 worldPos, float size) {
|
|
float x = worldPos.x;
|
|
float z = worldPos.z;
|
|
float qf = (Mathf.Sqrt(3f)/3f * x - 1f/3f * z) / size;
|
|
float rf = (2f/3f * z) / size;
|
|
return CubeRound(AxialToCube(qf, rf));
|
|
}
|
|
private struct Cube { public float x,y,z; public Cube(float x,float y,float z){this.x=x;this.y=y;this.z=z;} }
|
|
private static Cube AxialToCube(float q, float r) {
|
|
float x = q;
|
|
float z = r;
|
|
float y = -x - z;
|
|
return new Cube(x,y,z);
|
|
}
|
|
private static HexCoord CubeRound(Cube c) {
|
|
int rx = Mathf.RoundToInt(c.x);
|
|
int ry = Mathf.RoundToInt(c.y);
|
|
int rz = Mathf.RoundToInt(c.z);
|
|
|
|
float x_diff = Mathf.Abs(rx - c.x);
|
|
float y_diff = Mathf.Abs(ry - c.y);
|
|
float z_diff = Mathf.Abs(rz - c.z);
|
|
|
|
if (x_diff > y_diff && x_diff > z_diff) rx = -ry - rz;
|
|
else if (y_diff > z_diff) ry = -rx - rz;
|
|
else rz = -rx - ry;
|
|
|
|
return new HexCoord(rx, rz); // axial q = x, r = z
|
|
}
|
|
|
|
public static int Distance(HexCoord a, HexCoord b) {
|
|
int ax = a.q, az = a.r, ay = -ax - az;
|
|
int bx = b.q, bz = b.r, by = -bx - bz;
|
|
return Mathf.Max(Mathf.Abs(ax - bx), Mathf.Abs(ay - by), Mathf.Abs(az - bz));
|
|
}
|
|
|
|
public static void SetGridSize(float gridSize)
|
|
{
|
|
_gridSize = gridSize;
|
|
}
|
|
public static float GetGridSize() => _gridSize;
|
|
|
|
public static void SetHexMapOrigin(Vector3 zero)
|
|
{
|
|
_originPos = new Vector3(zero.x,0,zero.z);
|
|
}
|
|
|
|
public static void Log(object t)
|
|
{
|
|
|
|
}
|
|
}
|
|
|
|
} |