添加 CombatNodeComponent 及相关类

- CombatNodeComponent:节点组件,负责提取并开始关卡
- CombatScheduler:关卡调度器,负责关卡的生命周期调度
- MapEntity:地图实体,提供地图相关的数据
- Spawner:出生点,负责标记地图上的敌人出生点坐标
- House:基地,负责标记地图上的敌人目标点坐标
This commit is contained in:
SepComet
2026-02-28 15:44:22 +08:00
parent d9c118ace3
commit dd9cedef5f
91 changed files with 37977 additions and 651 deletions
@@ -0,0 +1,134 @@
using System.Collections.Generic;
using UnityEngine;
namespace GeometryTD.Pathfinding
{
public class GridMapPathfinder : IMapPathfinder
{
private static readonly Vector3Int[] NeighborOffsets =
{
new Vector3Int(1, 0, 0),
new Vector3Int(-1, 0, 0),
new Vector3Int(0, 1, 0),
new Vector3Int(0, -1, 0)
};
private readonly HashSet<Vector3Int> _walkableSet = new HashSet<Vector3Int>();
private readonly Queue<Vector3Int> _openQueue = new Queue<Vector3Int>();
private readonly Dictionary<Vector3Int, Vector3Int> _cameFrom = new Dictionary<Vector3Int, Vector3Int>();
public bool TryFindPath(
IReadOnlyCollection<Vector3Int> walkableCells,
Vector3Int startCell,
Vector3Int destinationCell,
IReadOnlyCollection<Vector3Int> blockedCells,
List<Vector3Int> pathResult)
{
if (pathResult == null)
{
return false;
}
pathResult.Clear();
if (walkableCells == null || walkableCells.Count <= 0)
{
return false;
}
BuildWalkableSet(walkableCells);
if (!_walkableSet.Contains(startCell) || !_walkableSet.Contains(destinationCell))
{
return false;
}
_openQueue.Clear();
_cameFrom.Clear();
_openQueue.Enqueue(startCell);
_cameFrom[startCell] = startCell;
while (_openQueue.Count > 0)
{
Vector3Int currentCell = _openQueue.Dequeue();
if (currentCell == destinationCell)
{
BuildPath(destinationCell, pathResult);
return true;
}
for (int i = 0; i < NeighborOffsets.Length; i++)
{
Vector3Int nextCell = currentCell + NeighborOffsets[i];
if (!_walkableSet.Contains(nextCell) || _cameFrom.ContainsKey(nextCell))
{
continue;
}
if (IsBlocked(nextCell, blockedCells, startCell, destinationCell))
{
continue;
}
_cameFrom[nextCell] = currentCell;
_openQueue.Enqueue(nextCell);
}
}
return false;
}
private void BuildWalkableSet(IReadOnlyCollection<Vector3Int> walkableCells)
{
_walkableSet.Clear();
foreach (Vector3Int cell in walkableCells)
{
_walkableSet.Add(cell);
}
}
private void BuildPath(Vector3Int destinationCell, List<Vector3Int> pathResult)
{
pathResult.Clear();
Vector3Int current = destinationCell;
while (true)
{
pathResult.Add(current);
Vector3Int parent = _cameFrom[current];
if (parent == current)
{
break;
}
current = parent;
}
pathResult.Reverse();
}
private static bool IsBlocked(
Vector3Int cell,
IReadOnlyCollection<Vector3Int> blockedCells,
Vector3Int startCell,
Vector3Int destinationCell)
{
if (blockedCells == null || blockedCells.Count <= 0)
{
return false;
}
if (cell == startCell || cell == destinationCell)
{
return false;
}
foreach (Vector3Int blockedCell in blockedCells)
{
if (blockedCell == cell)
{
return true;
}
}
return false;
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 7a92a95ffefd4a6082255420a184ee34
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,15 @@
using System.Collections.Generic;
using UnityEngine;
namespace GeometryTD.Pathfinding
{
public interface IMapPathfinder
{
bool TryFindPath(
IReadOnlyCollection<Vector3Int> walkableCells,
Vector3Int startCell,
Vector3Int destinationCell,
IReadOnlyCollection<Vector3Int> blockedCells,
List<Vector3Int> pathResult);
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 5540589b31b39ee4db4e77033a511a0c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: