Created
September 6, 2013 22:49
-
-
Save m1el/6471066 to your computer and use it in GitHub Desktop.
A* path finding implementation in js
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function astar_path(field, start, end) { | |
start = {x: start.x, y: start.y, cost: 0}; | |
var queue = [start], | |
visited = {}, | |
node; | |
visited[start.x + ':' + start.y] = start; | |
while ((node = queue.shift())) { | |
var neighbors = get_neighbors(field, node); | |
if (get_distance(node, end) === 0) { | |
return get_reverse_path(visited, end); | |
} | |
for (var i = 0; i < neighbors.length; i++) { | |
var n = neighbors[i], | |
id = n.x + ':' + n.y; | |
n.cost = node.cost + get_distance(n, node); | |
n.weight = n.cost + get_distance(n, end); | |
if (!visited.hasOwnProperty(id) || visited[id].cost > n.cost) { | |
add_weighted(queue, n); | |
visited[id] = n; | |
} | |
} | |
} | |
return null; | |
} | |
function get_distance(a, b) { | |
return Math.sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y)); | |
} | |
function add_weighted(queue, ref) { | |
for (var i = 0; i < queue.length; i++) { | |
if (queue[i].weight >= ref.weight) { | |
break; | |
} | |
} | |
queue.splice(i, 0, ref); | |
} | |
function get_neighbors(field, ref) { | |
var response = []; | |
var bot = Math.min(1, field.length - 1 - ref.y); | |
for (var i = Math.max(-1, -ref.y); i <= bot; i++) { | |
var y = ref.y + i, | |
right = Math.min(1, field[y].length - 1 - ref.x); | |
for (var j = Math.max(-1, -ref.x); j <= right; j++) { | |
if (i === 0 && j === 0) { | |
continue; | |
} | |
var x = ref.x + j; | |
if (!field[y][x]) { | |
response.push({x: x, y: y}); | |
} | |
} | |
} | |
return response; | |
} | |
function get_reverse_path(visited, end) { | |
var path = [end], | |
node = end, | |
sortFn = function(a, b) { return a.cost - b.cost; }, | |
getVis = function(a) { return visited[a.x + ':' + a.y]; }; | |
while (node.cost !== 0) { | |
var neighbours = get_neighbors(field, node); | |
neighbours = neighbours.map(getVis).sort(sortFn); | |
node = neighbours[0]; | |
path.push(node); | |
} | |
return path.reverse(); | |
} | |
var field = [ | |
[0,0,0,1,0], | |
[0,1,0,1,0], | |
[0,1,0,1,0], | |
[0,1,0,1,0], | |
[0,1,0,0,0] | |
]; | |
console.log(astar_path(field, {x: 0, y: 4}, {x: 4, y: 0})); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment