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