malwoden
Version:
   
100 lines • 4.26 kB
JavaScript
;
var __assign = (this && this.__assign) || function () {
__assign = Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.RangeFinder = void 0;
var get_ring_1 = require("../fov/get-ring");
var struct_1 = require("../struct");
/**
* Used to find a range from a central point, like movement or ranged attacks in
* turn-based games. This uses a search similar to Dijkstra or AStar, but returns
* a list of tiles in range of a starting point, rather than a path to a goal.
*/
var RangeFinder = /** @class */ (function () {
/**
* @param config - Configuration for the RangeFinder
* @param config.topology - four | eight
* @param config.getTerrainCallback - Override the distance function for terrain costs or blocked spaces.
*/
function RangeFinder(config) {
this.getTerrain = function () { return 1; };
this.topology = config.topology;
if (config.getTerrainCallback) {
this.getTerrain = config.getTerrainCallback;
}
}
RangeFinder.prototype.getNeighbors = function (pos) {
var neighbors = get_ring_1.getRing4(pos.x, pos.y, 1);
if (this.topology === "eight") {
neighbors.push({ x: pos.x + 1, y: pos.y - 1 });
neighbors.push({ x: pos.x - 1, y: pos.y - 1 });
neighbors.push({ x: pos.x - 1, y: pos.y + 1 });
neighbors.push({ x: pos.x + 1, y: pos.y + 1 });
}
return neighbors;
};
/**
* Find the range from a given point.
* @param config - Configuration for the findRange
* @param config.start - Vector2 - The starting point
* @param config.maxRange - The maximum range allowed
* @param config.minRange - The minimum range allowed (optional)
* @returns - RangeVector2[] ({x,y,r}[])
*/
RangeFinder.prototype.compute = function (config) {
var start = config.start, range = config.maxRange, _a = config.minRange, minRange = _a === void 0 ? 0 : _a;
// Nodes we will process neighbors of
var horizon = new struct_1.HeapPriorityQueue(function (v) { return v.r; });
horizon.insert(__assign(__assign({}, start), { r: 0 }));
var explored = new Map();
explored.set(start.x + ":" + start.y, 0);
while (horizon.size()) {
// Handle current node first
var current = horizon.pop();
// Handle neighbors
var neighbors = this.getNeighbors(current);
for (var _i = 0, neighbors_1 = neighbors; _i < neighbors_1.length; _i++) {
var n = neighbors_1[_i];
var distance = current.r + this.getTerrain(current, n);
var neighbor = __assign(__assign({}, n), { r: distance });
// See if it's even in range
if (neighbor.r > range)
continue;
// We pay attention only if we haven't seen it before,
// or we just found a shorter path
var importantNeighbor = !explored.has(neighbor.x + ":" + neighbor.y) ||
neighbor.r < explored.get(neighbor.x + ":" + neighbor.y);
if (importantNeighbor) {
explored.set(neighbor.x + ":" + neighbor.y, neighbor.r);
horizon.insert(neighbor);
}
}
}
// Return everything in range
var result = [];
explored.forEach(function (distance, vs) {
// Return if not in the right range
if (distance < minRange || distance > range)
return;
var _a = vs.split(":"), x = _a[0], y = _a[1];
result.push({
x: Number.parseInt(x),
y: Number.parseInt(y),
r: distance,
});
});
return result;
};
return RangeFinder;
}());
exports.RangeFinder = RangeFinder;
//# sourceMappingURL=range-finder.js.map