/** * 基本静态网格图与A*一起使用 * 将walls添加到walls HashSet,并将加权节点添加到weightedNodes */ class AstarGridGraph implements IAstarGraph { public dirs: Vector2[] = [ new Vector2(1, 0), new Vector2(0, -1), new Vector2(-1, 0), new Vector2(0, 1) ]; public walls: Vector2[] = []; public weightedNodes: Vector2[] = []; public defaultWeight: number = 1; public weightedNodeWeight = 5; private _width; private _height; private _neighbors: Vector2[] = new Array(4); constructor(width: number, height: number){ this._width = width; this._height = height; } /** * 确保节点在网格图的边界内 * @param node */ public isNodeInBounds(node: Vector2): boolean { return 0 <= node.x && node.x < this._width && 0 <= node.y && node.y < this._height; } /** * 检查节点是否可以通过。walls是不可逾越的。 * @param node */ public isNodePassable(node: Vector2): boolean { return !this.walls.firstOrDefault(wall => JSON.stringify(wall) == JSON.stringify(node)); } /** * 调用AStarPathfinder.search的快捷方式 * @param start * @param goal */ public search(start: Vector2, goal: Vector2){ return AStarPathfinder.search(this, start, goal); } public getNeighbors(node: Vector2): Vector2[] { this._neighbors.length = 0; this.dirs.forEach(dir => { let next = new Vector2(node.x + dir.x, node.y + dir.y); if (this.isNodeInBounds(next) && this.isNodePassable(next)) this._neighbors.push(next); }); return this._neighbors; } public cost(from: Vector2, to: Vector2): number { return this.weightedNodes.find((p)=> JSON.stringify(p) == JSON.stringify(to)) ? this.weightedNodeWeight : this.defaultWeight; } public heuristic(node: Vector2, goal: Vector2) { return Math.abs(node.x - goal.x) + Math.abs(node.y - goal.y); } }