Updating HUD, Gold Config, and finishing off Play flow for 9player map.
This commit is contained in:
parent
a7be12fa9b
commit
3dcc0e7edd
28 changed files with 2272 additions and 9601 deletions
|
|
@ -61,6 +61,17 @@ namespace TD.Gameplay
|
|||
// Built once on Start from LevelData.Goals[].TileArea.
|
||||
private HashSet<Vector2Int> goalTiles;
|
||||
|
||||
// Precomputed octile-distance-to-nearest-goal, indexed by [y * gridWidth + x] in
|
||||
// grid-local space (subtract GridOriginTile to convert world-tile → array index).
|
||||
// Computed ONCE on Start. Without this, the A* heuristic scanned every goal tile
|
||||
// (~48 tiles for the 9-player map) on every node visit — making the heuristic
|
||||
// O(node visits * goal count) per A* run. With this table, it's O(1) per node.
|
||||
// Tiles outside the grid use Heuristic's fallback path (per-goal scan); they are
|
||||
// rare so the table isn't extended to cover them.
|
||||
private float[] heuristicTable;
|
||||
private Vector2Int heuristicOrigin;
|
||||
private Vector2Int heuristicSize;
|
||||
|
||||
// A* scratch collections — allocated once and cleared per run to avoid GC.
|
||||
// PathfindingService is a singleton, so single-instance scratch is safe.
|
||||
// gScore is float to support diagonal cost √2; the priority queue matches.
|
||||
|
|
@ -85,6 +96,7 @@ namespace TD.Gameplay
|
|||
private void Start()
|
||||
{
|
||||
BuildGoalTileSet();
|
||||
BuildHeuristicTable();
|
||||
|
||||
var loader = LevelLoader.Instance;
|
||||
if (loader != null)
|
||||
|
|
@ -230,9 +242,24 @@ namespace TD.Gameplay
|
|||
}
|
||||
|
||||
// Octile distance to the nearest goal tile. Admissible heuristic for an
|
||||
// 8-connected uniform-cost grid (cardinal 1, diagonal √2).
|
||||
// 8-connected uniform-cost grid (cardinal 1, diagonal √2). Hot path: served
|
||||
// from heuristicTable (O(1)) when the tile is in the grid bounds, otherwise
|
||||
// falls back to scanning every goal (O(goalCount)).
|
||||
private float Heuristic(Vector2Int tile)
|
||||
{
|
||||
if (heuristicTable != null)
|
||||
{
|
||||
int x = tile.x - heuristicOrigin.x;
|
||||
int y = tile.y - heuristicOrigin.y;
|
||||
if (x >= 0 && x < heuristicSize.x && y >= 0 && y < heuristicSize.y)
|
||||
{
|
||||
return heuristicTable[y * heuristicSize.x + x];
|
||||
}
|
||||
}
|
||||
|
||||
// Out-of-grid fallback. A* shouldn't usually visit these (it expands only
|
||||
// from walkable tiles, which are in-bounds), but we keep correctness for
|
||||
// any callers that hand us a stray tile.
|
||||
float best = float.MaxValue;
|
||||
foreach (var goal in goalTiles)
|
||||
{
|
||||
|
|
@ -380,6 +407,53 @@ namespace TD.Gameplay
|
|||
Debug.Log($"[PathfindingService] Goal tile set built: {goalTiles.Count} tiles.");
|
||||
}
|
||||
|
||||
// Precomputes the octile-distance-to-nearest-goal for every tile in the grid.
|
||||
// Runs once on Start (cheap: ~3000 tiles × ~50 goals = 150K octile evaluations on
|
||||
// the 9-player map, well under a millisecond). The output is a flat float[] keyed
|
||||
// by grid-local index, hot for the A* heuristic.
|
||||
private void BuildHeuristicTable()
|
||||
{
|
||||
var loader = LevelLoader.Instance;
|
||||
if (loader == null || loader.LevelData == null)
|
||||
{
|
||||
heuristicTable = null;
|
||||
return;
|
||||
}
|
||||
|
||||
var levelData = loader.LevelData;
|
||||
heuristicOrigin = levelData.GridOriginTile;
|
||||
heuristicSize = levelData.GridSize;
|
||||
|
||||
int total = heuristicSize.x * heuristicSize.y;
|
||||
if (total <= 0 || goalTiles == null || goalTiles.Count == 0)
|
||||
{
|
||||
heuristicTable = null;
|
||||
return;
|
||||
}
|
||||
|
||||
heuristicTable = new float[total];
|
||||
for (int y = 0; y < heuristicSize.y; y++)
|
||||
{
|
||||
for (int x = 0; x < heuristicSize.x; x++)
|
||||
{
|
||||
Vector2Int worldTile = new Vector2Int(
|
||||
heuristicOrigin.x + x,
|
||||
heuristicOrigin.y + y);
|
||||
|
||||
float best = float.MaxValue;
|
||||
foreach (var goal in goalTiles)
|
||||
{
|
||||
float d = GridCoordinates.OctileDistance(worldTile, goal);
|
||||
if (d < best) best = d;
|
||||
}
|
||||
heuristicTable[y * heuristicSize.x + x] = best;
|
||||
}
|
||||
}
|
||||
|
||||
Debug.Log($"[PathfindingService] Heuristic table built: {total} tiles, " +
|
||||
$"origin={heuristicOrigin}, size={heuristicSize}.");
|
||||
}
|
||||
|
||||
private void HandleWalkabilityChanged()
|
||||
{
|
||||
OnPathsInvalidated?.Invoke();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue