Files

42 lines
1.8 KiB
C#
Raw Permalink Normal View History

namespace Theriapolis.Core.Tactical;
/// <summary>
/// Integer (cx, cy) key for a tactical chunk. The chunk covers world-pixel
/// rectangle [cx*CHUNK_SIZE, cy*CHUNK_SIZE, (cx+1)*CHUNK_SIZE, (cy+1)*CHUNK_SIZE).
/// At the current constants (CHUNK_SIZE = 64, TACTICAL_PER_WORLD_TILE = 32),
/// each chunk covers 2×2 world tiles.
/// </summary>
public readonly struct ChunkCoord : IEquatable<ChunkCoord>
{
public readonly int X;
public readonly int Y;
public ChunkCoord(int x, int y) { X = x; Y = y; }
/// <summary>Chunk that contains the given tactical-tile (world-pixel) coordinate.</summary>
public static ChunkCoord ForTactical(int tx, int ty)
=> new(FloorDiv(tx, C.TACTICAL_CHUNK_SIZE), FloorDiv(ty, C.TACTICAL_CHUNK_SIZE));
/// <summary>Chunk that contains the given world-tile coordinate.</summary>
public static ChunkCoord ForWorldTile(int wx, int wy)
{
// 1 world tile = TACTICAL_PER_WORLD_TILE world pixels = TACTICAL_PER_WORLD_TILE
// tactical tiles. One chunk covers CHUNK_SIZE / TACTICAL_PER_WORLD_TILE world tiles.
int worldTilesPerChunk = C.TACTICAL_CHUNK_SIZE / C.TACTICAL_PER_WORLD_TILE;
return new(FloorDiv(wx, worldTilesPerChunk), FloorDiv(wy, worldTilesPerChunk));
}
private static int FloorDiv(int a, int b)
{
int q = a / b;
if ((a ^ b) < 0 && q * b != a) q--;
return q;
}
public bool Equals(ChunkCoord other) => X == other.X && Y == other.Y;
public override bool Equals(object? obj) => obj is ChunkCoord c && Equals(c);
public override int GetHashCode() => HashCode.Combine(X, Y);
public static bool operator ==(ChunkCoord a, ChunkCoord b) => a.Equals(b);
public static bool operator !=(ChunkCoord a, ChunkCoord b) => !a.Equals(b);
public override string ToString() => $"({X},{Y})";
}