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) { } } }