Adding 9 Player level

This commit is contained in:
Matt F 2026-05-21 23:36:19 -07:00
parent fdada6f132
commit a7be12fa9b
30 changed files with 45984 additions and 300 deletions

View file

@ -91,8 +91,12 @@ namespace TD.Levels
// -------------------------------------------------------------------
// Static rasterization helper. Single source of truth for converting a Bounds to the
// set of tiles its rasterization covers. The bake will use the same primitive (a tile
// is "covered" iff bounds.Contains(tileCenter)) so gizmos and bake stay in lock-step.
// set of tiles its rasterization covers. Uses a half-open interval (min inclusive,
// max exclusive) on XZ so that:
// - a volume sized to N whole tiles rasterizes to exactly N tiles (no off-by-one),
// - two volumes that share a boundary (e.g., one ending at X=20, next starting at
// X=20) do not double-claim the boundary tile.
// Gizmos and bake share this helper so they stay in lock-step.
// -------------------------------------------------------------------
/// <summary>
@ -100,8 +104,8 @@ namespace TD.Levels
/// <paramref name="onTile"/> for each one. The candidate range is computed via
/// <see cref="GridCoordinates.WorldToGrid"/> with a one-tile padding on each side to guard
/// against rounding surprises (WorldToGrid uses round-to-nearest, which can over- or
/// under-shoot by one when bounds align with tile edges); the per-tile
/// <c>bounds.Contains(tileCenter)</c> test inside the loop guarantees correctness.
/// under-shoot by one when bounds align with tile edges); the per-tile half-open
/// interval test inside the loop guarantees correctness.
/// </summary>
public static void RasterizeBoundsToTiles(Bounds bounds, System.Action<Vector2Int> onTile)
{
@ -120,8 +124,11 @@ namespace TD.Levels
for (int y = yLo; y <= yHi; y++)
{
Vector3 tileCenter = GridCoordinates.GridToWorld(new Vector2Int(x, y));
Vector3 testPoint = new Vector3(tileCenter.x, bounds.center.y, tileCenter.z);
if (bounds.Contains(testPoint))
// Half-open interval on XZ: min inclusive, max exclusive. Y axis is implicitly
// satisfied because we test at bounds.center.y, which is always within Y range.
bool xIn = tileCenter.x >= bounds.min.x && tileCenter.x < bounds.max.x;
bool zIn = tileCenter.z >= bounds.min.z && tileCenter.z < bounds.max.z;
if (xIn && zIn)
{
onTile(new Vector2Int(x, y));
}
@ -226,12 +233,12 @@ namespace TD.Levels
if (!TryGetTightTileRect(out Vector2Int minTile, out Vector2Int maxTile)) return;
// Convert tile-corner indices to world-space corners. A tile at (x, y) spans world XZ
// from (x - 0.5, y - 0.5) to (x + 0.5, y + 0.5) (TILE_SIZE = 1, center-based).
float halfTile = GridCoordinates.TILE_SIZE * 0.5f;
Vector3 swCorner = new Vector3(minTile.x - halfTile, yLevel, minTile.y - halfTile);
Vector3 seCorner = new Vector3(maxTile.x + halfTile, yLevel, minTile.y - halfTile);
Vector3 neCorner = new Vector3(maxTile.x + halfTile, yLevel, maxTile.y + halfTile);
Vector3 nwCorner = new Vector3(minTile.x - halfTile, yLevel, maxTile.y + halfTile);
// from (x, y) to (x+1, y+1) (TILE_SIZE = 1, edge-aligned).
float tileSize = GridCoordinates.TILE_SIZE;
Vector3 swCorner = new Vector3(minTile.x * tileSize, yLevel, minTile.y * tileSize);
Vector3 seCorner = new Vector3((maxTile.x + 1) * tileSize, yLevel, minTile.y * tileSize);
Vector3 neCorner = new Vector3((maxTile.x + 1) * tileSize, yLevel, (maxTile.y + 1) * tileSize);
Vector3 nwCorner = new Vector3(minTile.x * tileSize, yLevel, (maxTile.y + 1) * tileSize);
Color prev = Gizmos.color;
Gizmos.color = outlineColor;