Spaces:
Running
Running
/** | |
* @class Simplified A* algorithm: all edges have a value of 1 | |
* @augments ROT.Path | |
* @see ROT.Path | |
*/ | |
ROT.Path.AStar = function(toX, toY, passableCallback, options) { | |
ROT.Path.call(this, toX, toY, passableCallback, options); | |
this._todo = []; | |
this._done = {}; | |
this._fromX = null; | |
this._fromY = null; | |
} | |
ROT.Path.AStar.extend(ROT.Path); | |
/** | |
* Compute a path from a given point | |
* @see ROT.Path#compute | |
*/ | |
ROT.Path.AStar.prototype.compute = function(fromX, fromY, callback) { | |
this._todo = []; | |
this._done = {}; | |
this._fromX = fromX; | |
this._fromY = fromY; | |
this._add(this._toX, this._toY, null); | |
while (this._todo.length) { | |
var item = this._todo.shift(); | |
if (item.x == fromX && item.y == fromY) { break; } | |
var neighbors = this._getNeighbors(item.x, item.y); | |
for (var i=0;i<neighbors.length;i++) { | |
var neighbor = neighbors[i]; | |
var x = neighbor[0]; | |
var y = neighbor[1]; | |
var id = x+","+y; | |
if (id in this._done) { continue; } | |
this._add(x, y, item); | |
} | |
} | |
var item = this._done[fromX+","+fromY]; | |
if (!item) { return; } | |
while (item) { | |
callback(item.x, item.y); | |
item = item.prev; | |
} | |
} | |
ROT.Path.AStar.prototype._add = function(x, y, prev) { | |
var obj = { | |
x: x, | |
y: y, | |
prev: prev, | |
g: (prev ? prev.g+1 : 0), | |
h: this._distance(x, y) | |
} | |
this._done[x+","+y] = obj; | |
/* insert into priority queue */ | |
var f = obj.g + obj.h; | |
for (var i=0;i<this._todo.length;i++) { | |
var item = this._todo[i]; | |
if (f < item.g + item.h) { | |
this._todo.splice(i, 0, obj); | |
return; | |
} | |
} | |
this._todo.push(obj); | |
} | |
ROT.Path.AStar.prototype._distance = function(x, y) { | |
switch (this._options.topology) { | |
case 4: | |
return (Math.abs(x-this._fromX) + Math.abs(y-this._fromY)); | |
break; | |
case 6: | |
var dx = Math.abs(x - this._fromX); | |
var dy = Math.abs(y - this._fromY); | |
return dy + Math.max(0, (dx-dy)/2); | |
break; | |
case 8: | |
return Math.max(Math.abs(x-this._fromX), Math.abs(y-this._fromY)); | |
break; | |
} | |
} | |