UNPKG

pathfinding

Version:

Comprehensive pathfinding library for grid based games

116 lines (98 loc) 3.68 kB
var Util = require('../core/Util'); var DiagonalMovement = require('../core/DiagonalMovement'); /** * Bi-directional Breadth-First-Search path finder. * @constructor * @param {object} opt * @param {boolean} opt.allowDiagonal Whether diagonal movement is allowed. * Deprecated, use diagonalMovement instead. * @param {boolean} opt.dontCrossCorners Disallow diagonal movement touching * block corners. Deprecated, use diagonalMovement instead. * @param {DiagonalMovement} opt.diagonalMovement Allowed diagonal movement. */ function BiBreadthFirstFinder(opt) { opt = opt || {}; this.allowDiagonal = opt.allowDiagonal; this.dontCrossCorners = opt.dontCrossCorners; this.diagonalMovement = opt.diagonalMovement; if (!this.diagonalMovement) { if (!this.allowDiagonal) { this.diagonalMovement = DiagonalMovement.Never; } else { if (this.dontCrossCorners) { this.diagonalMovement = DiagonalMovement.OnlyWhenNoObstacles; } else { this.diagonalMovement = DiagonalMovement.IfAtMostOneObstacle; } } } } /** * Find and return the the path. * @return {Array<Array<number>>} The path, including both start and * end positions. */ BiBreadthFirstFinder.prototype.findPath = function(startX, startY, endX, endY, grid) { var startNode = grid.getNodeAt(startX, startY), endNode = grid.getNodeAt(endX, endY), startOpenList = [], endOpenList = [], neighbors, neighbor, node, diagonalMovement = this.diagonalMovement, BY_START = 0, BY_END = 1, i, l; // push the start and end nodes into the queues startOpenList.push(startNode); startNode.opened = true; startNode.by = BY_START; endOpenList.push(endNode); endNode.opened = true; endNode.by = BY_END; // while both the queues are not empty while (startOpenList.length && endOpenList.length) { // expand start open list node = startOpenList.shift(); node.closed = true; neighbors = grid.getNeighbors(node, diagonalMovement); for (i = 0, l = neighbors.length; i < l; ++i) { neighbor = neighbors[i]; if (neighbor.closed) { continue; } if (neighbor.opened) { // if this node has been inspected by the reversed search, // then a path is found. if (neighbor.by === BY_END) { return Util.biBacktrace(node, neighbor); } continue; } startOpenList.push(neighbor); neighbor.parent = node; neighbor.opened = true; neighbor.by = BY_START; } // expand end open list node = endOpenList.shift(); node.closed = true; neighbors = grid.getNeighbors(node, diagonalMovement); for (i = 0, l = neighbors.length; i < l; ++i) { neighbor = neighbors[i]; if (neighbor.closed) { continue; } if (neighbor.opened) { if (neighbor.by === BY_START) { return Util.biBacktrace(neighbor, node); } continue; } endOpenList.push(neighbor); neighbor.parent = node; neighbor.opened = true; neighbor.by = BY_END; } } // fail to find the path return []; }; module.exports = BiBreadthFirstFinder;