@esengine/pathfinding 1.0.8 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/dist/index.d.ts +740 -0
- package/dist/index.js +1826 -0
- package/dist/index.js.map +1 -0
- package/module.json +24 -0
- package/package.json +61 -70
- package/README.md +0 -358
- package/dist/pathfinding.cjs +0 -566
- package/dist/pathfinding.cjs.map +0 -1
- package/dist/pathfinding.d.ts +0 -152
- package/dist/pathfinding.js +0 -572
- package/dist/pathfinding.js.map +0 -1
- package/dist/pathfinding.mjs +0 -558
- package/dist/pathfinding.mjs.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/core/IPathfinding.ts","../src/core/BinaryHeap.ts","../src/core/AStarPathfinder.ts","../src/grid/GridMap.ts","../src/navmesh/NavMesh.ts","../src/smoothing/PathSmoother.ts","../src/nodes/PathfindingNodes.ts"],"sourcesContent":["/**\n * @zh 寻路系统核心接口\n * @en Pathfinding System Core Interfaces\n */\n\n// =============================================================================\n// 基础类型 | Basic Types\n// =============================================================================\n\n/**\n * @zh 2D 坐标点\n * @en 2D coordinate point\n */\nexport interface IPoint {\n readonly x: number;\n readonly y: number;\n}\n\n/**\n * @zh 创建点\n * @en Create a point\n */\nexport function createPoint(x: number, y: number): IPoint {\n return { x, y };\n}\n\n/**\n * @zh 路径节点\n * @en Path node\n */\nexport interface IPathNode {\n /** @zh 节点唯一标识 @en Unique node identifier */\n readonly id: string | number;\n /** @zh 节点位置 @en Node position */\n readonly position: IPoint;\n /** @zh 移动代价 @en Movement cost */\n readonly cost: number;\n /** @zh 是否可通行 @en Is walkable */\n readonly walkable: boolean;\n}\n\n/**\n * @zh 路径结果\n * @en Path result\n */\nexport interface IPathResult {\n /** @zh 是否找到路径 @en Whether path was found */\n readonly found: boolean;\n /** @zh 路径点列表 @en List of path points */\n readonly path: readonly IPoint[];\n /** @zh 路径总代价 @en Total path cost */\n readonly cost: number;\n /** @zh 搜索的节点数 @en Number of nodes searched */\n readonly nodesSearched: number;\n}\n\n/**\n * @zh 空路径结果\n * @en Empty path result\n */\nexport const EMPTY_PATH_RESULT: IPathResult = {\n found: false,\n path: [],\n cost: 0,\n nodesSearched: 0\n};\n\n// =============================================================================\n// 地图接口 | Map Interface\n// =============================================================================\n\n/**\n * @zh 寻路地图接口\n * @en Pathfinding map interface\n */\nexport interface IPathfindingMap {\n /**\n * @zh 获取节点的邻居\n * @en Get neighbors of a node\n */\n getNeighbors(node: IPathNode): IPathNode[];\n\n /**\n * @zh 获取指定位置的节点\n * @en Get node at position\n */\n getNodeAt(x: number, y: number): IPathNode | null;\n\n /**\n * @zh 计算两点间的启发式距离\n * @en Calculate heuristic distance between two points\n */\n heuristic(a: IPoint, b: IPoint): number;\n\n /**\n * @zh 计算两个邻居节点间的移动代价\n * @en Calculate movement cost between two neighbor nodes\n */\n getMovementCost(from: IPathNode, to: IPathNode): number;\n\n /**\n * @zh 检查位置是否可通行\n * @en Check if position is walkable\n */\n isWalkable(x: number, y: number): boolean;\n}\n\n// =============================================================================\n// 启发式函数 | Heuristic Functions\n// =============================================================================\n\n/**\n * @zh 启发式函数类型\n * @en Heuristic function type\n */\nexport type HeuristicFunction = (a: IPoint, b: IPoint) => number;\n\n/**\n * @zh 曼哈顿距离(4方向移动)\n * @en Manhattan distance (4-directional movement)\n */\nexport function manhattanDistance(a: IPoint, b: IPoint): number {\n return Math.abs(a.x - b.x) + Math.abs(a.y - b.y);\n}\n\n/**\n * @zh 欧几里得距离(任意方向移动)\n * @en Euclidean distance (any direction movement)\n */\nexport function euclideanDistance(a: IPoint, b: IPoint): number {\n const dx = a.x - b.x;\n const dy = a.y - b.y;\n return Math.sqrt(dx * dx + dy * dy);\n}\n\n/**\n * @zh 切比雪夫距离(8方向移动)\n * @en Chebyshev distance (8-directional movement)\n */\nexport function chebyshevDistance(a: IPoint, b: IPoint): number {\n return Math.max(Math.abs(a.x - b.x), Math.abs(a.y - b.y));\n}\n\n/**\n * @zh 八角距离(8方向移动,对角线代价为 √2)\n * @en Octile distance (8-directional, diagonal cost √2)\n */\nexport function octileDistance(a: IPoint, b: IPoint): number {\n const dx = Math.abs(a.x - b.x);\n const dy = Math.abs(a.y - b.y);\n const D = 1;\n const D2 = Math.SQRT2;\n return D * (dx + dy) + (D2 - 2 * D) * Math.min(dx, dy);\n}\n\n// =============================================================================\n// 寻路器接口 | Pathfinder Interface\n// =============================================================================\n\n/**\n * @zh 寻路配置\n * @en Pathfinding options\n */\nexport interface IPathfindingOptions {\n /** @zh 最大搜索节点数 @en Maximum nodes to search */\n maxNodes?: number;\n /** @zh 启发式权重 (>1 更快但可能非最优) @en Heuristic weight (>1 faster but may be suboptimal) */\n heuristicWeight?: number;\n /** @zh 是否允许对角移动 @en Allow diagonal movement */\n allowDiagonal?: boolean;\n /** @zh 是否避免穿角 @en Avoid corner cutting */\n avoidCorners?: boolean;\n}\n\n/**\n * @zh 默认寻路配置\n * @en Default pathfinding options\n */\nexport const DEFAULT_PATHFINDING_OPTIONS: Required<IPathfindingOptions> = {\n maxNodes: 10000,\n heuristicWeight: 1.0,\n allowDiagonal: true,\n avoidCorners: true\n};\n\n/**\n * @zh 寻路器接口\n * @en Pathfinder interface\n */\nexport interface IPathfinder {\n /**\n * @zh 查找路径\n * @en Find path\n */\n findPath(\n startX: number,\n startY: number,\n endX: number,\n endY: number,\n options?: IPathfindingOptions\n ): IPathResult;\n\n /**\n * @zh 清理状态(用于重用)\n * @en Clear state (for reuse)\n */\n clear(): void;\n}\n\n// =============================================================================\n// 路径平滑接口 | Path Smoothing Interface\n// =============================================================================\n\n/**\n * @zh 路径平滑器接口\n * @en Path smoother interface\n */\nexport interface IPathSmoother {\n /**\n * @zh 平滑路径\n * @en Smooth path\n */\n smooth(path: readonly IPoint[], map: IPathfindingMap): IPoint[];\n}\n\n/**\n * @zh 视线检测函数类型\n * @en Line of sight check function type\n */\nexport type LineOfSightCheck = (\n x1: number,\n y1: number,\n x2: number,\n y2: number,\n map: IPathfindingMap\n) => boolean;\n","/**\n * @zh 二叉堆(优先队列)\n * @en Binary Heap (Priority Queue)\n *\n * @zh 用于 A* 算法的高效开放列表\n * @en Efficient open list for A* algorithm\n */\nexport class BinaryHeap<T> {\n private heap: T[] = [];\n private readonly compare: (a: T, b: T) => number;\n\n /**\n * @zh 创建二叉堆\n * @en Create binary heap\n *\n * @param compare - @zh 比较函数,返回负数表示 a < b @en Compare function, returns negative if a < b\n */\n constructor(compare: (a: T, b: T) => number) {\n this.compare = compare;\n }\n\n /**\n * @zh 堆大小\n * @en Heap size\n */\n get size(): number {\n return this.heap.length;\n }\n\n /**\n * @zh 是否为空\n * @en Is empty\n */\n get isEmpty(): boolean {\n return this.heap.length === 0;\n }\n\n /**\n * @zh 插入元素\n * @en Push element\n */\n push(item: T): void {\n this.heap.push(item);\n this.bubbleUp(this.heap.length - 1);\n }\n\n /**\n * @zh 弹出最小元素\n * @en Pop minimum element\n */\n pop(): T | undefined {\n if (this.heap.length === 0) {\n return undefined;\n }\n\n const result = this.heap[0];\n const last = this.heap.pop()!;\n\n if (this.heap.length > 0) {\n this.heap[0] = last;\n this.sinkDown(0);\n }\n\n return result;\n }\n\n /**\n * @zh 查看最小元素(不移除)\n * @en Peek minimum element (without removing)\n */\n peek(): T | undefined {\n return this.heap[0];\n }\n\n /**\n * @zh 更新元素(重新排序)\n * @en Update element (re-sort)\n */\n update(item: T): void {\n const index = this.heap.indexOf(item);\n if (index !== -1) {\n this.bubbleUp(index);\n this.sinkDown(index);\n }\n }\n\n /**\n * @zh 检查是否包含元素\n * @en Check if contains element\n */\n contains(item: T): boolean {\n return this.heap.indexOf(item) !== -1;\n }\n\n /**\n * @zh 清空堆\n * @en Clear heap\n */\n clear(): void {\n this.heap.length = 0;\n }\n\n /**\n * @zh 上浮操作\n * @en Bubble up operation\n */\n private bubbleUp(index: number): void {\n const item = this.heap[index];\n\n while (index > 0) {\n const parentIndex = Math.floor((index - 1) / 2);\n const parent = this.heap[parentIndex];\n\n if (this.compare(item, parent) >= 0) {\n break;\n }\n\n this.heap[index] = parent;\n index = parentIndex;\n }\n\n this.heap[index] = item;\n }\n\n /**\n * @zh 下沉操作\n * @en Sink down operation\n */\n private sinkDown(index: number): void {\n const length = this.heap.length;\n const item = this.heap[index];\n\n while (true) {\n const leftIndex = 2 * index + 1;\n const rightIndex = 2 * index + 2;\n let smallest = index;\n\n if (leftIndex < length && this.compare(this.heap[leftIndex], this.heap[smallest]) < 0) {\n smallest = leftIndex;\n }\n\n if (rightIndex < length && this.compare(this.heap[rightIndex], this.heap[smallest]) < 0) {\n smallest = rightIndex;\n }\n\n if (smallest === index) {\n break;\n }\n\n this.heap[index] = this.heap[smallest];\n this.heap[smallest] = item;\n index = smallest;\n }\n }\n}\n","/**\n * @zh A* 寻路算法实现\n * @en A* Pathfinding Algorithm Implementation\n */\n\nimport { BinaryHeap } from './BinaryHeap';\nimport type {\n IPathfindingMap,\n IPathfinder,\n IPathResult,\n IPathfindingOptions,\n IPathNode,\n IPoint\n} from './IPathfinding';\nimport { EMPTY_PATH_RESULT, DEFAULT_PATHFINDING_OPTIONS } from './IPathfinding';\n\n// =============================================================================\n// 内部节点类型 | Internal Node Type\n// =============================================================================\n\ninterface AStarNode {\n node: IPathNode;\n g: number; // Cost from start\n h: number; // Heuristic to end\n f: number; // Total cost (g + h)\n parent: AStarNode | null;\n closed: boolean;\n opened: boolean;\n}\n\n// =============================================================================\n// A* 寻路器 | A* Pathfinder\n// =============================================================================\n\n/**\n * @zh A* 寻路器\n * @en A* Pathfinder\n *\n * @zh 使用 A* 算法在地图上查找最短路径\n * @en Uses A* algorithm to find shortest path on a map\n *\n * @example\n * ```typescript\n * const map = new GridMap(width, height);\n * const pathfinder = new AStarPathfinder(map);\n * const result = pathfinder.findPath(0, 0, 10, 10);\n * if (result.found) {\n * console.log('Path:', result.path);\n * }\n * ```\n */\nexport class AStarPathfinder implements IPathfinder {\n private readonly map: IPathfindingMap;\n private nodeCache: Map<string | number, AStarNode> = new Map();\n private openList: BinaryHeap<AStarNode>;\n\n constructor(map: IPathfindingMap) {\n this.map = map;\n this.openList = new BinaryHeap<AStarNode>((a, b) => a.f - b.f);\n }\n\n /**\n * @zh 查找路径\n * @en Find path\n */\n findPath(\n startX: number,\n startY: number,\n endX: number,\n endY: number,\n options?: IPathfindingOptions\n ): IPathResult {\n const opts = { ...DEFAULT_PATHFINDING_OPTIONS, ...options };\n\n // Clear previous state\n this.clear();\n\n // Get start and end nodes\n const startNode = this.map.getNodeAt(startX, startY);\n const endNode = this.map.getNodeAt(endX, endY);\n\n // Validate nodes\n if (!startNode || !endNode) {\n return EMPTY_PATH_RESULT;\n }\n\n if (!startNode.walkable || !endNode.walkable) {\n return EMPTY_PATH_RESULT;\n }\n\n // Same position\n if (startNode.id === endNode.id) {\n return {\n found: true,\n path: [startNode.position],\n cost: 0,\n nodesSearched: 1\n };\n }\n\n // Initialize start node\n const start = this.getOrCreateAStarNode(startNode);\n start.g = 0;\n start.h = this.map.heuristic(startNode.position, endNode.position) * opts.heuristicWeight;\n start.f = start.h;\n start.opened = true;\n\n this.openList.push(start);\n\n let nodesSearched = 0;\n const endPosition = endNode.position;\n\n // A* main loop\n while (!this.openList.isEmpty && nodesSearched < opts.maxNodes) {\n const current = this.openList.pop()!;\n current.closed = true;\n nodesSearched++;\n\n // Found the goal\n if (current.node.id === endNode.id) {\n return this.buildPath(current, nodesSearched);\n }\n\n // Explore neighbors\n const neighbors = this.map.getNeighbors(current.node);\n\n for (const neighborNode of neighbors) {\n // Skip if not walkable or already closed\n if (!neighborNode.walkable) {\n continue;\n }\n\n const neighbor = this.getOrCreateAStarNode(neighborNode);\n\n if (neighbor.closed) {\n continue;\n }\n\n // Calculate tentative g score\n const movementCost = this.map.getMovementCost(current.node, neighborNode);\n const tentativeG = current.g + movementCost;\n\n // Check if this path is better\n if (!neighbor.opened) {\n // First time visiting this node\n neighbor.g = tentativeG;\n neighbor.h = this.map.heuristic(neighborNode.position, endPosition) * opts.heuristicWeight;\n neighbor.f = neighbor.g + neighbor.h;\n neighbor.parent = current;\n neighbor.opened = true;\n this.openList.push(neighbor);\n } else if (tentativeG < neighbor.g) {\n // Found a better path\n neighbor.g = tentativeG;\n neighbor.f = neighbor.g + neighbor.h;\n neighbor.parent = current;\n this.openList.update(neighbor);\n }\n }\n }\n\n // No path found\n return {\n found: false,\n path: [],\n cost: 0,\n nodesSearched\n };\n }\n\n /**\n * @zh 清理状态\n * @en Clear state\n */\n clear(): void {\n this.nodeCache.clear();\n this.openList.clear();\n }\n\n /**\n * @zh 获取或创建 A* 节点\n * @en Get or create A* node\n */\n private getOrCreateAStarNode(node: IPathNode): AStarNode {\n let astarNode = this.nodeCache.get(node.id);\n\n if (!astarNode) {\n astarNode = {\n node,\n g: Infinity,\n h: 0,\n f: Infinity,\n parent: null,\n closed: false,\n opened: false\n };\n this.nodeCache.set(node.id, astarNode);\n }\n\n return astarNode;\n }\n\n /**\n * @zh 构建路径结果\n * @en Build path result\n */\n private buildPath(endNode: AStarNode, nodesSearched: number): IPathResult {\n const path: IPoint[] = [];\n let current: AStarNode | null = endNode;\n\n while (current) {\n path.unshift(current.node.position);\n current = current.parent;\n }\n\n return {\n found: true,\n path,\n cost: endNode.g,\n nodesSearched\n };\n }\n}\n\n// =============================================================================\n// 工厂函数 | Factory Function\n// =============================================================================\n\n/**\n * @zh 创建 A* 寻路器\n * @en Create A* pathfinder\n */\nexport function createAStarPathfinder(map: IPathfindingMap): AStarPathfinder {\n return new AStarPathfinder(map);\n}\n","/**\n * @zh 网格地图实现\n * @en Grid Map Implementation\n */\n\nimport type {\n IPathfindingMap,\n IPathNode,\n IPoint,\n HeuristicFunction\n} from '../core/IPathfinding';\nimport { createPoint, octileDistance } from '../core/IPathfinding';\n\n// =============================================================================\n// 网格节点 | Grid Node\n// =============================================================================\n\n/**\n * @zh 网格节点\n * @en Grid node\n */\nexport class GridNode implements IPathNode {\n readonly id: string;\n readonly position: IPoint;\n readonly x: number;\n readonly y: number;\n cost: number;\n walkable: boolean;\n\n constructor(x: number, y: number, walkable: boolean = true, cost: number = 1) {\n this.x = x;\n this.y = y;\n this.id = `${x},${y}`;\n this.position = createPoint(x, y);\n this.walkable = walkable;\n this.cost = cost;\n }\n}\n\n// =============================================================================\n// 移动方向 | Movement Directions\n// =============================================================================\n\n/**\n * @zh 4方向偏移 (上下左右)\n * @en 4-directional offsets (up, down, left, right)\n */\nexport const DIRECTIONS_4 = [\n { dx: 0, dy: -1 }, // Up\n { dx: 1, dy: 0 }, // Right\n { dx: 0, dy: 1 }, // Down\n { dx: -1, dy: 0 } // Left\n] as const;\n\n/**\n * @zh 8方向偏移 (含对角线)\n * @en 8-directional offsets (including diagonals)\n */\nexport const DIRECTIONS_8 = [\n { dx: 0, dy: -1 }, // Up\n { dx: 1, dy: -1 }, // Up-Right\n { dx: 1, dy: 0 }, // Right\n { dx: 1, dy: 1 }, // Down-Right\n { dx: 0, dy: 1 }, // Down\n { dx: -1, dy: 1 }, // Down-Left\n { dx: -1, dy: 0 }, // Left\n { dx: -1, dy: -1 } // Up-Left\n] as const;\n\n// =============================================================================\n// 网格地图配置 | Grid Map Options\n// =============================================================================\n\n/**\n * @zh 网格地图配置\n * @en Grid map options\n */\nexport interface IGridMapOptions {\n /** @zh 是否允许对角移动 @en Allow diagonal movement */\n allowDiagonal?: boolean;\n /** @zh 对角移动代价 @en Diagonal movement cost */\n diagonalCost?: number;\n /** @zh 是否避免穿角 @en Avoid corner cutting */\n avoidCorners?: boolean;\n /** @zh 启发式函数 @en Heuristic function */\n heuristic?: HeuristicFunction;\n}\n\n/**\n * @zh 默认网格地图配置\n * @en Default grid map options\n */\nexport const DEFAULT_GRID_OPTIONS: Required<IGridMapOptions> = {\n allowDiagonal: true,\n diagonalCost: Math.SQRT2,\n avoidCorners: true,\n heuristic: octileDistance\n};\n\n// =============================================================================\n// 网格地图 | Grid Map\n// =============================================================================\n\n/**\n * @zh 网格地图\n * @en Grid Map\n *\n * @zh 基于二维数组的网格地图实现,支持4方向和8方向移动\n * @en Grid map implementation based on 2D array, supports 4 and 8 directional movement\n *\n * @example\n * ```typescript\n * // Create a 10x10 grid\n * const grid = new GridMap(10, 10);\n *\n * // Set some cells as obstacles\n * grid.setWalkable(5, 5, false);\n * grid.setWalkable(5, 6, false);\n *\n * // Use with pathfinder\n * const pathfinder = new AStarPathfinder(grid);\n * const result = pathfinder.findPath(0, 0, 9, 9);\n * ```\n */\nexport class GridMap implements IPathfindingMap {\n readonly width: number;\n readonly height: number;\n private readonly nodes: GridNode[][];\n private readonly options: Required<IGridMapOptions>;\n\n constructor(width: number, height: number, options?: IGridMapOptions) {\n this.width = width;\n this.height = height;\n this.options = { ...DEFAULT_GRID_OPTIONS, ...options };\n this.nodes = this.createNodes();\n }\n\n /**\n * @zh 创建网格节点\n * @en Create grid nodes\n */\n private createNodes(): GridNode[][] {\n const nodes: GridNode[][] = [];\n\n for (let y = 0; y < this.height; y++) {\n nodes[y] = [];\n for (let x = 0; x < this.width; x++) {\n nodes[y][x] = new GridNode(x, y, true, 1);\n }\n }\n\n return nodes;\n }\n\n /**\n * @zh 获取指定位置的节点\n * @en Get node at position\n */\n getNodeAt(x: number, y: number): GridNode | null {\n if (!this.isInBounds(x, y)) {\n return null;\n }\n return this.nodes[y][x];\n }\n\n /**\n * @zh 检查坐标是否在边界内\n * @en Check if coordinates are within bounds\n */\n isInBounds(x: number, y: number): boolean {\n return x >= 0 && x < this.width && y >= 0 && y < this.height;\n }\n\n /**\n * @zh 检查位置是否可通行\n * @en Check if position is walkable\n */\n isWalkable(x: number, y: number): boolean {\n const node = this.getNodeAt(x, y);\n return node !== null && node.walkable;\n }\n\n /**\n * @zh 设置位置是否可通行\n * @en Set position walkability\n */\n setWalkable(x: number, y: number, walkable: boolean): void {\n const node = this.getNodeAt(x, y);\n if (node) {\n node.walkable = walkable;\n }\n }\n\n /**\n * @zh 设置位置的移动代价\n * @en Set movement cost at position\n */\n setCost(x: number, y: number, cost: number): void {\n const node = this.getNodeAt(x, y);\n if (node) {\n node.cost = cost;\n }\n }\n\n /**\n * @zh 获取节点的邻居\n * @en Get neighbors of a node\n */\n getNeighbors(node: IPathNode): GridNode[] {\n const neighbors: GridNode[] = [];\n const { x, y } = node.position;\n const directions = this.options.allowDiagonal ? DIRECTIONS_8 : DIRECTIONS_4;\n\n for (let i = 0; i < directions.length; i++) {\n const dir = directions[i];\n const nx = x + dir.dx;\n const ny = y + dir.dy;\n\n if (!this.isInBounds(nx, ny)) {\n continue;\n }\n\n const neighbor = this.nodes[ny][nx];\n\n if (!neighbor.walkable) {\n continue;\n }\n\n // Check corner cutting for diagonal movement\n if (this.options.avoidCorners && dir.dx !== 0 && dir.dy !== 0) {\n const horizontal = this.getNodeAt(x + dir.dx, y);\n const vertical = this.getNodeAt(x, y + dir.dy);\n\n if (!horizontal?.walkable || !vertical?.walkable) {\n continue;\n }\n }\n\n neighbors.push(neighbor);\n }\n\n return neighbors;\n }\n\n /**\n * @zh 计算启发式距离\n * @en Calculate heuristic distance\n */\n heuristic(a: IPoint, b: IPoint): number {\n return this.options.heuristic(a, b);\n }\n\n /**\n * @zh 计算移动代价\n * @en Calculate movement cost\n */\n getMovementCost(from: IPathNode, to: IPathNode): number {\n const dx = Math.abs(from.position.x - to.position.x);\n const dy = Math.abs(from.position.y - to.position.y);\n\n // Diagonal movement\n if (dx !== 0 && dy !== 0) {\n return to.cost * this.options.diagonalCost;\n }\n\n // Cardinal movement\n return to.cost;\n }\n\n /**\n * @zh 从二维数组加载地图\n * @en Load map from 2D array\n *\n * @param data - @zh 0=可通行,非0=不可通行 @en 0=walkable, non-0=blocked\n */\n loadFromArray(data: number[][]): void {\n for (let y = 0; y < Math.min(data.length, this.height); y++) {\n for (let x = 0; x < Math.min(data[y].length, this.width); x++) {\n this.nodes[y][x].walkable = data[y][x] === 0;\n }\n }\n }\n\n /**\n * @zh 从字符串加载地图\n * @en Load map from string\n *\n * @param str - @zh 地图字符串,'.'=可通行,'#'=障碍 @en Map string, '.'=walkable, '#'=blocked\n */\n loadFromString(str: string): void {\n const lines = str.trim().split('\\n');\n\n for (let y = 0; y < Math.min(lines.length, this.height); y++) {\n const line = lines[y];\n for (let x = 0; x < Math.min(line.length, this.width); x++) {\n this.nodes[y][x].walkable = line[x] !== '#';\n }\n }\n }\n\n /**\n * @zh 导出为字符串\n * @en Export to string\n */\n toString(): string {\n let result = '';\n\n for (let y = 0; y < this.height; y++) {\n for (let x = 0; x < this.width; x++) {\n result += this.nodes[y][x].walkable ? '.' : '#';\n }\n result += '\\n';\n }\n\n return result;\n }\n\n /**\n * @zh 重置所有节点为可通行\n * @en Reset all nodes to walkable\n */\n reset(): void {\n for (let y = 0; y < this.height; y++) {\n for (let x = 0; x < this.width; x++) {\n this.nodes[y][x].walkable = true;\n this.nodes[y][x].cost = 1;\n }\n }\n }\n\n /**\n * @zh 设置矩形区域的通行性\n * @en Set walkability for a rectangle region\n */\n setRectWalkable(\n x: number,\n y: number,\n width: number,\n height: number,\n walkable: boolean\n ): void {\n for (let dy = 0; dy < height; dy++) {\n for (let dx = 0; dx < width; dx++) {\n this.setWalkable(x + dx, y + dy, walkable);\n }\n }\n }\n}\n\n// =============================================================================\n// 工厂函数 | Factory Function\n// =============================================================================\n\n/**\n * @zh 创建网格地图\n * @en Create grid map\n */\nexport function createGridMap(\n width: number,\n height: number,\n options?: IGridMapOptions\n): GridMap {\n return new GridMap(width, height, options);\n}\n","/**\n * @zh 导航网格实现\n * @en NavMesh Implementation\n */\n\nimport type {\n IPathfindingMap,\n IPathNode,\n IPoint,\n IPathResult,\n IPathfindingOptions\n} from '../core/IPathfinding';\nimport { createPoint, euclideanDistance, EMPTY_PATH_RESULT, DEFAULT_PATHFINDING_OPTIONS } from '../core/IPathfinding';\nimport { BinaryHeap } from '../core/BinaryHeap';\n\n// =============================================================================\n// 导航多边形 | Navigation Polygon\n// =============================================================================\n\n/**\n * @zh 导航多边形\n * @en Navigation polygon\n */\nexport interface INavPolygon {\n /** @zh 多边形ID @en Polygon ID */\n readonly id: number;\n /** @zh 顶点列表 @en Vertex list */\n readonly vertices: readonly IPoint[];\n /** @zh 中心点 @en Center point */\n readonly center: IPoint;\n /** @zh 邻居多边形ID @en Neighbor polygon IDs */\n readonly neighbors: readonly number[];\n /** @zh 到邻居的共享边 @en Shared edges to neighbors */\n readonly portals: ReadonlyMap<number, IPortal>;\n}\n\n/**\n * @zh 入口(两个多边形之间的共享边)\n * @en Portal (shared edge between two polygons)\n */\nexport interface IPortal {\n /** @zh 边的左端点 @en Left endpoint of edge */\n readonly left: IPoint;\n /** @zh 边的右端点 @en Right endpoint of edge */\n readonly right: IPoint;\n}\n\n// =============================================================================\n// 导航网格节点 | NavMesh Node\n// =============================================================================\n\n/**\n * @zh 导航网格节点(包装多边形)\n * @en NavMesh node (wraps polygon)\n */\nclass NavMeshNode implements IPathNode {\n readonly id: number;\n readonly position: IPoint;\n readonly cost: number;\n readonly walkable: boolean;\n readonly polygon: INavPolygon;\n\n constructor(polygon: INavPolygon) {\n this.id = polygon.id;\n this.position = polygon.center;\n this.cost = 1;\n this.walkable = true;\n this.polygon = polygon;\n }\n}\n\n// =============================================================================\n// 导航网格 | Navigation Mesh\n// =============================================================================\n\n/**\n * @zh 导航网格\n * @en Navigation Mesh\n *\n * @zh 使用凸多边形网格进行高效寻路,适合复杂地形\n * @en Uses convex polygon mesh for efficient pathfinding, suitable for complex terrain\n *\n * @example\n * ```typescript\n * const navmesh = new NavMesh();\n *\n * // Add polygons\n * navmesh.addPolygon([\n * { x: 0, y: 0 }, { x: 10, y: 0 },\n * { x: 10, y: 10 }, { x: 0, y: 10 }\n * ]);\n *\n * // Build connections\n * navmesh.build();\n *\n * // Find path\n * const result = navmesh.findPath(1, 1, 8, 8);\n * ```\n */\nexport class NavMesh implements IPathfindingMap {\n private polygons: Map<number, INavPolygon> = new Map();\n private nodes: Map<number, NavMeshNode> = new Map();\n private nextId = 0;\n\n /**\n * @zh 添加导航多边形\n * @en Add navigation polygon\n *\n * @returns @zh 多边形ID @en Polygon ID\n */\n addPolygon(vertices: IPoint[], neighbors: number[] = []): number {\n const id = this.nextId++;\n const center = this.calculateCenter(vertices);\n\n const polygon: INavPolygon = {\n id,\n vertices,\n center,\n neighbors,\n portals: new Map()\n };\n\n this.polygons.set(id, polygon);\n this.nodes.set(id, new NavMeshNode(polygon));\n\n return id;\n }\n\n /**\n * @zh 设置两个多边形之间的连接\n * @en Set connection between two polygons\n */\n setConnection(\n polyA: number,\n polyB: number,\n portal: IPortal\n ): void {\n const polygonA = this.polygons.get(polyA);\n const polygonB = this.polygons.get(polyB);\n\n if (!polygonA || !polygonB) {\n return;\n }\n\n // Update neighbors and portals\n const neighborsA = [...polygonA.neighbors];\n const portalsA = new Map(polygonA.portals);\n\n if (!neighborsA.includes(polyB)) {\n neighborsA.push(polyB);\n }\n portalsA.set(polyB, portal);\n\n this.polygons.set(polyA, {\n ...polygonA,\n neighbors: neighborsA,\n portals: portalsA\n });\n\n // Reverse portal for the other direction\n const reversePortal: IPortal = {\n left: portal.right,\n right: portal.left\n };\n\n const neighborsB = [...polygonB.neighbors];\n const portalsB = new Map(polygonB.portals);\n\n if (!neighborsB.includes(polyA)) {\n neighborsB.push(polyA);\n }\n portalsB.set(polyA, reversePortal);\n\n this.polygons.set(polyB, {\n ...polygonB,\n neighbors: neighborsB,\n portals: portalsB\n });\n }\n\n /**\n * @zh 自动检测并建立相邻多边形的连接\n * @en Auto-detect and build connections between adjacent polygons\n */\n build(): void {\n const polygonList = Array.from(this.polygons.values());\n\n for (let i = 0; i < polygonList.length; i++) {\n for (let j = i + 1; j < polygonList.length; j++) {\n const polyA = polygonList[i];\n const polyB = polygonList[j];\n\n const sharedEdge = this.findSharedEdge(polyA.vertices, polyB.vertices);\n\n if (sharedEdge) {\n this.setConnection(polyA.id, polyB.id, sharedEdge);\n }\n }\n }\n }\n\n /**\n * @zh 查找两个多边形的共享边\n * @en Find shared edge between two polygons\n */\n private findSharedEdge(\n verticesA: readonly IPoint[],\n verticesB: readonly IPoint[]\n ): IPortal | null {\n const epsilon = 0.0001;\n\n for (let i = 0; i < verticesA.length; i++) {\n const a1 = verticesA[i];\n const a2 = verticesA[(i + 1) % verticesA.length];\n\n for (let j = 0; j < verticesB.length; j++) {\n const b1 = verticesB[j];\n const b2 = verticesB[(j + 1) % verticesB.length];\n\n // Check if edges match (in either direction)\n const match1 =\n Math.abs(a1.x - b2.x) < epsilon &&\n Math.abs(a1.y - b2.y) < epsilon &&\n Math.abs(a2.x - b1.x) < epsilon &&\n Math.abs(a2.y - b1.y) < epsilon;\n\n const match2 =\n Math.abs(a1.x - b1.x) < epsilon &&\n Math.abs(a1.y - b1.y) < epsilon &&\n Math.abs(a2.x - b2.x) < epsilon &&\n Math.abs(a2.y - b2.y) < epsilon;\n\n if (match1 || match2) {\n return {\n left: a1,\n right: a2\n };\n }\n }\n }\n\n return null;\n }\n\n /**\n * @zh 计算多边形中心\n * @en Calculate polygon center\n */\n private calculateCenter(vertices: readonly IPoint[]): IPoint {\n let x = 0;\n let y = 0;\n\n for (const v of vertices) {\n x += v.x;\n y += v.y;\n }\n\n return createPoint(x / vertices.length, y / vertices.length);\n }\n\n /**\n * @zh 查找包含点的多边形\n * @en Find polygon containing point\n */\n findPolygonAt(x: number, y: number): INavPolygon | null {\n for (const polygon of this.polygons.values()) {\n if (this.isPointInPolygon(x, y, polygon.vertices)) {\n return polygon;\n }\n }\n return null;\n }\n\n /**\n * @zh 检查点是否在多边形内\n * @en Check if point is inside polygon\n */\n private isPointInPolygon(x: number, y: number, vertices: readonly IPoint[]): boolean {\n let inside = false;\n const n = vertices.length;\n\n for (let i = 0, j = n - 1; i < n; j = i++) {\n const xi = vertices[i].x;\n const yi = vertices[i].y;\n const xj = vertices[j].x;\n const yj = vertices[j].y;\n\n if (\n yi > y !== yj > y &&\n x < ((xj - xi) * (y - yi)) / (yj - yi) + xi\n ) {\n inside = !inside;\n }\n }\n\n return inside;\n }\n\n // ==========================================================================\n // IPathfindingMap 接口实现 | IPathfindingMap Interface Implementation\n // ==========================================================================\n\n getNodeAt(x: number, y: number): IPathNode | null {\n const polygon = this.findPolygonAt(x, y);\n return polygon ? this.nodes.get(polygon.id) ?? null : null;\n }\n\n getNeighbors(node: IPathNode): IPathNode[] {\n const navNode = node as NavMeshNode;\n const neighbors: IPathNode[] = [];\n\n for (const neighborId of navNode.polygon.neighbors) {\n const neighbor = this.nodes.get(neighborId);\n if (neighbor) {\n neighbors.push(neighbor);\n }\n }\n\n return neighbors;\n }\n\n heuristic(a: IPoint, b: IPoint): number {\n return euclideanDistance(a, b);\n }\n\n getMovementCost(from: IPathNode, to: IPathNode): number {\n return euclideanDistance(from.position, to.position);\n }\n\n isWalkable(x: number, y: number): boolean {\n return this.findPolygonAt(x, y) !== null;\n }\n\n // ==========================================================================\n // 寻路 | Pathfinding\n // ==========================================================================\n\n /**\n * @zh 在导航网格上寻路\n * @en Find path on navigation mesh\n */\n findPath(\n startX: number,\n startY: number,\n endX: number,\n endY: number,\n options?: IPathfindingOptions\n ): IPathResult {\n const opts = { ...DEFAULT_PATHFINDING_OPTIONS, ...options };\n\n const startPolygon = this.findPolygonAt(startX, startY);\n const endPolygon = this.findPolygonAt(endX, endY);\n\n if (!startPolygon || !endPolygon) {\n return EMPTY_PATH_RESULT;\n }\n\n // Same polygon\n if (startPolygon.id === endPolygon.id) {\n return {\n found: true,\n path: [createPoint(startX, startY), createPoint(endX, endY)],\n cost: euclideanDistance(\n createPoint(startX, startY),\n createPoint(endX, endY)\n ),\n nodesSearched: 1\n };\n }\n\n // A* on polygon graph\n const polygonPath = this.findPolygonPath(startPolygon, endPolygon, opts);\n\n if (!polygonPath.found) {\n return EMPTY_PATH_RESULT;\n }\n\n // Convert polygon path to point path using funnel algorithm\n const start = createPoint(startX, startY);\n const end = createPoint(endX, endY);\n const pointPath = this.funnelPath(start, end, polygonPath.polygons);\n\n return {\n found: true,\n path: pointPath,\n cost: this.calculatePathLength(pointPath),\n nodesSearched: polygonPath.nodesSearched\n };\n }\n\n /**\n * @zh 在多边形图上寻路\n * @en Find path on polygon graph\n */\n private findPolygonPath(\n start: INavPolygon,\n end: INavPolygon,\n opts: Required<IPathfindingOptions>\n ): { found: boolean; polygons: INavPolygon[]; nodesSearched: number } {\n interface AStarState {\n polygon: INavPolygon;\n g: number;\n f: number;\n parent: AStarState | null;\n }\n\n const openList = new BinaryHeap<AStarState>((a, b) => a.f - b.f);\n const closed = new Set<number>();\n const states = new Map<number, AStarState>();\n\n const startState: AStarState = {\n polygon: start,\n g: 0,\n f: euclideanDistance(start.center, end.center) * opts.heuristicWeight,\n parent: null\n };\n\n states.set(start.id, startState);\n openList.push(startState);\n\n let nodesSearched = 0;\n\n while (!openList.isEmpty && nodesSearched < opts.maxNodes) {\n const current = openList.pop()!;\n nodesSearched++;\n\n if (current.polygon.id === end.id) {\n // Reconstruct path\n const path: INavPolygon[] = [];\n let state: AStarState | null = current;\n\n while (state) {\n path.unshift(state.polygon);\n state = state.parent;\n }\n\n return { found: true, polygons: path, nodesSearched };\n }\n\n closed.add(current.polygon.id);\n\n for (const neighborId of current.polygon.neighbors) {\n if (closed.has(neighborId)) {\n continue;\n }\n\n const neighborPolygon = this.polygons.get(neighborId);\n if (!neighborPolygon) {\n continue;\n }\n\n const g = current.g + euclideanDistance(\n current.polygon.center,\n neighborPolygon.center\n );\n\n let neighborState = states.get(neighborId);\n\n if (!neighborState) {\n neighborState = {\n polygon: neighborPolygon,\n g,\n f: g + euclideanDistance(neighborPolygon.center, end.center) * opts.heuristicWeight,\n parent: current\n };\n states.set(neighborId, neighborState);\n openList.push(neighborState);\n } else if (g < neighborState.g) {\n neighborState.g = g;\n neighborState.f = g + euclideanDistance(neighborPolygon.center, end.center) * opts.heuristicWeight;\n neighborState.parent = current;\n openList.update(neighborState);\n }\n }\n }\n\n return { found: false, polygons: [], nodesSearched };\n }\n\n /**\n * @zh 使用漏斗算法优化路径\n * @en Optimize path using funnel algorithm\n */\n private funnelPath(\n start: IPoint,\n end: IPoint,\n polygons: INavPolygon[]\n ): IPoint[] {\n if (polygons.length <= 1) {\n return [start, end];\n }\n\n // Collect portals\n const portals: IPortal[] = [];\n\n for (let i = 0; i < polygons.length - 1; i++) {\n const portal = polygons[i].portals.get(polygons[i + 1].id);\n if (portal) {\n portals.push(portal);\n }\n }\n\n if (portals.length === 0) {\n return [start, end];\n }\n\n // Simple string pulling algorithm\n const path: IPoint[] = [start];\n\n let apex = start;\n let leftIndex = 0;\n let rightIndex = 0;\n let left = portals[0].left;\n let right = portals[0].right;\n\n for (let i = 1; i <= portals.length; i++) {\n const nextLeft = i < portals.length ? portals[i].left : end;\n const nextRight = i < portals.length ? portals[i].right : end;\n\n // Update right\n if (this.triArea2(apex, right, nextRight) <= 0) {\n if (apex === right || this.triArea2(apex, left, nextRight) > 0) {\n right = nextRight;\n rightIndex = i;\n } else {\n path.push(left);\n apex = left;\n leftIndex = rightIndex = leftIndex;\n left = right = apex;\n i = leftIndex;\n continue;\n }\n }\n\n // Update left\n if (this.triArea2(apex, left, nextLeft) >= 0) {\n if (apex === left || this.triArea2(apex, right, nextLeft) < 0) {\n left = nextLeft;\n leftIndex = i;\n } else {\n path.push(right);\n apex = right;\n leftIndex = rightIndex = rightIndex;\n left = right = apex;\n i = rightIndex;\n continue;\n }\n }\n }\n\n path.push(end);\n\n return path;\n }\n\n /**\n * @zh 计算三角形面积的两倍(用于判断点的相对位置)\n * @en Calculate twice the triangle area (for point relative position)\n */\n private triArea2(a: IPoint, b: IPoint, c: IPoint): number {\n return (c.x - a.x) * (b.y - a.y) - (b.x - a.x) * (c.y - a.y);\n }\n\n /**\n * @zh 计算路径总长度\n * @en Calculate total path length\n */\n private calculatePathLength(path: readonly IPoint[]): number {\n let length = 0;\n\n for (let i = 1; i < path.length; i++) {\n length += euclideanDistance(path[i - 1], path[i]);\n }\n\n return length;\n }\n\n /**\n * @zh 清空导航网格\n * @en Clear navigation mesh\n */\n clear(): void {\n this.polygons.clear();\n this.nodes.clear();\n this.nextId = 0;\n }\n\n /**\n * @zh 获取所有多边形\n * @en Get all polygons\n */\n getPolygons(): INavPolygon[] {\n return Array.from(this.polygons.values());\n }\n\n /**\n * @zh 获取多边形数量\n * @en Get polygon count\n */\n get polygonCount(): number {\n return this.polygons.size;\n }\n}\n\n// =============================================================================\n// 工厂函数 | Factory Function\n// =============================================================================\n\n/**\n * @zh 创建导航网格\n * @en Create navigation mesh\n */\nexport function createNavMesh(): NavMesh {\n return new NavMesh();\n}\n","/**\n * @zh 路径平滑算法\n * @en Path Smoothing Algorithms\n */\n\nimport type {\n IPathfindingMap,\n IPathSmoother,\n IPoint\n} from '../core/IPathfinding';\nimport { createPoint } from '../core/IPathfinding';\n\n// =============================================================================\n// 视线检测 | Line of Sight\n// =============================================================================\n\n/**\n * @zh 使用 Bresenham 算法检测视线\n * @en Line of sight check using Bresenham algorithm\n */\nexport function bresenhamLineOfSight(\n x1: number,\n y1: number,\n x2: number,\n y2: number,\n map: IPathfindingMap\n): boolean {\n // Round to grid coordinates\n let ix1 = Math.floor(x1);\n let iy1 = Math.floor(y1);\n const ix2 = Math.floor(x2);\n const iy2 = Math.floor(y2);\n\n const dx = Math.abs(ix2 - ix1);\n const dy = Math.abs(iy2 - iy1);\n\n const sx = ix1 < ix2 ? 1 : -1;\n const sy = iy1 < iy2 ? 1 : -1;\n\n let err = dx - dy;\n\n while (true) {\n if (!map.isWalkable(ix1, iy1)) {\n return false;\n }\n\n if (ix1 === ix2 && iy1 === iy2) {\n break;\n }\n\n const e2 = 2 * err;\n\n if (e2 > -dy) {\n err -= dy;\n ix1 += sx;\n }\n\n if (e2 < dx) {\n err += dx;\n iy1 += sy;\n }\n }\n\n return true;\n}\n\n/**\n * @zh 使用射线投射检测视线(更精确)\n * @en Line of sight check using ray casting (more precise)\n */\nexport function raycastLineOfSight(\n x1: number,\n y1: number,\n x2: number,\n y2: number,\n map: IPathfindingMap,\n stepSize: number = 0.5\n): boolean {\n const dx = x2 - x1;\n const dy = y2 - y1;\n const distance = Math.sqrt(dx * dx + dy * dy);\n\n if (distance === 0) {\n return map.isWalkable(Math.floor(x1), Math.floor(y1));\n }\n\n const steps = Math.ceil(distance / stepSize);\n const stepX = dx / steps;\n const stepY = dy / steps;\n\n let x = x1;\n let y = y1;\n\n for (let i = 0; i <= steps; i++) {\n if (!map.isWalkable(Math.floor(x), Math.floor(y))) {\n return false;\n }\n x += stepX;\n y += stepY;\n }\n\n return true;\n}\n\n// =============================================================================\n// 路径简化器(拐点移除)| Path Simplifier (Waypoint Removal)\n// =============================================================================\n\n/**\n * @zh 路径简化器 - 移除不必要的拐点\n * @en Path Simplifier - Removes unnecessary waypoints\n *\n * @zh 使用视线检测移除可以直接到达的中间点\n * @en Uses line of sight to remove intermediate points that can be reached directly\n */\nexport class LineOfSightSmoother implements IPathSmoother {\n private readonly lineOfSight: typeof bresenhamLineOfSight;\n\n constructor(lineOfSight: typeof bresenhamLineOfSight = bresenhamLineOfSight) {\n this.lineOfSight = lineOfSight;\n }\n\n smooth(path: readonly IPoint[], map: IPathfindingMap): IPoint[] {\n if (path.length <= 2) {\n return [...path];\n }\n\n const result: IPoint[] = [path[0]];\n let current = 0;\n\n while (current < path.length - 1) {\n // Find the furthest point we can see from current\n let furthest = current + 1;\n\n for (let i = path.length - 1; i > current + 1; i--) {\n if (this.lineOfSight(\n path[current].x,\n path[current].y,\n path[i].x,\n path[i].y,\n map\n )) {\n furthest = i;\n break;\n }\n }\n\n result.push(path[furthest]);\n current = furthest;\n }\n\n return result;\n }\n}\n\n// =============================================================================\n// 曲线平滑器 | Curve Smoother\n// =============================================================================\n\n/**\n * @zh Catmull-Rom 样条曲线平滑\n * @en Catmull-Rom spline smoothing\n */\nexport class CatmullRomSmoother implements IPathSmoother {\n private readonly segments: number;\n private readonly tension: number;\n\n /**\n * @param segments - @zh 每段之间的插值点数 @en Number of interpolation points per segment\n * @param tension - @zh 张力 (0-1) @en Tension (0-1)\n */\n constructor(segments: number = 5, tension: number = 0.5) {\n this.segments = segments;\n this.tension = tension;\n }\n\n smooth(path: readonly IPoint[], _map: IPathfindingMap): IPoint[] {\n if (path.length <= 2) {\n return [...path];\n }\n\n const result: IPoint[] = [];\n\n // Add phantom points at the ends\n const points = [\n path[0],\n ...path,\n path[path.length - 1]\n ];\n\n for (let i = 1; i < points.length - 2; i++) {\n const p0 = points[i - 1];\n const p1 = points[i];\n const p2 = points[i + 1];\n const p3 = points[i + 2];\n\n for (let j = 0; j < this.segments; j++) {\n const t = j / this.segments;\n const point = this.interpolate(p0, p1, p2, p3, t);\n result.push(point);\n }\n }\n\n // Add final point\n result.push(path[path.length - 1]);\n\n return result;\n }\n\n /**\n * @zh Catmull-Rom 插值\n * @en Catmull-Rom interpolation\n */\n private interpolate(\n p0: IPoint,\n p1: IPoint,\n p2: IPoint,\n p3: IPoint,\n t: number\n ): IPoint {\n const t2 = t * t;\n const t3 = t2 * t;\n\n const tension = this.tension;\n\n const x =\n 0.5 *\n ((2 * p1.x) +\n (-p0.x + p2.x) * t * tension +\n (2 * p0.x - 5 * p1.x + 4 * p2.x - p3.x) * t2 * tension +\n (-p0.x + 3 * p1.x - 3 * p2.x + p3.x) * t3 * tension);\n\n const y =\n 0.5 *\n ((2 * p1.y) +\n (-p0.y + p2.y) * t * tension +\n (2 * p0.y - 5 * p1.y + 4 * p2.y - p3.y) * t2 * tension +\n (-p0.y + 3 * p1.y - 3 * p2.y + p3.y) * t3 * tension);\n\n return createPoint(x, y);\n }\n}\n\n// =============================================================================\n// 组合平滑器 | Combined Smoother\n// =============================================================================\n\n/**\n * @zh 组合路径平滑器\n * @en Combined path smoother\n *\n * @zh 先简化路径,再用曲线平滑\n * @en First simplify path, then smooth with curves\n */\nexport class CombinedSmoother implements IPathSmoother {\n private readonly simplifier: LineOfSightSmoother;\n private readonly curveSmoother: CatmullRomSmoother;\n\n constructor(curveSegments: number = 5, tension: number = 0.5) {\n this.simplifier = new LineOfSightSmoother();\n this.curveSmoother = new CatmullRomSmoother(curveSegments, tension);\n }\n\n smooth(path: readonly IPoint[], map: IPathfindingMap): IPoint[] {\n // First simplify\n const simplified = this.simplifier.smooth(path, map);\n\n // Then curve smooth\n return this.curveSmoother.smooth(simplified, map);\n }\n}\n\n// =============================================================================\n// 工厂函数 | Factory Functions\n// =============================================================================\n\n/**\n * @zh 创建视线平滑器\n * @en Create line of sight smoother\n */\nexport function createLineOfSightSmoother(\n lineOfSight?: typeof bresenhamLineOfSight\n): LineOfSightSmoother {\n return new LineOfSightSmoother(lineOfSight);\n}\n\n/**\n * @zh 创建曲线平滑器\n * @en Create curve smoother\n */\nexport function createCatmullRomSmoother(\n segments?: number,\n tension?: number\n): CatmullRomSmoother {\n return new CatmullRomSmoother(segments, tension);\n}\n\n/**\n * @zh 创建组合平滑器\n * @en Create combined smoother\n */\nexport function createCombinedSmoother(\n curveSegments?: number,\n tension?: number\n): CombinedSmoother {\n return new CombinedSmoother(curveSegments, tension);\n}\n","/**\n * @zh 寻路系统蓝图节点\n * @en Pathfinding System Blueprint Nodes\n */\n\nimport type { BlueprintNodeTemplate, BlueprintNode, INodeExecutor, ExecutionResult } from '@esengine/blueprint';\nimport type { IPathResult, IPoint } from '../core/IPathfinding';\n\n// =============================================================================\n// 执行上下文接口 | Execution Context Interface\n// =============================================================================\n\ninterface PathfindingContext {\n evaluateInput(nodeId: string, pinName: string, defaultValue?: unknown): unknown;\n setOutputs(nodeId: string, outputs: Record<string, unknown>): void;\n findPath(startX: number, startY: number, endX: number, endY: number): IPathResult;\n findPathSmooth(startX: number, startY: number, endX: number, endY: number): IPathResult;\n isWalkable(x: number, y: number): boolean;\n getPathDistance(path: IPoint[]): number;\n}\n\n// =============================================================================\n// FindPath 节点 | FindPath Node\n// =============================================================================\n\nexport const FindPathTemplate: BlueprintNodeTemplate = {\n type: 'FindPath',\n title: 'Find Path',\n category: 'custom',\n description: 'Find path from start to end / 从起点到终点寻路',\n keywords: ['path', 'pathfinding', 'astar', 'navigate', 'route'],\n menuPath: ['Pathfinding', 'Find Path'],\n inputs: [\n { name: 'exec', displayName: '', type: 'exec' },\n { name: 'startX', displayName: 'Start X', type: 'float' },\n { name: 'startY', displayName: 'Start Y', type: 'float' },\n { name: 'endX', displayName: 'End X', type: 'float' },\n { name: 'endY', displayName: 'End Y', type: 'float' }\n ],\n outputs: [\n { name: 'exec', displayName: '', type: 'exec' },\n { name: 'found', displayName: 'Found', type: 'bool' },\n { name: 'path', displayName: 'Path', type: 'array' },\n { name: 'cost', displayName: 'Cost', type: 'float' }\n ],\n color: '#4caf50'\n};\n\nexport class FindPathExecutor implements INodeExecutor {\n execute(node: BlueprintNode, context: unknown): ExecutionResult {\n const ctx = context as PathfindingContext;\n const startX = ctx.evaluateInput(node.id, 'startX', 0) as number;\n const startY = ctx.evaluateInput(node.id, 'startY', 0) as number;\n const endX = ctx.evaluateInput(node.id, 'endX', 0) as number;\n const endY = ctx.evaluateInput(node.id, 'endY', 0) as number;\n\n const result = ctx.findPath(startX, startY, endX, endY);\n\n return {\n outputs: {\n found: result.found,\n path: result.path,\n cost: result.cost\n },\n nextExec: 'exec'\n };\n }\n}\n\n// =============================================================================\n// FindPathSmooth 节点 | FindPathSmooth Node\n// =============================================================================\n\nexport const FindPathSmoothTemplate: BlueprintNodeTemplate = {\n type: 'FindPathSmooth',\n title: 'Find Path (Smooth)',\n category: 'custom',\n description: 'Find path with smoothing / 寻路并平滑路径',\n keywords: ['path', 'pathfinding', 'smooth', 'navigate'],\n menuPath: ['Pathfinding', 'Find Path (Smooth)'],\n inputs: [\n { name: 'exec', displayName: '', type: 'exec' },\n { name: 'startX', displayName: 'Start X', type: 'float' },\n { name: 'startY', displayName: 'Start Y', type: 'float' },\n { name: 'endX', displayName: 'End X', type: 'float' },\n { name: 'endY', displayName: 'End Y', type: 'float' }\n ],\n outputs: [\n { name: 'exec', displayName: '', type: 'exec' },\n { name: 'found', displayName: 'Found', type: 'bool' },\n { name: 'path', displayName: 'Path', type: 'array' },\n { name: 'cost', displayName: 'Cost', type: 'float' }\n ],\n color: '#4caf50'\n};\n\nexport class FindPathSmoothExecutor implements INodeExecutor {\n execute(node: BlueprintNode, context: unknown): ExecutionResult {\n const ctx = context as PathfindingContext;\n const startX = ctx.evaluateInput(node.id, 'startX', 0) as number;\n const startY = ctx.evaluateInput(node.id, 'startY', 0) as number;\n const endX = ctx.evaluateInput(node.id, 'endX', 0) as number;\n const endY = ctx.evaluateInput(node.id, 'endY', 0) as number;\n\n const result = ctx.findPathSmooth(startX, startY, endX, endY);\n\n return {\n outputs: {\n found: result.found,\n path: result.path,\n cost: result.cost\n },\n nextExec: 'exec'\n };\n }\n}\n\n// =============================================================================\n// IsWalkable 节点 | IsWalkable Node\n// =============================================================================\n\nexport const IsWalkableTemplate: BlueprintNodeTemplate = {\n type: 'IsWalkable',\n title: 'Is Walkable',\n category: 'custom',\n description: 'Check if position is walkable / 检查位置是否可通行',\n keywords: ['walkable', 'obstacle', 'blocked', 'terrain'],\n menuPath: ['Pathfinding', 'Is Walkable'],\n isPure: true,\n inputs: [\n { name: 'x', displayName: 'X', type: 'float' },\n { name: 'y', displayName: 'Y', type: 'float' }\n ],\n outputs: [\n { name: 'walkable', displayName: 'Walkable', type: 'bool' }\n ],\n color: '#4caf50'\n};\n\nexport class IsWalkableExecutor implements INodeExecutor {\n execute(node: BlueprintNode, context: unknown): ExecutionResult {\n const ctx = context as PathfindingContext;\n const x = ctx.evaluateInput(node.id, 'x', 0) as number;\n const y = ctx.evaluateInput(node.id, 'y', 0) as number;\n\n const walkable = ctx.isWalkable(x, y);\n\n return { outputs: { walkable } };\n }\n}\n\n// =============================================================================\n// GetPathLength 节点 | GetPathLength Node\n// =============================================================================\n\nexport const GetPathLengthTemplate: BlueprintNodeTemplate = {\n type: 'GetPathLength',\n title: 'Get Path Length',\n category: 'custom',\n description: 'Get the number of points in path / 获取路径点数量',\n keywords: ['path', 'length', 'count', 'waypoints'],\n menuPath: ['Pathfinding', 'Get Path Length'],\n isPure: true,\n inputs: [\n { name: 'path', displayName: 'Path', type: 'array' }\n ],\n outputs: [\n { name: 'length', displayName: 'Length', type: 'int' }\n ],\n color: '#4caf50'\n};\n\nexport class GetPathLengthExecutor implements INodeExecutor {\n execute(node: BlueprintNode, context: unknown): ExecutionResult {\n const ctx = context as PathfindingContext;\n const path = ctx.evaluateInput(node.id, 'path', []) as IPoint[];\n\n return { outputs: { length: path.length } };\n }\n}\n\n// =============================================================================\n// GetPathDistance 节点 | GetPathDistance Node\n// =============================================================================\n\nexport const GetPathDistanceTemplate: BlueprintNodeTemplate = {\n type: 'GetPathDistance',\n title: 'Get Path Distance',\n category: 'custom',\n description: 'Get total path distance / 获取路径总距离',\n keywords: ['path', 'distance', 'length', 'travel'],\n menuPath: ['Pathfinding', 'Get Path Distance'],\n isPure: true,\n inputs: [\n { name: 'path', displayName: 'Path', type: 'array' }\n ],\n outputs: [\n { name: 'distance', displayName: 'Distance', type: 'float' }\n ],\n color: '#4caf50'\n};\n\nexport class GetPathDistanceExecutor implements INodeExecutor {\n execute(node: BlueprintNode, context: unknown): ExecutionResult {\n const ctx = context as PathfindingContext;\n const path = ctx.evaluateInput(node.id, 'path', []) as IPoint[];\n\n const distance = ctx.getPathDistance(path);\n\n return { outputs: { distance } };\n }\n}\n\n// =============================================================================\n// GetPathPoint 节点 | GetPathPoint Node\n// =============================================================================\n\nexport const GetPathPointTemplate: BlueprintNodeTemplate = {\n type: 'GetPathPoint',\n title: 'Get Path Point',\n category: 'custom',\n description: 'Get point at index in path / 获取路径中指定索引的点',\n keywords: ['path', 'point', 'waypoint', 'index'],\n menuPath: ['Pathfinding', 'Get Path Point'],\n isPure: true,\n inputs: [\n { name: 'path', displayName: 'Path', type: 'array' },\n { name: 'index', displayName: 'Index', type: 'int' }\n ],\n outputs: [\n { name: 'x', displayName: 'X', type: 'float' },\n { name: 'y', displayName: 'Y', type: 'float' },\n { name: 'valid', displayName: 'Valid', type: 'bool' }\n ],\n color: '#4caf50'\n};\n\nexport class GetPathPointExecutor implements INodeExecutor {\n execute(node: BlueprintNode, context: unknown): ExecutionResult {\n const ctx = context as PathfindingContext;\n const path = ctx.evaluateInput(node.id, 'path', []) as IPoint[];\n const index = ctx.evaluateInput(node.id, 'index', 0) as number;\n\n if (index >= 0 && index < path.length) {\n return {\n outputs: {\n x: path[index].x,\n y: path[index].y,\n valid: true\n }\n };\n }\n\n return {\n outputs: {\n x: 0,\n y: 0,\n valid: false\n }\n };\n }\n}\n\n// =============================================================================\n// MoveAlongPath 节点 | MoveAlongPath Node\n// =============================================================================\n\nexport const MoveAlongPathTemplate: BlueprintNodeTemplate = {\n type: 'MoveAlongPath',\n title: 'Move Along Path',\n category: 'custom',\n description: 'Get position along path at progress / 获取路径上指定进度的位置',\n keywords: ['path', 'move', 'lerp', 'progress', 'interpolate'],\n menuPath: ['Pathfinding', 'Move Along Path'],\n isPure: true,\n inputs: [\n { name: 'path', displayName: 'Path', type: 'array' },\n { name: 'progress', displayName: 'Progress (0-1)', type: 'float' }\n ],\n outputs: [\n { name: 'x', displayName: 'X', type: 'float' },\n { name: 'y', displayName: 'Y', type: 'float' }\n ],\n color: '#4caf50'\n};\n\nexport class MoveAlongPathExecutor implements INodeExecutor {\n execute(node: BlueprintNode, context: unknown): ExecutionResult {\n const ctx = context as PathfindingContext;\n const path = ctx.evaluateInput(node.id, 'path', []) as IPoint[];\n let progress = ctx.evaluateInput(node.id, 'progress', 0) as number;\n\n if (path.length === 0) {\n return { outputs: { x: 0, y: 0 } };\n }\n\n if (path.length === 1) {\n return { outputs: { x: path[0].x, y: path[0].y } };\n }\n\n // Clamp progress\n progress = Math.max(0, Math.min(1, progress));\n\n // Calculate total distance\n let totalDistance = 0;\n const segmentDistances: number[] = [];\n\n for (let i = 1; i < path.length; i++) {\n const dx = path[i].x - path[i - 1].x;\n const dy = path[i].y - path[i - 1].y;\n const dist = Math.sqrt(dx * dx + dy * dy);\n segmentDistances.push(dist);\n totalDistance += dist;\n }\n\n if (totalDistance === 0) {\n return { outputs: { x: path[0].x, y: path[0].y } };\n }\n\n // Find the segment and position\n const targetDistance = progress * totalDistance;\n let accumulatedDistance = 0;\n\n for (let i = 0; i < segmentDistances.length; i++) {\n const segmentDist = segmentDistances[i];\n\n if (accumulatedDistance + segmentDist >= targetDistance) {\n const segmentProgress = (targetDistance - accumulatedDistance) / segmentDist;\n const x = path[i].x + (path[i + 1].x - path[i].x) * segmentProgress;\n const y = path[i].y + (path[i + 1].y - path[i].y) * segmentProgress;\n return { outputs: { x, y } };\n }\n\n accumulatedDistance += segmentDist;\n }\n\n // Return last point\n const last = path[path.length - 1];\n return { outputs: { x: last.x, y: last.y } };\n }\n}\n\n// =============================================================================\n// HasLineOfSight 节点 | HasLineOfSight Node\n// =============================================================================\n\nexport const HasLineOfSightTemplate: BlueprintNodeTemplate = {\n type: 'HasLineOfSight',\n title: 'Has Line of Sight',\n category: 'custom',\n description: 'Check if there is a clear line between two points / 检查两点之间是否有清晰的视线',\n keywords: ['line', 'sight', 'los', 'visibility', 'raycast'],\n menuPath: ['Pathfinding', 'Has Line of Sight'],\n isPure: true,\n inputs: [\n { name: 'startX', displayName: 'Start X', type: 'float' },\n { name: 'startY', displayName: 'Start Y', type: 'float' },\n { name: 'endX', displayName: 'End X', type: 'float' },\n { name: 'endY', displayName: 'End Y', type: 'float' }\n ],\n outputs: [\n { name: 'hasLOS', displayName: 'Has LOS', type: 'bool' }\n ],\n color: '#4caf50'\n};\n\nexport class HasLineOfSightExecutor implements INodeExecutor {\n execute(node: BlueprintNode, context: unknown): ExecutionResult {\n const ctx = context as PathfindingContext & {\n hasLineOfSight?(x1: number, y1: number, x2: number, y2: number): boolean;\n };\n\n const startX = ctx.evaluateInput(node.id, 'startX', 0) as number;\n const startY = ctx.evaluateInput(node.id, 'startY', 0) as number;\n const endX = ctx.evaluateInput(node.id, 'endX', 0) as number;\n const endY = ctx.evaluateInput(node.id, 'endY', 0) as number;\n\n const hasLOS = ctx.hasLineOfSight?.(startX, startY, endX, endY) ?? true;\n\n return { outputs: { hasLOS } };\n }\n}\n\n// =============================================================================\n// 节点定义集合 | Node Definition Collection\n// =============================================================================\n\nexport const PathfindingNodeDefinitions = {\n templates: [\n FindPathTemplate,\n FindPathSmoothTemplate,\n IsWalkableTemplate,\n GetPathLengthTemplate,\n GetPathDistanceTemplate,\n GetPathPointTemplate,\n MoveAlongPathTemplate,\n HasLineOfSightTemplate\n ],\n executors: new Map<string, INodeExecutor>([\n ['FindPath', new FindPathExecutor()],\n ['FindPathSmooth', new FindPathSmoothExecutor()],\n ['IsWalkable', new IsWalkableExecutor()],\n ['GetPathLength', new GetPathLengthExecutor()],\n ['GetPathDistance', new GetPathDistanceExecutor()],\n ['GetPathPoint', new GetPathPointExecutor()],\n ['MoveAlongPath', new MoveAlongPathExecutor()],\n ['HasLineOfSight', new HasLineOfSightExecutor()]\n ])\n};\n"],"mappings":"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","names":["createPoint","x","y","EMPTY_PATH_RESULT","found","path","cost","nodesSearched","manhattanDistance","a","b","Math","abs","euclideanDistance","dx","dy","sqrt","chebyshevDistance","max","octileDistance","D","D2","SQRT2","min","DEFAULT_PATHFINDING_OPTIONS","maxNodes","heuristicWeight","allowDiagonal","avoidCorners","BinaryHeap","compare","heap","size","length","isEmpty","push","item","bubbleUp","pop","undefined","result","last","sinkDown","peek","update","index","indexOf","contains","clear","parentIndex","Math","floor","parent","leftIndex","rightIndex","smallest","AStarPathfinder","map","nodeCache","Map","openList","BinaryHeap","a","b","f","findPath","startX","startY","endX","endY","options","opts","DEFAULT_PATHFINDING_OPTIONS","clear","startNode","getNodeAt","endNode","EMPTY_PATH_RESULT","walkable","id","found","path","position","cost","nodesSearched","start","getOrCreateAStarNode","g","h","heuristic","heuristicWeight","opened","push","endPosition","isEmpty","maxNodes","current","pop","closed","node","buildPath","neighbors","getNeighbors","neighborNode","neighbor","movementCost","getMovementCost","tentativeG","parent","update","astarNode","get","Infinity","set","unshift","createAStarPathfinder","GridNode","x","y","walkable","cost","id","position","createPoint","DIRECTIONS_4","dx","dy","DIRECTIONS_8","DEFAULT_GRID_OPTIONS","allowDiagonal","diagonalCost","Math","SQRT2","avoidCorners","heuristic","octileDistance","GridMap","width","height","options","nodes","createNodes","getNodeAt","isInBounds","isWalkable","node","setWalkable","setCost","getNeighbors","neighbors","directions","i","length","dir","nx","ny","neighbor","horizontal","vertical","push","a","b","getMovementCost","from","to","abs","loadFromArray","data","min","loadFromString","str","lines","trim","split","line","toString","result","reset","setRectWalkable","createGridMap","NavMeshNode","polygon","id","position","cost","walkable","center","NavMesh","polygons","Map","nodes","nextId","addPolygon","vertices","neighbors","calculateCenter","portals","set","setConnection","polyA","polyB","portal","polygonA","get","polygonB","neighborsA","portalsA","includes","push","reversePortal","left","right","neighborsB","portalsB","build","polygonList","Array","from","values","i","length","j","sharedEdge","findSharedEdge","verticesA","verticesB","epsilon","a1","a2","b1","b2","match1","Math","abs","x","y","match2","v","createPoint","findPolygonAt","isPointInPolygon","inside","n","xi","yi","xj","yj","getNodeAt","getNeighbors","node","navNode","neighborId","neighbor","heuristic","a","b","euclideanDistance","getMovementCost","to","isWalkable","findPath","startX","startY","endX","endY","options","opts","DEFAULT_PATHFINDING_OPTIONS","startPolygon","endPolygon","EMPTY_PATH_RESULT","found","path","nodesSearched","polygonPath","findPolygonPath","start","end","pointPath","funnelPath","calculatePathLength","openList","BinaryHeap","f","closed","Set","states","startState","g","heuristicWeight","parent","isEmpty","maxNodes","current","pop","state","unshift","add","has","neighborPolygon","neighborState","update","apex","leftIndex","rightIndex","nextLeft","nextRight","triArea2","c","clear","getPolygons","polygonCount","size","createNavMesh","bresenhamLineOfSight","x1","y1","x2","y2","map","ix1","Math","floor","iy1","ix2","iy2","dx","abs","dy","sx","sy","err","isWalkable","e2","raycastLineOfSight","stepSize","distance","sqrt","steps","ceil","stepX","stepY","x","y","i","LineOfSightSmoother","lineOfSight","smooth","path","length","result","current","furthest","push","CatmullRomSmoother","segments","tension","_map","points","p0","p1","p2","p3","j","t","point","interpolate","t2","t3","createPoint","CombinedSmoother","curveSegments","simplifier","curveSmoother","simplified","createLineOfSightSmoother","createCatmullRomSmoother","createCombinedSmoother","FindPathTemplate","type","title","category","description","keywords","menuPath","inputs","name","displayName","outputs","color","FindPathExecutor","execute","node","context","ctx","startX","evaluateInput","id","startY","endX","endY","result","findPath","found","path","cost","nextExec","FindPathSmoothTemplate","FindPathSmoothExecutor","findPathSmooth","IsWalkableTemplate","isPure","IsWalkableExecutor","x","y","walkable","isWalkable","GetPathLengthTemplate","GetPathLengthExecutor","length","GetPathDistanceTemplate","GetPathDistanceExecutor","distance","getPathDistance","GetPathPointTemplate","GetPathPointExecutor","index","valid","MoveAlongPathTemplate","MoveAlongPathExecutor","progress","Math","max","min","totalDistance","segmentDistances","i","dx","dy","dist","sqrt","push","targetDistance","accumulatedDistance","segmentDist","segmentProgress","last","HasLineOfSightTemplate","HasLineOfSightExecutor","hasLOS","hasLineOfSight","PathfindingNodeDefinitions","templates","executors","Map"]}
|
package/module.json
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "pathfinding",
|
|
3
|
+
"name": "@esengine/pathfinding",
|
|
4
|
+
"globalKey": "pathfinding",
|
|
5
|
+
"displayName": "Pathfinding",
|
|
6
|
+
"description": "寻路系统,提供 A*、网格地图、导航网格和路径平滑 | Pathfinding system with A*, grid map, NavMesh and path smoothing",
|
|
7
|
+
"version": "1.0.0",
|
|
8
|
+
"category": "AI",
|
|
9
|
+
"icon": "Route",
|
|
10
|
+
"tags": ["pathfinding", "navigation", "astar", "navmesh", "ai"],
|
|
11
|
+
"isCore": false,
|
|
12
|
+
"defaultEnabled": true,
|
|
13
|
+
"isEngineModule": true,
|
|
14
|
+
"canContainContent": false,
|
|
15
|
+
"platforms": ["web", "desktop", "mobile"],
|
|
16
|
+
"dependencies": ["core", "math", "blueprint"],
|
|
17
|
+
"exports": {
|
|
18
|
+
"components": ["PathfindingAgentComponent"],
|
|
19
|
+
"systems": ["PathfindingSystem"]
|
|
20
|
+
},
|
|
21
|
+
"requiresWasm": false,
|
|
22
|
+
"outputPath": "dist/index.js",
|
|
23
|
+
"pluginExport": "PathfindingPlugin"
|
|
24
|
+
}
|
package/package.json
CHANGED
|
@@ -1,70 +1,61 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@esengine/pathfinding",
|
|
3
|
-
"version": "
|
|
4
|
-
"description": "
|
|
5
|
-
"
|
|
6
|
-
"
|
|
7
|
-
"
|
|
8
|
-
"
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
"
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
"
|
|
17
|
-
"
|
|
18
|
-
],
|
|
19
|
-
"
|
|
20
|
-
"
|
|
21
|
-
"
|
|
22
|
-
"
|
|
23
|
-
"
|
|
24
|
-
"
|
|
25
|
-
"
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
"
|
|
29
|
-
"
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
"
|
|
38
|
-
"
|
|
39
|
-
"
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
"
|
|
43
|
-
"
|
|
44
|
-
"
|
|
45
|
-
"
|
|
46
|
-
"
|
|
47
|
-
"
|
|
48
|
-
"
|
|
49
|
-
"
|
|
50
|
-
"
|
|
51
|
-
"
|
|
52
|
-
|
|
53
|
-
"
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
"
|
|
57
|
-
"
|
|
58
|
-
"
|
|
59
|
-
"
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
"jest": "^29.7.0",
|
|
63
|
-
"ts-jest": "^29.1.2",
|
|
64
|
-
"rimraf": "^5.0.0",
|
|
65
|
-
"rollup": "^4.42.0",
|
|
66
|
-
"rollup-plugin-dts": "^6.2.1",
|
|
67
|
-
"typedoc": "^0.25.13",
|
|
68
|
-
"typescript": "^5.4.5"
|
|
69
|
-
}
|
|
70
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "@esengine/pathfinding",
|
|
3
|
+
"version": "2.0.0",
|
|
4
|
+
"description": "寻路系统 | Pathfinding System - A*, Grid, NavMesh",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"module": "./dist/index.js",
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"import": "./dist/index.js",
|
|
12
|
+
"types": "./dist/index.d.ts"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"files": [
|
|
16
|
+
"dist",
|
|
17
|
+
"module.json"
|
|
18
|
+
],
|
|
19
|
+
"devDependencies": {
|
|
20
|
+
"tsup": "^8.0.0",
|
|
21
|
+
"typescript": "^5.8.0",
|
|
22
|
+
"vitest": "^2.1.9",
|
|
23
|
+
"@esengine/ecs-framework": "2.5.0",
|
|
24
|
+
"@esengine/ecs-framework-math": "1.0.5",
|
|
25
|
+
"@esengine/blueprint": "2.0.0"
|
|
26
|
+
},
|
|
27
|
+
"peerDependencies": {
|
|
28
|
+
"@esengine/ecs-framework": "2.5.0",
|
|
29
|
+
"@esengine/ecs-framework-math": "1.0.5",
|
|
30
|
+
"@esengine/blueprint": "2.0.0"
|
|
31
|
+
},
|
|
32
|
+
"publishConfig": {
|
|
33
|
+
"access": "public",
|
|
34
|
+
"registry": "https://registry.npmjs.org/"
|
|
35
|
+
},
|
|
36
|
+
"repository": {
|
|
37
|
+
"type": "git",
|
|
38
|
+
"url": "https://github.com/esengine/esengine.git",
|
|
39
|
+
"directory": "packages/framework/pathfinding"
|
|
40
|
+
},
|
|
41
|
+
"keywords": [
|
|
42
|
+
"ecs",
|
|
43
|
+
"pathfinding",
|
|
44
|
+
"astar",
|
|
45
|
+
"a-star",
|
|
46
|
+
"navmesh",
|
|
47
|
+
"navigation",
|
|
48
|
+
"game-ai",
|
|
49
|
+
"cocos",
|
|
50
|
+
"laya",
|
|
51
|
+
"esengine"
|
|
52
|
+
],
|
|
53
|
+
"scripts": {
|
|
54
|
+
"build": "tsup",
|
|
55
|
+
"build:watch": "tsup --watch",
|
|
56
|
+
"type-check": "tsc --noEmit",
|
|
57
|
+
"test": "vitest run",
|
|
58
|
+
"test:watch": "vitest",
|
|
59
|
+
"clean": "rimraf dist"
|
|
60
|
+
}
|
|
61
|
+
}
|