@esengine/pathfinding
Version:
寻路算法库,支持A*、广度优先等算法,适用于Cocos Creator、Laya等游戏引擎
82 lines (69 loc) • 2.73 kB
text/typescript
import { IVector2, Vector2Utils } from '../../../Types/IVector2';
import { IUnweightedGraph } from './IUnweightedGraph';
import { BreadthFirstPathfinder } from './BreadthFirstPathfinder';
/**
* 基本的无权网格图,用于广度优先搜索
* 适用于简单的网格寻路,如迷宫、推箱子等游戏
*/
export class UnweightedGridGraph implements IUnweightedGraph<IVector2> {
private static readonly CARDINAL_DIRS: IVector2[] = [
Vector2Utils.create(1, 0),
Vector2Utils.create(0, -1),
Vector2Utils.create(-1, 0),
Vector2Utils.create(0, 1)
];
private static readonly COMPASS_DIRS: IVector2[] = [
Vector2Utils.create(1, 0),
Vector2Utils.create(1, -1),
Vector2Utils.create(0, -1),
Vector2Utils.create(-1, -1),
Vector2Utils.create(-1, 0),
Vector2Utils.create(-1, 1),
Vector2Utils.create(0, 1),
Vector2Utils.create(1, 1),
];
public walls: IVector2[] = [];
private _width: number;
private _height: number;
private _dirs: IVector2[];
private _neighbors: IVector2[] = [];
constructor(width: number, height: number, allowDiagonalSearch: boolean = false) {
this._width = width;
this._height = height;
this._dirs = allowDiagonalSearch ? UnweightedGridGraph.COMPASS_DIRS : UnweightedGridGraph.CARDINAL_DIRS;
}
public isNodeInBounds(node: IVector2): boolean {
return 0 <= node.x && node.x < this._width && 0 <= node.y && node.y < this._height;
}
public isNodePassable(node: IVector2): boolean {
return !this.walls.find(wall => Vector2Utils.equals(wall, node));
}
public getNeighbors(node: IVector2): IVector2[] {
this._neighbors.length = 0;
for (const dir of this._dirs) {
const next = Vector2Utils.add(node, dir);
if (this.isNodeInBounds(next) && this.isNodePassable(next)) {
this._neighbors.push(next);
}
}
return this._neighbors;
}
/**
* 搜索路径的便捷方法
* @param start 起始位置
* @param goal 目标位置
* @returns 路径数组,如果没找到则返回空数组
*/
public searchPath(start: IVector2, goal: IVector2): IVector2[] {
return BreadthFirstPathfinder.searchPath(this, start, goal);
}
/**
* 检查是否存在路径
* @param start 起始位置
* @param goal 目标位置
* @returns 是否存在路径
*/
public hasPath(start: IVector2, goal: IVector2): boolean {
return BreadthFirstPathfinder.search(this, start, goal);
}
}