Skip to content

Instantly share code, notes, and snippets.

@huckfinnaafb
Created January 2, 2012 02:44
Show Gist options
  • Save huckfinnaafb/1549077 to your computer and use it in GitHub Desktop.
Save huckfinnaafb/1549077 to your computer and use it in GitHub Desktop.
A*pathfinding implementation
/*
A* Pathfinding
*/
function Path(map, start, end) {
// Sets
var open = [],
closed = [];
// Create node for start
var begin;
begin = new Path.Node(start);
begin.gscore = 0;
begin.hscore = Path.heuristic(start, end);
begin.fscore = begin.gscore + begin.hscore;
// Open set begins with start node
Path.append(open, begin);
while (open.length) {
// Node with lowest fscore
var current = _.min(open, function (element) {
return element.fscore;
});
// Current node not at the end of path
if (!Vector.isEqual(current.vector, end)) {
// Swap sets
Path.remove(open, current);
Path.append(closed, current);
// Loop through immediate neighbors
var j, neighbors = Path.neighbors(current);
for (j = 0; j < neighbors.length; j += 1) {
// Shorthand
var neighbor = neighbors[j];
// Tentative move cost
var cost = current.gscore + 1; // 1 is guaranteed distance between two neighboring tiles for now
if (Path.isMember(open, neighbor) && cost < neighbor.gscore) {
Path.remove(open, neighbor);
}
if (Path.isMember(closed, neighbor) && cost < neighbor.gscore) {
Path.remove(closed, neighbor);
}
if (!Path.isMember(closed, neighbor) && !Path.isMember(open, neighbor)) {
Path.append(open, neighbor);
neighbor.hscore = Path.heuristic(neighbor.vector, end);
neighbor.gscore = cost;
neighbor.fscore = neighbor.gscore + neighbor.hscore;
neighbor.parent = current;
}
}
} else {
return Path.reconstruct(current);
}
}
}
Path.Node = function (vector) {
this.parent = undefined;
this.gscore = undefined;
this.hscore = undefined;
this.fscore = undefined; // gscore + hscore
this.vector = new Vector(vector.x, vector.y);
};
Path.append = function (collection, node) {
return collection.push(node);
};
Path.remove = function (collection, node) {
return collection.remove(Path.find(collection, node));
};
Path.find = function (collection, node) {
var i;
for (i = 0; i < collection.length; i += 1) {
if (Vector.isEqual(collection[i].vector, node.vector)) {
return i;
}
}
};
Path.neighbors = function (node) {
return [
new Path.Node(Vector.add(node.vector, Vector.N)),
new Path.Node(Vector.add(node.vector, Vector.W)),
new Path.Node(Vector.add(node.vector, Vector.S)),
new Path.Node(Vector.add(node.vector, Vector.E))
];
};
Path.heuristic = function (a, b) {
return Vector.distance(a, b);
};
Path.isMember = function (collection, node) {
return Path.find(collection, node) > -1;
};
Path.reconstruct = function (node) {
var path = [];
while (typeof node.parent !== 'undefined') {
path.push(node.vector);
node = node.parent;
}
return path.reverse();
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment