using System; using System.Runtime.CompilerServices; using Unity.Mathematics; namespace DanieleMarotta.RiversongCodeShowcase { public static class TileMath { [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int2 Rotate(int2 v, Directions direction) { switch (direction) { case Directions.North: return new int2(v.x, v.y); case Directions.West: return new int2(v.y, -v.x); case Directions.South: return new int2(-v.x, -v.y); case Directions.East: return new int2(-v.y, v.x); default: throw new ArgumentOutOfRangeException(); } } public static TileRect GetBuildingRect(int2 rectCenter, Directions direction, int width, int height) { int dx; int dy; var sx = (width - 1) >> 1; var sy = (height - 1) >> 1; if (width == height || direction == Directions.North) { dx = -sx; dy = -sy; } else { switch (direction) { case Directions.West: dx = sy - (height - 1); dy = -sx; (width, height) = (height, width); break; case Directions.South: dx = sx - (width - 1); dy = sy - (height - 1); break; case Directions.East: dx = -sy; dy = sx - (width - 1); (width, height) = (height, width); break; default: throw new ArgumentOutOfRangeException(); } } return new TileRect(rectCenter + new int2(dx, dy), width, height); } public static void WalkLine(int2 startTile, int2 endTile, Action tileAction) { var dx = endTile.x - startTile.x; var dy = endTile.y - startTile.y; if (math.abs(dx) >= math.abs(dy)) endTile.y = startTile.y; else endTile.x = startTile.x; var tile = startTile; var d = math.sign(endTile - startTile); while (true) { tileAction.Invoke(tile); if (math.all(tile == endTile)) break; tile += d; } } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int StepCount(int2 tile, int2 otherTile) { var delta = math.abs(tile - otherTile); return math.max(delta.x, delta.y); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int StepCount(int2 tile, in TileRect rect) { var left = math.max(rect.Min.x - tile.x, 0); var right = math.max(tile.x - rect.Max.x, 0); var dx = math.max(left, right); var bottom = math.max(rect.Min.y - tile.y, 0); var top = math.max(tile.y - rect.Max.y, 0); var dy = math.max(bottom, top); return math.max(dx, dy); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int StepCount(in TileRect rect, int2 tile) { return StepCount(tile, rect); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int StepCount(in TileRect rect, in TileRect otherRect) { var left = math.max(otherRect.Min.x - rect.Max.x, 0); var right = math.max(rect.Min.x - otherRect.Max.x, 0); var dx = math.max(left, right); var bottom = math.max(otherRect.Min.y - rect.Max.y, 0); var top = math.max(rect.Min.y - otherRect.Max.y, 0); var dy = math.max(bottom, top); return math.max(dx, dy); } } }