diff --git a/astar.js b/astar.js index 3c617c7..6945818 100644 --- a/astar.js +++ b/astar.js @@ -50,7 +50,8 @@ var astar = { graph.cleanDirty(); options = options || {}; var heuristic = options.heuristic || astar.heuristics.manhattan, - closest = options.closest || false; + closest = options.closest || false, + clearance = options.clearance || 1; var openHeap = getHeap(), closestNode = start; // set the start node to be the closest if required @@ -58,6 +59,7 @@ var astar = { start.h = heuristic(start, end); openHeap.push(start); + graph.markDirty(start); while(openHeap.size() > 0) { @@ -78,7 +80,7 @@ var astar = { for (var i = 0, il = neighbors.length; i < il; ++i) { var neighbor = neighbors[i]; - if (neighbor.closed || neighbor.isWall()) { + if (neighbor.closed || neighbor.isWall() || neighbor.clearanceLower(clearance)) { // Not a valid node to process, skip to next neighbor. continue; } @@ -164,7 +166,37 @@ function Graph(gridIn, options) { this.grid[x] = []; for (var y = 0, row = gridIn[x]; y < row.length; y++) { - var node = new GridNode(x, y, row[y]); + var clearance = 0; + if (row[y] !== 0) { // Tile isn't a wall, check clearance + // Limit loop through the map border + var clearanceMax = Math.min(gridIn.length - x, gridIn[x].length - y), + wallFound = false; + clearance = 1; + + while (!wallFound && clearance < clearanceMax) { + // Loop over x values + for (var i = 0 ; i <= clearance; i++) { + if (gridIn[parseInt(x) + i][parseInt(y) + clearance] === 0) { + wallFound = true; + break; + } + } + // Loop over y values + if (!wallFound) { + for (var j = 0 ; j <= clearance; j++) { + if (gridIn[parseInt(x) + clearance][parseInt(y) + j] === 0) { + wallFound = true; + break; + } + } + } + // No wall found, update clearance + if (!wallFound) { + clearance++; + } + } + } + var node = new GridNode(x, y, row[y], clearance); this.grid[x][y] = node; this.nodes.push(node); } @@ -256,10 +288,11 @@ Graph.prototype.toString = function() { return graphString.join("\n"); }; -function GridNode(x, y, weight) { +function GridNode(x, y, weight, clearance) { this.x = x; this.y = y; this.weight = weight; + this.clearance = clearance; } GridNode.prototype.toString = function() { @@ -278,6 +311,10 @@ GridNode.prototype.isWall = function() { return this.weight === 0; }; +GridNode.prototype.clearanceLower = function(clearance) { + return this.clearance < clearance; +}; + function BinaryHeap(scoreFunction){ this.content = []; this.scoreFunction = scoreFunction; diff --git a/test/tests.js b/test/tests.js index 02fcb22..85da8e5 100644 --- a/test/tests.js +++ b/test/tests.js @@ -212,6 +212,9 @@ test( "GPS Pathfinding", function() { // TODO: Determine the real distance between cities (from another data set) return this.GPS_distance(city); }; + CityNode.prototype.clearanceLower = function(clearance) { + return this.clearance < clearance; + }; var graph = new CityGraph(data, links);