Comparing version 2.0.2 to 2.0.3
1299
dist/navmesh.js
@@ -10,3 +10,3 @@ (function webpackUniversalModuleDefinition(root, factory) { | ||
root["NavMesh"] = factory(); | ||
})(window, function() { | ||
})((typeof self !== "undefined" ? self : this), function() { | ||
return /******/ (function(modules) { // webpackBootstrap | ||
@@ -110,3 +110,3 @@ /******/ // The module cache | ||
/* global module, define */ | ||
if (typeof module === 'object' && typeof module.exports === 'object') { | ||
if ( true && typeof module.exports === 'object') { | ||
module.exports = definition(); | ||
@@ -514,3 +514,3 @@ } else if (true) { | ||
// EXTERNAL MODULE: C:/Users/micha/Documents/GitHub/navmesh/node_modules/javascript-astar/astar.js | ||
// EXTERNAL MODULE: D:/GitHub/navmesh/node_modules/javascript-astar/astar.js | ||
var astar = __webpack_require__(0); | ||
@@ -520,6 +520,2 @@ var astar_default = /*#__PURE__*/__webpack_require__.n(astar); | ||
// CONCATENATED MODULE: ./math/vector-2.js | ||
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); | ||
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } | ||
/** | ||
@@ -531,6 +527,4 @@ * Stripped down version of Phaser's Vector2 with just the functionality needed for navmeshes | ||
*/ | ||
var Vector2 = function () { | ||
function Vector2(x, y) { | ||
_classCallCheck(this, Vector2); | ||
class Vector2 { | ||
constructor(x, y) { | ||
this.x = x || 0; | ||
@@ -540,49 +534,33 @@ this.y = y || 0; | ||
_createClass(Vector2, [{ | ||
key: "equals", | ||
value: function equals(v) { | ||
return this.x === v.x && this.y === v.y; | ||
} | ||
}, { | ||
key: "angle", | ||
value: function angle(v) { | ||
return Math.atan2(v.y - this.y, v.x - this.x); | ||
} | ||
}, { | ||
key: "distance", | ||
value: function distance(v) { | ||
var dx = v.x - this.x; | ||
var dy = v.y - this.y; | ||
return Math.sqrt(dx * dx + dy * dy); | ||
} | ||
}, { | ||
key: "add", | ||
value: function add(v) { | ||
this.x += v.x; | ||
this.y += v.y; | ||
} | ||
}, { | ||
key: "subtract", | ||
value: function subtract(v) { | ||
this.x -= v.x; | ||
this.y -= v.y; | ||
} | ||
}, { | ||
key: "clone", | ||
value: function clone() { | ||
return new Vector2(this.x, this.y); | ||
} | ||
}]); | ||
equals(v) { | ||
return this.x === v.x && this.y === v.y; | ||
} | ||
return Vector2; | ||
}(); | ||
angle(v) { | ||
return Math.atan2(v.y - this.y, v.x - this.x); | ||
} | ||
/* harmony default export */ var vector_2 = (Vector2); | ||
// CONCATENATED MODULE: ./navpoly.js | ||
var navpoly_createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); | ||
distance(v) { | ||
const dx = v.x - this.x; | ||
const dy = v.y - this.y; | ||
return Math.sqrt(dx * dx + dy * dy); | ||
} | ||
function navpoly_classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } | ||
add(v) { | ||
this.x += v.x; | ||
this.y += v.y; | ||
} | ||
subtract(v) { | ||
this.x -= v.x; | ||
this.y -= v.y; | ||
} | ||
clone() { | ||
return new Vector2(this.x, this.y); | ||
} | ||
} | ||
// CONCATENATED MODULE: ./navpoly.js | ||
/** | ||
@@ -597,3 +575,3 @@ * A class that represents a navigable polygon with a navmesh. It is built on top of a | ||
var navpoly_NavPoly = function () { | ||
class navpoly_NavPoly { | ||
/** | ||
@@ -606,5 +584,3 @@ * Creates an instance of NavPoly. | ||
*/ | ||
function NavPoly(id, polygon) { | ||
navpoly_classCallCheck(this, NavPoly); | ||
constructor(id, polygon) { | ||
this.id = id; | ||
@@ -617,6 +593,4 @@ this.polygon = polygon; | ||
this.boundingRadius = this.calculateRadius(); | ||
this.weight = 1; // jsastar property | ||
} | ||
/** | ||
@@ -630,168 +604,100 @@ * Returns an array of points that form the polygon. | ||
navpoly_createClass(NavPoly, [{ | ||
key: "getPoints", | ||
value: function getPoints() { | ||
return this.polygon.points; | ||
} | ||
getPoints() { | ||
return this.polygon.points; | ||
} | ||
/** | ||
* Check if the given point-like object is within the polygon | ||
* | ||
* @param {object} point Object of the form {x, y} | ||
* @returns {boolean} | ||
* @memberof NavPoly | ||
*/ | ||
/** | ||
* Check if the given point-like object is within the polygon | ||
* | ||
* @param {object} point Object of the form {x, y} | ||
* @returns {boolean} | ||
* @memberof NavPoly | ||
*/ | ||
}, { | ||
key: "contains", | ||
value: function contains(point) { | ||
// Phaser's polygon check doesn't handle when a point is on one of the edges of the line. Note: | ||
// check numerical stability here. It would also be good to optimize this for different shapes. | ||
return this.polygon.contains(point.x, point.y) || this.isPointOnEdge(point); | ||
} | ||
contains(point) { | ||
// Phaser's polygon check doesn't handle when a point is on one of the edges of the line. Note: | ||
// check numerical stability here. It would also be good to optimize this for different shapes. | ||
return this.polygon.contains(point.x, point.y) || this.isPointOnEdge(point); | ||
} | ||
/** | ||
* Only rectangles are supported, so this calculation works, but this is not actually the centroid | ||
* calculation for a polygon. This is just the average of the vertices - proper centroid of a | ||
* polygon factors in the area. | ||
* | ||
* @returns {Vector2} | ||
* @memberof NavPoly | ||
*/ | ||
/** | ||
* Only rectangles are supported, so this calculation works, but this is not actually the centroid | ||
* calculation for a polygon. This is just the average of the vertices - proper centroid of a | ||
* polygon factors in the area. | ||
* | ||
* @returns {Vector2} | ||
* @memberof NavPoly | ||
*/ | ||
}, { | ||
key: "calculateCentroid", | ||
value: function calculateCentroid() { | ||
var centroid = new vector_2(0, 0); | ||
var length = this.polygon.points.length; | ||
this.polygon.points.forEach(function (p) { | ||
return centroid.add(p); | ||
}); | ||
centroid.x /= length; | ||
centroid.y /= length; | ||
return centroid; | ||
} | ||
calculateCentroid() { | ||
const centroid = new Vector2(0, 0); | ||
const length = this.polygon.points.length; | ||
this.polygon.points.forEach(p => centroid.add(p)); | ||
centroid.x /= length; | ||
centroid.y /= length; | ||
return centroid; | ||
} | ||
/** | ||
* Calculate the radius of a circle that circumscribes the polygon. | ||
* | ||
* @returns {number} | ||
* @memberof NavPoly | ||
*/ | ||
/** | ||
* Calculate the radius of a circle that circumscribes the polygon. | ||
* | ||
* @returns {number} | ||
* @memberof NavPoly | ||
*/ | ||
}, { | ||
key: "calculateRadius", | ||
value: function calculateRadius() { | ||
var boundingRadius = 0; | ||
var _iteratorNormalCompletion = true; | ||
var _didIteratorError = false; | ||
var _iteratorError = undefined; | ||
calculateRadius() { | ||
let boundingRadius = 0; | ||
try { | ||
for (var _iterator = this.polygon.points[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { | ||
var point = _step.value; | ||
for (const point of this.polygon.points) { | ||
const d = this.centroid.distance(point); | ||
if (d > boundingRadius) boundingRadius = d; | ||
} | ||
var d = this.centroid.distance(point); | ||
if (d > boundingRadius) boundingRadius = d; | ||
} | ||
} catch (err) { | ||
_didIteratorError = true; | ||
_iteratorError = err; | ||
} finally { | ||
try { | ||
if (!_iteratorNormalCompletion && _iterator.return) { | ||
_iterator.return(); | ||
} | ||
} finally { | ||
if (_didIteratorError) { | ||
throw _iteratorError; | ||
} | ||
} | ||
} | ||
return boundingRadius; | ||
} | ||
/** | ||
* Check if the given point-like object is on one of the edges of the polygon. | ||
* | ||
* @param {object} Point-like object in the form { x, y } | ||
* @returns {boolean} | ||
* @memberof NavPoly | ||
*/ | ||
return boundingRadius; | ||
isPointOnEdge({ | ||
x, | ||
y | ||
}) { | ||
for (const edge of this.edges) { | ||
if (edge.pointOnSegment(x, y)) return true; | ||
} | ||
/** | ||
* Check if the given point-like object is on one of the edges of the polygon. | ||
* | ||
* @param {object} Point-like object in the form { x, y } | ||
* @returns {boolean} | ||
* @memberof NavPoly | ||
*/ | ||
return false; | ||
} | ||
}, { | ||
key: "isPointOnEdge", | ||
value: function isPointOnEdge(_ref) { | ||
var x = _ref.x, | ||
y = _ref.y; | ||
var _iteratorNormalCompletion2 = true; | ||
var _didIteratorError2 = false; | ||
var _iteratorError2 = undefined; | ||
destroy() { | ||
this.neighbors = []; | ||
this.portals = []; | ||
} // jsastar methods | ||
try { | ||
for (var _iterator2 = this.edges[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) { | ||
var edge = _step2.value; | ||
if (edge.pointOnSegment(x, y)) return true; | ||
} | ||
} catch (err) { | ||
_didIteratorError2 = true; | ||
_iteratorError2 = err; | ||
} finally { | ||
try { | ||
if (!_iteratorNormalCompletion2 && _iterator2.return) { | ||
_iterator2.return(); | ||
} | ||
} finally { | ||
if (_didIteratorError2) { | ||
throw _iteratorError2; | ||
} | ||
} | ||
} | ||
toString() { | ||
return `NavPoly(id: ${this.id} at: ${this.centroid})`; | ||
} | ||
return false; | ||
} | ||
}, { | ||
key: "destroy", | ||
value: function destroy() { | ||
this.neighbors = []; | ||
this.portals = []; | ||
} | ||
isWall() { | ||
return this.weight === 0; | ||
} | ||
// jsastar methods | ||
centroidDistance(navPolygon) { | ||
return this.centroid.distance(navPolygon.centroid); | ||
} | ||
}, { | ||
key: "toString", | ||
value: function toString() { | ||
return "NavPoly(id: " + this.id + " at: " + this.centroid + ")"; | ||
} | ||
}, { | ||
key: "isWall", | ||
value: function isWall() { | ||
return this.weight === 0; | ||
} | ||
}, { | ||
key: "centroidDistance", | ||
value: function centroidDistance(navPolygon) { | ||
return this.centroid.distance(navPolygon.centroid); | ||
} | ||
}, { | ||
key: "getCost", | ||
value: function getCost(navPolygon) { | ||
return this.centroidDistance(navPolygon); | ||
} | ||
}]); | ||
getCost(navPolygon) { | ||
return this.centroidDistance(navPolygon); | ||
} | ||
return NavPoly; | ||
}(); | ||
/* harmony default export */ var navpoly = (navpoly_NavPoly); | ||
} | ||
// CONCATENATED MODULE: ./navgraph.js | ||
var navgraph_createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); | ||
function navgraph_classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } | ||
/** | ||
@@ -805,6 +711,4 @@ * Graph for javascript-astar. It implements the functionality for astar. See GPS test from astar | ||
var NavGraph = function () { | ||
function NavGraph(navPolygons) { | ||
navgraph_classCallCheck(this, NavGraph); | ||
class NavGraph { | ||
constructor(navPolygons) { | ||
this.nodes = navPolygons; | ||
@@ -814,27 +718,20 @@ this.init(); | ||
navgraph_createClass(NavGraph, [{ | ||
key: "neighbors", | ||
value: function neighbors(navPolygon) { | ||
return navPolygon.neighbors; | ||
} | ||
}, { | ||
key: "navHeuristic", | ||
value: function navHeuristic(navPolygon1, navPolygon2) { | ||
return navPolygon1.centroidDistance(navPolygon2); | ||
} | ||
}, { | ||
key: "destroy", | ||
value: function destroy() { | ||
this.cleanDirty(); | ||
this.nodes = []; | ||
} | ||
}]); | ||
neighbors(navPolygon) { | ||
return navPolygon.neighbors; | ||
} | ||
return NavGraph; | ||
}(); | ||
navHeuristic(navPolygon1, navPolygon2) { | ||
return navPolygon1.centroidDistance(navPolygon2); | ||
} | ||
destroy() { | ||
this.cleanDirty(); | ||
this.nodes = []; | ||
} | ||
} | ||
NavGraph.prototype.init = astar_default.a.Graph.prototype.init; | ||
NavGraph.prototype.cleanDirty = astar_default.a.Graph.prototype.cleanDirty; | ||
NavGraph.prototype.markDirty = astar_default.a.Graph.prototype.markDirty; | ||
/* harmony default export */ var navgraph = (NavGraph); | ||
@@ -848,9 +745,8 @@ // CONCATENATED MODULE: ./utils.js | ||
function triarea2(a, b, c) { | ||
var ax = b.x - a.x; | ||
var ay = b.y - a.y; | ||
var bx = c.x - a.x; | ||
var by = c.y - a.y; | ||
const ax = b.x - a.x; | ||
const ay = b.y - a.y; | ||
const bx = c.x - a.x; | ||
const by = c.y - a.y; | ||
return bx * ay - ax * by; | ||
} | ||
/** | ||
@@ -861,2 +757,3 @@ * Clamp value between min and max | ||
*/ | ||
function clamp(value, min, max) { | ||
@@ -867,3 +764,2 @@ if (value < min) value = min; | ||
} | ||
/** | ||
@@ -874,8 +770,6 @@ * Check if two values within a small margin of one another | ||
*/ | ||
function almostEqual(value1, value2) { | ||
var errorMargin = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0.0001; | ||
function almostEqual(value1, value2, errorMargin = 0.0001) { | ||
if (Math.abs(value1 - value2) <= errorMargin) return true;else return false; | ||
} | ||
/** | ||
@@ -887,11 +781,12 @@ * Find the smallest angle difference between two angles | ||
*/ | ||
function angleDifference(x, y) { | ||
var a = x - y; | ||
var i = a + Math.PI; | ||
var j = Math.PI * 2; | ||
let a = x - y; | ||
const i = a + Math.PI; | ||
const j = Math.PI * 2; | ||
a = i - Math.floor(i / j) * j; // (a+180) % 360; this ensures the correct sign | ||
a -= Math.PI; | ||
return a; | ||
} | ||
/** | ||
@@ -902,9 +797,9 @@ * Check if two lines are collinear (within a marign) | ||
*/ | ||
function areCollinear(line1, line2) { | ||
var errorMargin = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0.0001; | ||
function areCollinear(line1, line2, errorMargin = 0.0001) { | ||
// Figure out if the two lines are equal by looking at the area of the triangle formed | ||
// by their points | ||
var area1 = triarea2(line1.start, line1.end, line2.start); | ||
var area2 = triarea2(line1.start, line1.end, line2.end); | ||
const area1 = triarea2(line1.start, line1.end, line2.start); | ||
const area2 = triarea2(line1.start, line1.end, line2.end); | ||
if (almostEqual(area1, 0, errorMargin) && almostEqual(area2, 0, errorMargin)) { | ||
@@ -915,11 +810,5 @@ return true; | ||
// CONCATENATED MODULE: ./channel.js | ||
var channel_createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); | ||
function channel_classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } | ||
// Mostly sourced from PatrolJS at the moment. TODO: come back and reimplement this as an incomplete | ||
// funnel algorithm so astar checks can be more accurate. | ||
/** | ||
@@ -929,119 +818,98 @@ * @private | ||
var channel_Channel = function () { | ||
function Channel() { | ||
channel_classCallCheck(this, Channel); | ||
class channel_Channel { | ||
constructor() { | ||
this.portals = []; | ||
} | ||
channel_createClass(Channel, [{ | ||
key: "push", | ||
value: function push(p1) { | ||
var p2 = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null; | ||
push(p1, p2 = null) { | ||
if (p2 === null) p2 = p1; | ||
this.portals.push({ | ||
left: p1, | ||
right: p2 | ||
}); | ||
} | ||
if (p2 === null) p2 = p1; | ||
this.portals.push({ | ||
left: p1, | ||
right: p2 | ||
}); | ||
} | ||
}, { | ||
key: "stringPull", | ||
value: function stringPull() { | ||
var portals = this.portals; | ||
var pts = []; | ||
// Init scan state | ||
var portalApex, portalLeft, portalRight; | ||
var apexIndex = 0, | ||
leftIndex = 0, | ||
rightIndex = 0; | ||
stringPull() { | ||
var portals = this.portals; | ||
var pts = []; // Init scan state | ||
portalApex = portals[0].left; | ||
portalLeft = portals[0].left; | ||
portalRight = portals[0].right; | ||
var portalApex, portalLeft, portalRight; | ||
var apexIndex = 0, | ||
leftIndex = 0, | ||
rightIndex = 0; | ||
portalApex = portals[0].left; | ||
portalLeft = portals[0].left; | ||
portalRight = portals[0].right; // Add start point. | ||
// Add start point. | ||
pts.push(portalApex); | ||
pts.push(portalApex); | ||
for (var i = 1; i < portals.length; i++) { | ||
// Find the next portal vertices | ||
var left = portals[i].left; | ||
var right = portals[i].right; | ||
for (var i = 1; i < portals.length; i++) { | ||
// Find the next portal vertices | ||
var left = portals[i].left; | ||
var right = portals[i].right; // Update right vertex. | ||
// Update right vertex. | ||
if (triarea2(portalApex, portalRight, right) <= 0.0) { | ||
if (portalApex.equals(portalRight) || triarea2(portalApex, portalLeft, right) > 0.0) { | ||
// Tighten the funnel. | ||
portalRight = right; | ||
rightIndex = i; | ||
} else { | ||
// Right vertex just crossed over the left vertex, so the left vertex should | ||
// now be part of the path. | ||
pts.push(portalLeft); | ||
if (triarea2(portalApex, portalRight, right) <= 0.0) { | ||
if (portalApex.equals(portalRight) || triarea2(portalApex, portalLeft, right) > 0.0) { | ||
// Tighten the funnel. | ||
portalRight = right; | ||
rightIndex = i; | ||
} else { | ||
// Right vertex just crossed over the left vertex, so the left vertex should | ||
// now be part of the path. | ||
pts.push(portalLeft); // Restart scan from portal left point. | ||
// Make current left the new apex. | ||
// Restart scan from portal left point. | ||
portalApex = portalLeft; | ||
apexIndex = leftIndex; // Reset portal | ||
// Make current left the new apex. | ||
portalApex = portalLeft; | ||
apexIndex = leftIndex; | ||
// Reset portal | ||
portalLeft = portalApex; | ||
portalRight = portalApex; | ||
leftIndex = apexIndex; | ||
rightIndex = apexIndex; | ||
// Restart scan | ||
i = apexIndex; | ||
continue; | ||
} | ||
portalLeft = portalApex; | ||
portalRight = portalApex; | ||
leftIndex = apexIndex; | ||
rightIndex = apexIndex; // Restart scan | ||
i = apexIndex; | ||
continue; | ||
} | ||
} // Update left vertex. | ||
// Update left vertex. | ||
if (triarea2(portalApex, portalLeft, left) >= 0.0) { | ||
if (portalApex.equals(portalLeft) || triarea2(portalApex, portalRight, left) < 0.0) { | ||
// Tighten the funnel. | ||
portalLeft = left; | ||
leftIndex = i; | ||
} else { | ||
// Left vertex just crossed over the right vertex, so the right vertex should | ||
// now be part of the path | ||
pts.push(portalRight); | ||
// Restart scan from portal right point. | ||
if (triarea2(portalApex, portalLeft, left) >= 0.0) { | ||
if (portalApex.equals(portalLeft) || triarea2(portalApex, portalRight, left) < 0.0) { | ||
// Tighten the funnel. | ||
portalLeft = left; | ||
leftIndex = i; | ||
} else { | ||
// Left vertex just crossed over the right vertex, so the right vertex should | ||
// now be part of the path | ||
pts.push(portalRight); // Restart scan from portal right point. | ||
// Make current right the new apex. | ||
// Make current right the new apex. | ||
portalApex = portalRight; | ||
apexIndex = rightIndex; | ||
// Reset portal | ||
portalLeft = portalApex; | ||
portalRight = portalApex; | ||
leftIndex = apexIndex; | ||
rightIndex = apexIndex; | ||
// Restart scan | ||
i = apexIndex; | ||
continue; | ||
} | ||
portalApex = portalRight; | ||
apexIndex = rightIndex; // Reset portal | ||
portalLeft = portalApex; | ||
portalRight = portalApex; | ||
leftIndex = apexIndex; | ||
rightIndex = apexIndex; // Restart scan | ||
i = apexIndex; | ||
continue; | ||
} | ||
} | ||
} | ||
if (pts.length === 0 || !pts[pts.length - 1].equals(portals[portals.length - 1].left)) { | ||
// Append last point to path. | ||
pts.push(portals[portals.length - 1].left); | ||
} | ||
this.path = pts; | ||
return pts; | ||
if (pts.length === 0 || !pts[pts.length - 1].equals(portals[portals.length - 1].left)) { | ||
// Append last point to path. | ||
pts.push(portals[portals.length - 1].left); | ||
} | ||
}]); | ||
return Channel; | ||
}(); | ||
this.path = pts; | ||
return pts; | ||
} | ||
} | ||
/* harmony default export */ var channel_0 = (channel_Channel); | ||
// CONCATENATED MODULE: ./math/line.js | ||
var line_createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); | ||
function line_classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } | ||
/** | ||
@@ -1054,9 +922,6 @@ * Stripped down version of Phaser's Line with just the functionality needed for navmeshes | ||
var line_Line = function () { | ||
function Line(x1, y1, x2, y2) { | ||
line_classCallCheck(this, Line); | ||
this.start = new vector_2(x1, y1); | ||
this.end = new vector_2(x2, y2); | ||
class line_Line { | ||
constructor(x1, y1, x2, y2) { | ||
this.start = new Vector2(x1, y1); | ||
this.end = new Vector2(x2, y2); | ||
this.left = Math.min(x1, x2); | ||
@@ -1068,26 +933,14 @@ this.right = Math.max(x1, x2); | ||
line_createClass(Line, [{ | ||
key: "pointOnSegment", | ||
value: function pointOnSegment(x, y) { | ||
return x >= this.left && x <= this.right && y >= this.top && y <= this.bottom && this.pointOnLine(x, y); | ||
} | ||
}, { | ||
key: "pointOnLine", | ||
value: function pointOnLine(x, y) { | ||
// Compare slope of line start -> xy to line start -> line end | ||
return (x - this.left) * (this.bottom - this.top) === (this.right - this.left) * (y - this.top); | ||
} | ||
}]); | ||
pointOnSegment(x, y) { | ||
return x >= this.left && x <= this.right && y >= this.top && y <= this.bottom && this.pointOnLine(x, y); | ||
} | ||
return Line; | ||
}(); | ||
pointOnLine(x, y) { | ||
// Compare slope of line start -> xy to line start -> line end | ||
return (x - this.left) * (this.bottom - this.top) === (this.right - this.left) * (y - this.top); | ||
} | ||
/* harmony default export */ var math_line = (line_Line); | ||
} | ||
// CONCATENATED MODULE: ./math/polygon.js | ||
var polygon_createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); | ||
function polygon_classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } | ||
/** | ||
@@ -1100,54 +953,41 @@ * Stripped down version of Phaser's Polygon with just the functionality needed for navmeshes | ||
var polygon_Polygon = function () { | ||
function Polygon(points) { | ||
var closed = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true; | ||
polygon_classCallCheck(this, Polygon); | ||
class polygon_Polygon { | ||
constructor(points, closed = true) { | ||
this.points = points; | ||
this.edges = []; | ||
for (var i = 1; i < points.length; i++) { | ||
var p1 = points[i - 1]; | ||
var p2 = points[i]; | ||
this.edges.push(new math_line(p1.x, p1.y, p2.x, p2.y)); | ||
for (let i = 1; i < points.length; i++) { | ||
const p1 = points[i - 1]; | ||
const p2 = points[i]; | ||
this.edges.push(new line_Line(p1.x, p1.y, p2.x, p2.y)); | ||
} | ||
if (closed) { | ||
var first = points[0]; | ||
var last = points[points.length - 1]; | ||
this.edges.push(new math_line(first.x, first.y, last.x, last.y)); | ||
const first = points[0]; | ||
const last = points[points.length - 1]; | ||
this.edges.push(new line_Line(first.x, first.y, last.x, last.y)); | ||
} | ||
} | ||
polygon_createClass(Polygon, [{ | ||
key: "contains", | ||
value: function contains(x, y) { | ||
var inside = false; | ||
contains(x, y) { | ||
let inside = false; | ||
for (var i = -1, j = this.points.length - 1; ++i < this.points.length; j = i) { | ||
var ix = this.points[i].x; | ||
var iy = this.points[i].y; | ||
for (let i = -1, j = this.points.length - 1; ++i < this.points.length; j = i) { | ||
const ix = this.points[i].x; | ||
const iy = this.points[i].y; | ||
const jx = this.points[j].x; | ||
const jy = this.points[j].y; | ||
var jx = this.points[j].x; | ||
var jy = this.points[j].y; | ||
if ((iy <= y && y < jy || jy <= y && y < iy) && x < (jx - ix) * (y - iy) / (jy - iy) + ix) { | ||
inside = !inside; | ||
} | ||
if ((iy <= y && y < jy || jy <= y && y < iy) && x < (jx - ix) * (y - iy) / (jy - iy) + ix) { | ||
inside = !inside; | ||
} | ||
return inside; | ||
} | ||
}]); | ||
return Polygon; | ||
}(); | ||
return inside; | ||
} | ||
/* harmony default export */ var math_polygon = (polygon_Polygon); | ||
} | ||
// CONCATENATED MODULE: ./navmesh.js | ||
var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }(); | ||
var navmesh_createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); | ||
function navmesh_classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } | ||
@@ -1159,6 +999,2 @@ | ||
/** | ||
@@ -1176,3 +1012,3 @@ * The workhorse that represents a navigation mesh built from a series of polygons. Once built, the | ||
var navmesh_NavMesh = function () { | ||
class navmesh_NavMesh { | ||
/** | ||
@@ -1186,26 +1022,15 @@ * Creates an instance of NavMesh. | ||
*/ | ||
function NavMesh(meshPolygonPoints) { | ||
var meshShrinkAmount = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0; | ||
navmesh_classCallCheck(this, NavMesh); | ||
constructor(meshPolygonPoints, meshShrinkAmount = 0) { | ||
this._meshShrinkAmount = meshShrinkAmount; | ||
var newPolys = meshPolygonPoints.map(function (polyPoints) { | ||
var vectors = polyPoints.map(function (p) { | ||
return new vector_2(p.x, p.y); | ||
}); | ||
return new math_polygon(vectors); | ||
const newPolys = meshPolygonPoints.map(polyPoints => { | ||
const vectors = polyPoints.map(p => new Vector2(p.x, p.y)); | ||
return new polygon_Polygon(vectors); | ||
}); | ||
this._navPolygons = newPolys.map((polygon, i) => new navpoly_NavPoly(i, polygon)); | ||
this._navPolygons = newPolys.map(function (polygon, i) { | ||
return new navpoly(i, polygon); | ||
}); | ||
this._calculateNeighbors(); // Astar graph of connections between polygons | ||
this._calculateNeighbors(); | ||
// Astar graph of connections between polygons | ||
this._graph = new navgraph(this._navPolygons); | ||
} | ||
/** | ||
@@ -1219,359 +1044,198 @@ * Get the NavPolys that are in this navmesh. | ||
navmesh_createClass(NavMesh, [{ | ||
key: "getPolygons", | ||
value: function getPolygons() { | ||
return this._navPolygons; | ||
} | ||
getPolygons() { | ||
return this._navPolygons; | ||
} | ||
/** | ||
* Cleanup method to remove references. | ||
* | ||
* @memberof NavMesh | ||
*/ | ||
/** | ||
* Cleanup method to remove references. | ||
* | ||
* @memberof NavMesh | ||
*/ | ||
}, { | ||
key: "destroy", | ||
value: function destroy() { | ||
this._graph.destroy(); | ||
var _iteratorNormalCompletion = true; | ||
var _didIteratorError = false; | ||
var _iteratorError = undefined; | ||
destroy() { | ||
this._graph.destroy(); | ||
try { | ||
for (var _iterator = this._navPolygons[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { | ||
var poly = _step.value; | ||
poly.destroy(); | ||
} | ||
} catch (err) { | ||
_didIteratorError = true; | ||
_iteratorError = err; | ||
} finally { | ||
try { | ||
if (!_iteratorNormalCompletion && _iterator.return) { | ||
_iterator.return(); | ||
} | ||
} finally { | ||
if (_didIteratorError) { | ||
throw _iteratorError; | ||
} | ||
} | ||
} | ||
for (const poly of this._navPolygons) poly.destroy(); | ||
this._navPolygons = []; | ||
} | ||
this._navPolygons = []; | ||
} | ||
/** | ||
* Find a path from the start point to the end point using this nav mesh. | ||
* | ||
* @param {object} startPoint A point-like object in the form {x, y} | ||
* @param {object} endPoint A point-like object in the form {x, y} | ||
* @returns {Vector2[]|null} An array of points if a path is found, or null if no path | ||
* | ||
* @memberof NavMesh | ||
*/ | ||
/** | ||
* Find a path from the start point to the end point using this nav mesh. | ||
* | ||
* @param {object} startPoint A point-like object in the form {x, y} | ||
* @param {object} endPoint A point-like object in the form {x, y} | ||
* @returns {Vector2[]|null} An array of points if a path is found, or null if no path | ||
* | ||
* @memberof NavMesh | ||
*/ | ||
}, { | ||
key: "findPath", | ||
value: function findPath(startPoint, endPoint) { | ||
var startPoly = null; | ||
var endPoly = null; | ||
var startDistance = Number.MAX_VALUE; | ||
var endDistance = Number.MAX_VALUE; | ||
var d = void 0, | ||
r = void 0; | ||
var startVector = new vector_2(startPoint.x, startPoint.y); | ||
var endVector = new vector_2(endPoint.x, endPoint.y); | ||
findPath(startPoint, endPoint) { | ||
let startPoly = null; | ||
let endPoly = null; | ||
let startDistance = Number.MAX_VALUE; | ||
let endDistance = Number.MAX_VALUE; | ||
let d, r; | ||
const startVector = new Vector2(startPoint.x, startPoint.y); | ||
const endVector = new Vector2(endPoint.x, endPoint.y); // Find the closest poly for the starting and ending point | ||
// Find the closest poly for the starting and ending point | ||
var _iteratorNormalCompletion2 = true; | ||
var _didIteratorError2 = false; | ||
var _iteratorError2 = undefined; | ||
for (const navPoly of this._navPolygons) { | ||
r = navPoly.boundingRadius; // Start | ||
try { | ||
for (var _iterator2 = this._navPolygons[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) { | ||
var navPoly = _step2.value; | ||
d = navPoly.centroid.distance(startVector); | ||
r = navPoly.boundingRadius; | ||
// Start | ||
d = navPoly.centroid.distance(startVector); | ||
if (d <= startDistance && d <= r && navPoly.contains(startVector)) { | ||
startPoly = navPoly; | ||
startDistance = d; | ||
} | ||
// End | ||
d = navPoly.centroid.distance(endVector); | ||
if (d <= endDistance && d <= r && navPoly.contains(endVector)) { | ||
endPoly = navPoly; | ||
endDistance = d; | ||
} | ||
} | ||
if (d <= startDistance && d <= r && navPoly.contains(startVector)) { | ||
startPoly = navPoly; | ||
startDistance = d; | ||
} // End | ||
// If the start point wasn't inside a polygon, run a more liberal check that allows a point | ||
// to be within meshShrinkAmount radius of a polygon | ||
} catch (err) { | ||
_didIteratorError2 = true; | ||
_iteratorError2 = err; | ||
} finally { | ||
try { | ||
if (!_iteratorNormalCompletion2 && _iterator2.return) { | ||
_iterator2.return(); | ||
} | ||
} finally { | ||
if (_didIteratorError2) { | ||
throw _iteratorError2; | ||
} | ||
} | ||
d = navPoly.centroid.distance(endVector); | ||
if (d <= endDistance && d <= r && navPoly.contains(endVector)) { | ||
endPoly = navPoly; | ||
endDistance = d; | ||
} | ||
} // If the start point wasn't inside a polygon, run a more liberal check that allows a point | ||
// to be within meshShrinkAmount radius of a polygon | ||
if (!startPoly && this._meshShrinkAmount > 0) { | ||
var _iteratorNormalCompletion3 = true; | ||
var _didIteratorError3 = false; | ||
var _iteratorError3 = undefined; | ||
try { | ||
for (var _iterator3 = this._navPolygons[Symbol.iterator](), _step3; !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done); _iteratorNormalCompletion3 = true) { | ||
var _navPoly = _step3.value; | ||
if (!startPoly && this._meshShrinkAmount > 0) { | ||
for (const navPoly of this._navPolygons) { | ||
// Check if point is within bounding circle to avoid extra projection calculations | ||
r = navPoly.boundingRadius + this._meshShrinkAmount; | ||
d = navPoly.centroid.distance(startVector); | ||
// Check if point is within bounding circle to avoid extra projection calculations | ||
r = _navPoly.boundingRadius + this._meshShrinkAmount; | ||
d = _navPoly.centroid.distance(startVector); | ||
if (d <= r) { | ||
// Check if projected point is within range of a polgyon and is closer than the | ||
// previous point | ||
var _projectPointToPolygo = this._projectPointToPolygon(startVector, _navPoly), | ||
distance = _projectPointToPolygo.distance; | ||
if (d <= r) { | ||
// Check if projected point is within range of a polgyon and is closer than the | ||
// previous point | ||
const { | ||
distance | ||
} = this._projectPointToPolygon(startVector, navPoly); | ||
if (distance <= this._meshShrinkAmount && distance < startDistance) { | ||
startPoly = _navPoly; | ||
startDistance = distance; | ||
} | ||
} | ||
if (distance <= this._meshShrinkAmount && distance < startDistance) { | ||
startPoly = navPoly; | ||
startDistance = distance; | ||
} | ||
} catch (err) { | ||
_didIteratorError3 = true; | ||
_iteratorError3 = err; | ||
} finally { | ||
try { | ||
if (!_iteratorNormalCompletion3 && _iterator3.return) { | ||
_iterator3.return(); | ||
} | ||
} finally { | ||
if (_didIteratorError3) { | ||
throw _iteratorError3; | ||
} | ||
} | ||
} | ||
} | ||
} // Same check as above, but for the end point | ||
// Same check as above, but for the end point | ||
if (!endPoly && this._meshShrinkAmount > 0) { | ||
var _iteratorNormalCompletion4 = true; | ||
var _didIteratorError4 = false; | ||
var _iteratorError4 = undefined; | ||
try { | ||
for (var _iterator4 = this._navPolygons[Symbol.iterator](), _step4; !(_iteratorNormalCompletion4 = (_step4 = _iterator4.next()).done); _iteratorNormalCompletion4 = true) { | ||
var _navPoly2 = _step4.value; | ||
if (!endPoly && this._meshShrinkAmount > 0) { | ||
for (const navPoly of this._navPolygons) { | ||
r = navPoly.boundingRadius + this._meshShrinkAmount; | ||
d = navPoly.centroid.distance(endVector); | ||
r = _navPoly2.boundingRadius + this._meshShrinkAmount; | ||
d = _navPoly2.centroid.distance(endVector); | ||
if (d <= r) { | ||
var _projectPointToPolygo2 = this._projectPointToPolygon(endVector, _navPoly2), | ||
_distance = _projectPointToPolygo2.distance; | ||
if (d <= r) { | ||
const { | ||
distance | ||
} = this._projectPointToPolygon(endVector, navPoly); | ||
if (_distance <= this._meshShrinkAmount && _distance < endDistance) { | ||
endPoly = _navPoly2; | ||
endDistance = _distance; | ||
} | ||
} | ||
if (distance <= this._meshShrinkAmount && distance < endDistance) { | ||
endPoly = navPoly; | ||
endDistance = distance; | ||
} | ||
} catch (err) { | ||
_didIteratorError4 = true; | ||
_iteratorError4 = err; | ||
} finally { | ||
try { | ||
if (!_iteratorNormalCompletion4 && _iterator4.return) { | ||
_iterator4.return(); | ||
} | ||
} finally { | ||
if (_didIteratorError4) { | ||
throw _iteratorError4; | ||
} | ||
} | ||
} | ||
} | ||
} // No matching polygons locations for the start or end, so no path found | ||
// No matching polygons locations for the start or end, so no path found | ||
if (!startPoly || !endPoly) return null; | ||
// If the start and end polygons are the same, return a direct path | ||
if (startPoly === endPoly) return [startVector, endVector]; | ||
if (!startPoly || !endPoly) return null; // If the start and end polygons are the same, return a direct path | ||
// Search! | ||
var astarPath = astar_default.a.astar.search(this._graph, startPoly, endPoly, { | ||
heuristic: this._graph.navHeuristic | ||
}); | ||
if (startPoly === endPoly) return [startVector, endVector]; // Search! | ||
// While the start and end polygons may be valid, no path between them | ||
if (astarPath.length === 0) return null; | ||
const astarPath = astar_default.a.astar.search(this._graph, startPoly, endPoly, { | ||
heuristic: this._graph.navHeuristic | ||
}); // While the start and end polygons may be valid, no path between them | ||
// jsastar drops the first point from the path, but the funnel algorithm needs it | ||
astarPath.unshift(startPoly); | ||
if (astarPath.length === 0) return null; // jsastar drops the first point from the path, but the funnel algorithm needs it | ||
// We have a path, so now time for the funnel algorithm | ||
var channel = new channel_0(); | ||
channel.push(startVector); | ||
for (var i = 0; i < astarPath.length - 1; i++) { | ||
var navPolygon = astarPath[i]; | ||
var nextNavPolygon = astarPath[i + 1]; | ||
astarPath.unshift(startPoly); // We have a path, so now time for the funnel algorithm | ||
// Find the portal | ||
var portal = null; | ||
for (var _i = 0; _i < navPolygon.neighbors.length; _i++) { | ||
if (navPolygon.neighbors[_i].id === nextNavPolygon.id) { | ||
portal = navPolygon.portals[_i]; | ||
} | ||
const channel = new channel_0(); | ||
channel.push(startVector); | ||
for (let i = 0; i < astarPath.length - 1; i++) { | ||
const navPolygon = astarPath[i]; | ||
const nextNavPolygon = astarPath[i + 1]; // Find the portal | ||
let portal = null; | ||
for (let i = 0; i < navPolygon.neighbors.length; i++) { | ||
if (navPolygon.neighbors[i].id === nextNavPolygon.id) { | ||
portal = navPolygon.portals[i]; | ||
} | ||
} // Push the portal vertices into the channel | ||
// Push the portal vertices into the channel | ||
channel.push(portal.start, portal.end); | ||
} | ||
channel.push(endVector); | ||
// Pull a string along the channel to run the funnel | ||
channel.stringPull(); | ||
channel.push(portal.start, portal.end); | ||
} | ||
// Clone path, excluding duplicates | ||
var lastPoint = null; | ||
var phaserPath = []; | ||
var _iteratorNormalCompletion5 = true; | ||
var _didIteratorError5 = false; | ||
var _iteratorError5 = undefined; | ||
channel.push(endVector); // Pull a string along the channel to run the funnel | ||
try { | ||
for (var _iterator5 = channel.path[Symbol.iterator](), _step5; !(_iteratorNormalCompletion5 = (_step5 = _iterator5.next()).done); _iteratorNormalCompletion5 = true) { | ||
var p = _step5.value; | ||
channel.stringPull(); // Clone path, excluding duplicates | ||
var newPoint = p.clone(); | ||
if (!lastPoint || !newPoint.equals(lastPoint)) phaserPath.push(newPoint); | ||
lastPoint = newPoint; | ||
} | ||
} catch (err) { | ||
_didIteratorError5 = true; | ||
_iteratorError5 = err; | ||
} finally { | ||
try { | ||
if (!_iteratorNormalCompletion5 && _iterator5.return) { | ||
_iterator5.return(); | ||
} | ||
} finally { | ||
if (_didIteratorError5) { | ||
throw _iteratorError5; | ||
} | ||
} | ||
} | ||
let lastPoint = null; | ||
const phaserPath = []; | ||
return phaserPath; | ||
for (const p of channel.path) { | ||
const newPoint = p.clone(); | ||
if (!lastPoint || !newPoint.equals(lastPoint)) phaserPath.push(newPoint); | ||
lastPoint = newPoint; | ||
} | ||
}, { | ||
key: "_calculateNeighbors", | ||
value: function _calculateNeighbors() { | ||
// Fill out the neighbor information for each navpoly | ||
for (var i = 0; i < this._navPolygons.length; i++) { | ||
var navPoly = this._navPolygons[i]; | ||
for (var j = i + 1; j < this._navPolygons.length; j++) { | ||
var otherNavPoly = this._navPolygons[j]; | ||
return phaserPath; | ||
} | ||
// Check if the other navpoly is within range to touch | ||
var d = navPoly.centroid.distance(otherNavPoly.centroid); | ||
if (d > navPoly.boundingRadius + otherNavPoly.boundingRadius) continue; | ||
_calculateNeighbors() { | ||
// Fill out the neighbor information for each navpoly | ||
for (let i = 0; i < this._navPolygons.length; i++) { | ||
const navPoly = this._navPolygons[i]; | ||
// The are in range, so check each edge pairing | ||
var _iteratorNormalCompletion6 = true; | ||
var _didIteratorError6 = false; | ||
var _iteratorError6 = undefined; | ||
for (let j = i + 1; j < this._navPolygons.length; j++) { | ||
const otherNavPoly = this._navPolygons[j]; // Check if the other navpoly is within range to touch | ||
try { | ||
for (var _iterator6 = navPoly.edges[Symbol.iterator](), _step6; !(_iteratorNormalCompletion6 = (_step6 = _iterator6.next()).done); _iteratorNormalCompletion6 = true) { | ||
var edge = _step6.value; | ||
var _iteratorNormalCompletion7 = true; | ||
var _didIteratorError7 = false; | ||
var _iteratorError7 = undefined; | ||
const d = navPoly.centroid.distance(otherNavPoly.centroid); | ||
if (d > navPoly.boundingRadius + otherNavPoly.boundingRadius) continue; // The are in range, so check each edge pairing | ||
try { | ||
for (var _iterator7 = otherNavPoly.edges[Symbol.iterator](), _step7; !(_iteratorNormalCompletion7 = (_step7 = _iterator7.next()).done); _iteratorNormalCompletion7 = true) { | ||
var otherEdge = _step7.value; | ||
for (const edge of navPoly.edges) { | ||
for (const otherEdge of otherNavPoly.edges) { | ||
// If edges aren't collinear, not an option for connecting navpolys | ||
if (!areCollinear(edge, otherEdge)) continue; // If they are collinear, check if they overlap | ||
// If edges aren't collinear, not an option for connecting navpolys | ||
if (!areCollinear(edge, otherEdge)) continue; | ||
const overlap = this._getSegmentOverlap(edge, otherEdge); | ||
// If they are collinear, check if they overlap | ||
var overlap = this._getSegmentOverlap(edge, otherEdge); | ||
if (!overlap) continue; | ||
if (!overlap) continue; // Connections are symmetric! | ||
// Connections are symmetric! | ||
navPoly.neighbors.push(otherNavPoly); | ||
otherNavPoly.neighbors.push(navPoly); | ||
navPoly.neighbors.push(otherNavPoly); | ||
otherNavPoly.neighbors.push(navPoly); // Calculate the portal between the two polygons - this needs to be in | ||
// counter-clockwise order, relative to each polygon | ||
// Calculate the portal between the two polygons - this needs to be in | ||
// counter-clockwise order, relative to each polygon | ||
const [p1, p2] = overlap; | ||
let edgeStartAngle = navPoly.centroid.angle(edge.start); | ||
let a1 = navPoly.centroid.angle(overlap[0]); | ||
let a2 = navPoly.centroid.angle(overlap[1]); | ||
let d1 = angleDifference(edgeStartAngle, a1); | ||
let d2 = angleDifference(edgeStartAngle, a2); | ||
var _overlap = _slicedToArray(overlap, 2), | ||
p1 = _overlap[0], | ||
p2 = _overlap[1]; | ||
if (d1 < d2) { | ||
navPoly.portals.push(new line_Line(p1.x, p1.y, p2.x, p2.y)); | ||
} else { | ||
navPoly.portals.push(new line_Line(p2.x, p2.y, p1.x, p1.y)); | ||
} | ||
var edgeStartAngle = navPoly.centroid.angle(edge.start); | ||
var a1 = navPoly.centroid.angle(overlap[0]); | ||
var a2 = navPoly.centroid.angle(overlap[1]); | ||
var d1 = angleDifference(edgeStartAngle, a1); | ||
var d2 = angleDifference(edgeStartAngle, a2); | ||
if (d1 < d2) { | ||
navPoly.portals.push(new math_line(p1.x, p1.y, p2.x, p2.y)); | ||
} else { | ||
navPoly.portals.push(new math_line(p2.x, p2.y, p1.x, p1.y)); | ||
} | ||
edgeStartAngle = otherNavPoly.centroid.angle(otherEdge.start); | ||
a1 = otherNavPoly.centroid.angle(overlap[0]); | ||
a2 = otherNavPoly.centroid.angle(overlap[1]); | ||
d1 = angleDifference(edgeStartAngle, a1); | ||
d2 = angleDifference(edgeStartAngle, a2); | ||
edgeStartAngle = otherNavPoly.centroid.angle(otherEdge.start); | ||
a1 = otherNavPoly.centroid.angle(overlap[0]); | ||
a2 = otherNavPoly.centroid.angle(overlap[1]); | ||
d1 = angleDifference(edgeStartAngle, a1); | ||
d2 = angleDifference(edgeStartAngle, a2); | ||
if (d1 < d2) { | ||
otherNavPoly.portals.push(new math_line(p1.x, p1.y, p2.x, p2.y)); | ||
} else { | ||
otherNavPoly.portals.push(new math_line(p2.x, p2.y, p1.x, p1.y)); | ||
} | ||
if (d1 < d2) { | ||
otherNavPoly.portals.push(new line_Line(p1.x, p1.y, p2.x, p2.y)); | ||
} else { | ||
otherNavPoly.portals.push(new line_Line(p2.x, p2.y, p1.x, p1.y)); | ||
} // Two convex polygons shouldn't be connected more than once! (Unless | ||
// there are unnecessary vertices...) | ||
// Two convex polygons shouldn't be connected more than once! (Unless | ||
// there are unnecessary vertices...) | ||
} | ||
} catch (err) { | ||
_didIteratorError7 = true; | ||
_iteratorError7 = err; | ||
} finally { | ||
try { | ||
if (!_iteratorNormalCompletion7 && _iterator7.return) { | ||
_iterator7.return(); | ||
} | ||
} finally { | ||
if (_didIteratorError7) { | ||
throw _iteratorError7; | ||
} | ||
} | ||
} | ||
} | ||
} catch (err) { | ||
_didIteratorError6 = true; | ||
_iteratorError6 = err; | ||
} finally { | ||
try { | ||
if (!_iteratorNormalCompletion6 && _iterator6.return) { | ||
_iterator6.return(); | ||
} | ||
} finally { | ||
if (_didIteratorError6) { | ||
throw _iteratorError6; | ||
} | ||
} | ||
} | ||
@@ -1581,109 +1245,94 @@ } | ||
} | ||
} // Check two collinear line segments to see if they overlap by sorting the points. | ||
// Algorithm source: http://stackoverflow.com/a/17152247 | ||
// Check two collinear line segments to see if they overlap by sorting the points. | ||
// Algorithm source: http://stackoverflow.com/a/17152247 | ||
}, { | ||
key: "_getSegmentOverlap", | ||
value: function _getSegmentOverlap(line1, line2) { | ||
var points = [{ line: line1, point: line1.start }, { line: line1, point: line1.end }, { line: line2, point: line2.start }, { line: line2, point: line2.end }]; | ||
points.sort(function (a, b) { | ||
if (a.point.x < b.point.x) return -1;else if (a.point.x > b.point.x) return 1;else { | ||
if (a.point.y < b.point.y) return -1;else if (a.point.y > b.point.y) return 1;else return 0; | ||
} | ||
}); | ||
// If the first two points in the array come from the same line, no overlap | ||
var noOverlap = points[0].line === points[1].line; | ||
// If the two middle points in the array are the same coordinates, then there is a | ||
// single point of overlap. | ||
var singlePointOverlap = points[1].point.equals(points[2].point); | ||
if (noOverlap || singlePointOverlap) return null;else return [points[1].point, points[2].point]; | ||
} | ||
_getSegmentOverlap(line1, line2) { | ||
const points = [{ | ||
line: line1, | ||
point: line1.start | ||
}, { | ||
line: line1, | ||
point: line1.end | ||
}, { | ||
line: line2, | ||
point: line2.start | ||
}, { | ||
line: line2, | ||
point: line2.end | ||
}]; | ||
points.sort(function (a, b) { | ||
if (a.point.x < b.point.x) return -1;else if (a.point.x > b.point.x) return 1;else { | ||
if (a.point.y < b.point.y) return -1;else if (a.point.y > b.point.y) return 1;else return 0; | ||
} | ||
}); // If the first two points in the array come from the same line, no overlap | ||
/** | ||
* Project a point onto a polygon in the shortest distance possible. | ||
* | ||
* @param {Phaser.Point} point The point to project | ||
* @param {NavPoly} navPoly The navigation polygon to test against | ||
* @returns {{point: Phaser.Point, distance: number}} | ||
* | ||
* @private | ||
* @memberof NavMesh | ||
*/ | ||
const noOverlap = points[0].line === points[1].line; // If the two middle points in the array are the same coordinates, then there is a | ||
// single point of overlap. | ||
}, { | ||
key: "_projectPointToPolygon", | ||
value: function _projectPointToPolygon(point, navPoly) { | ||
var closestProjection = null; | ||
var closestDistance = Number.MAX_VALUE; | ||
var _iteratorNormalCompletion8 = true; | ||
var _didIteratorError8 = false; | ||
var _iteratorError8 = undefined; | ||
const singlePointOverlap = points[1].point.equals(points[2].point); | ||
if (noOverlap || singlePointOverlap) return null;else return [points[1].point, points[2].point]; | ||
} | ||
/** | ||
* Project a point onto a polygon in the shortest distance possible. | ||
* | ||
* @param {Phaser.Point} point The point to project | ||
* @param {NavPoly} navPoly The navigation polygon to test against | ||
* @returns {{point: Phaser.Point, distance: number}} | ||
* | ||
* @private | ||
* @memberof NavMesh | ||
*/ | ||
try { | ||
for (var _iterator8 = navPoly.edges[Symbol.iterator](), _step8; !(_iteratorNormalCompletion8 = (_step8 = _iterator8.next()).done); _iteratorNormalCompletion8 = true) { | ||
var edge = _step8.value; | ||
var projectedPoint = this._projectPointToEdge(point, edge); | ||
var d = point.distance(projectedPoint); | ||
if (closestProjection === null || d < closestDistance) { | ||
closestDistance = d; | ||
closestProjection = projectedPoint; | ||
} | ||
} | ||
} catch (err) { | ||
_didIteratorError8 = true; | ||
_iteratorError8 = err; | ||
} finally { | ||
try { | ||
if (!_iteratorNormalCompletion8 && _iterator8.return) { | ||
_iterator8.return(); | ||
} | ||
} finally { | ||
if (_didIteratorError8) { | ||
throw _iteratorError8; | ||
} | ||
} | ||
} | ||
_projectPointToPolygon(point, navPoly) { | ||
let closestProjection = null; | ||
let closestDistance = Number.MAX_VALUE; | ||
return { point: closestProjection, distance: closestDistance }; | ||
} | ||
}, { | ||
key: "_distanceSquared", | ||
value: function _distanceSquared(a, b) { | ||
var dx = b.x - a.x; | ||
var dy = b.y - a.y; | ||
return dx * dx + dy * dy; | ||
} | ||
for (const edge of navPoly.edges) { | ||
const projectedPoint = this._projectPointToEdge(point, edge); | ||
// Project a point onto a line segment | ||
// JS Source: http://stackoverflow.com/questions/849211/shortest-distance-between-a-point-and-a-line-segment | ||
const d = point.distance(projectedPoint); | ||
}, { | ||
key: "_projectPointToEdge", | ||
value: function _projectPointToEdge(point, line) { | ||
var a = line.start; | ||
var b = line.end; | ||
// Consider the parametric equation for the edge's line, p = a + t (b - a). We want to find | ||
// where our point lies on the line by solving for t: | ||
// t = [(p-a) . (b-a)] / |b-a|^2 | ||
var l2 = this._distanceSquared(a, b); | ||
var t = ((point.x - a.x) * (b.x - a.x) + (point.y - a.y) * (b.y - a.y)) / l2; | ||
// We clamp t from [0,1] to handle points outside the segment vw. | ||
t = clamp(t, 0, 1); | ||
// Project onto the segment | ||
var p = new vector_2(a.x + t * (b.x - a.x), a.y + t * (b.y - a.y)); | ||
return p; | ||
if (closestProjection === null || d < closestDistance) { | ||
closestDistance = d; | ||
closestProjection = projectedPoint; | ||
} | ||
} | ||
}]); | ||
return NavMesh; | ||
}(); | ||
return { | ||
point: closestProjection, | ||
distance: closestDistance | ||
}; | ||
} | ||
/* harmony default export */ var navmesh = (navmesh_NavMesh); | ||
_distanceSquared(a, b) { | ||
const dx = b.x - a.x; | ||
const dy = b.y - a.y; | ||
return dx * dx + dy * dy; | ||
} // Project a point onto a line segment | ||
// JS Source: http://stackoverflow.com/questions/849211/shortest-distance-between-a-point-and-a-line-segment | ||
_projectPointToEdge(point, line) { | ||
const a = line.start; | ||
const b = line.end; // Consider the parametric equation for the edge's line, p = a + t (b - a). We want to find | ||
// where our point lies on the line by solving for t: | ||
// t = [(p-a) . (b-a)] / |b-a|^2 | ||
const l2 = this._distanceSquared(a, b); | ||
let t = ((point.x - a.x) * (b.x - a.x) + (point.y - a.y) * (b.y - a.y)) / l2; // We clamp t from [0,1] to handle points outside the segment vw. | ||
t = clamp(t, 0, 1); // Project onto the segment | ||
const p = new Vector2(a.x + t * (b.x - a.x), a.y + t * (b.y - a.y)); | ||
return p; | ||
} | ||
} | ||
// CONCATENATED MODULE: ./index.js | ||
/* harmony default export */ var index = __webpack_exports__["default"] = (navmesh_NavMesh); | ||
/* harmony default export */ var index = __webpack_exports__["default"] = (navmesh); | ||
/***/ }) | ||
@@ -1690,0 +1339,0 @@ /******/ ])["default"]; |
@@ -1,2 +0,2 @@ | ||
!function(t,n){"object"==typeof exports&&"object"==typeof module?module.exports=n():"function"==typeof define&&define.amd?define([],n):"object"==typeof exports?exports.NavMesh=n():t.NavMesh=n()}(window,function(){return function(t){var n={};function e(r){if(n[r])return n[r].exports;var i=n[r]={i:r,l:!1,exports:{}};return t[r].call(i.exports,i,i.exports,e),i.l=!0,i.exports}return e.m=t,e.c=n,e.d=function(t,n,r){e.o(t,n)||Object.defineProperty(t,n,{enumerable:!0,get:r})},e.r=function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},e.t=function(t,n){if(1&n&&(t=e(t)),8&n)return t;if(4&n&&"object"==typeof t&&t&&t.__esModule)return t;var r=Object.create(null);if(e.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:t}),2&n&&"string"!=typeof t)for(var i in t)e.d(r,i,function(n){return t[n]}.bind(null,i));return r},e.n=function(t){var n=t&&t.__esModule?function(){return t.default}:function(){return t};return e.d(n,"a",n),n},e.o=function(t,n){return Object.prototype.hasOwnProperty.call(t,n)},e.p="",e(e.s=1)}([function(t,n,e){var r,i,o;!function(n){"object"==typeof t&&"object"==typeof t.exports?t.exports=n():(i=[],void 0===(o="function"==typeof(r=n)?r.apply(void 0,i):r)||(t.exports=o))}(function(){function t(t){for(var n=t,e=[];n.parent;)e.unshift(n),n=n.parent;return e}var n={search:function(e,r,o,a){e.cleanDirty();var u=(a=a||{}).heuristic||n.heuristics.manhattan,s=a.closest||!1,h=new i(function(t){return t.f}),l=r;for(r.h=u(r,o),e.markDirty(r),h.push(r);h.size()>0;){var c=h.pop();if(c===o)return t(c);c.closed=!0;for(var f=e.neighbors(c),y=0,p=f.length;y<p;++y){var v=f[y];if(!v.closed&&!v.isWall()){var d=c.g+v.getCost(c),g=v.visited;(!g||d<v.g)&&(v.visited=!0,v.parent=c,v.h=v.h||u(v,o),v.g=d,v.f=v.g+v.h,e.markDirty(v),s&&(v.h<l.h||v.h===l.h&&v.g<l.g)&&(l=v),g?h.rescoreElement(v):h.push(v))}}}return s?t(l):[]},heuristics:{manhattan:function(t,n){return Math.abs(n.x-t.x)+Math.abs(n.y-t.y)},diagonal:function(t,n){var e=Math.sqrt(2),r=Math.abs(n.x-t.x),i=Math.abs(n.y-t.y);return 1*(r+i)+(e-2)*Math.min(r,i)}},cleanNode:function(t){t.f=0,t.g=0,t.h=0,t.visited=!1,t.closed=!1,t.parent=null}};function e(t,n){n=n||{},this.nodes=[],this.diagonal=!!n.diagonal,this.grid=[];for(var e=0;e<t.length;e++){this.grid[e]=[];for(var i=0,o=t[e];i<o.length;i++){var a=new r(e,i,o[i]);this.grid[e][i]=a,this.nodes.push(a)}}this.init()}function r(t,n,e){this.x=t,this.y=n,this.weight=e}function i(t){this.content=[],this.scoreFunction=t}return e.prototype.init=function(){this.dirtyNodes=[];for(var t=0;t<this.nodes.length;t++)n.cleanNode(this.nodes[t])},e.prototype.cleanDirty=function(){for(var t=0;t<this.dirtyNodes.length;t++)n.cleanNode(this.dirtyNodes[t]);this.dirtyNodes=[]},e.prototype.markDirty=function(t){this.dirtyNodes.push(t)},e.prototype.neighbors=function(t){var n=[],e=t.x,r=t.y,i=this.grid;return i[e-1]&&i[e-1][r]&&n.push(i[e-1][r]),i[e+1]&&i[e+1][r]&&n.push(i[e+1][r]),i[e]&&i[e][r-1]&&n.push(i[e][r-1]),i[e]&&i[e][r+1]&&n.push(i[e][r+1]),this.diagonal&&(i[e-1]&&i[e-1][r-1]&&n.push(i[e-1][r-1]),i[e+1]&&i[e+1][r-1]&&n.push(i[e+1][r-1]),i[e-1]&&i[e-1][r+1]&&n.push(i[e-1][r+1]),i[e+1]&&i[e+1][r+1]&&n.push(i[e+1][r+1])),n},e.prototype.toString=function(){for(var t=[],n=this.grid,e=0;e<n.length;e++){for(var r=[],i=n[e],o=0;o<i.length;o++)r.push(i[o].weight);t.push(r.join(" "))}return t.join("\n")},r.prototype.toString=function(){return"["+this.x+" "+this.y+"]"},r.prototype.getCost=function(t){return t&&t.x!=this.x&&t.y!=this.y?1.41421*this.weight:this.weight},r.prototype.isWall=function(){return 0===this.weight},i.prototype={push:function(t){this.content.push(t),this.sinkDown(this.content.length-1)},pop:function(){var t=this.content[0],n=this.content.pop();return this.content.length>0&&(this.content[0]=n,this.bubbleUp(0)),t},remove:function(t){var n=this.content.indexOf(t),e=this.content.pop();n!==this.content.length-1&&(this.content[n]=e,this.scoreFunction(e)<this.scoreFunction(t)?this.sinkDown(n):this.bubbleUp(n))},size:function(){return this.content.length},rescoreElement:function(t){this.sinkDown(this.content.indexOf(t))},sinkDown:function(t){for(var n=this.content[t];t>0;){var e=(t+1>>1)-1,r=this.content[e];if(!(this.scoreFunction(n)<this.scoreFunction(r)))break;this.content[e]=n,this.content[t]=r,t=e}},bubbleUp:function(t){for(var n=this.content.length,e=this.content[t],r=this.scoreFunction(e);;){var i,o=t+1<<1,a=o-1,u=null;if(a<n){var s=this.content[a];(i=this.scoreFunction(s))<r&&(u=a)}if(o<n){var h=this.content[o];this.scoreFunction(h)<(null===u?r:i)&&(u=o)}if(null===u)break;this.content[t]=this.content[u],this.content[u]=e,t=u}}},{astar:n,Graph:e}})},function(t,n,e){"use strict";e.r(n);var r=e(0),i=e.n(r),o=function(){function t(t,n){for(var e=0;e<n.length;e++){var r=n[e];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(t,r.key,r)}}return function(n,e,r){return e&&t(n.prototype,e),r&&t(n,r),n}}();var a=function(){function t(n,e){!function(t,n){if(!(t instanceof n))throw new TypeError("Cannot call a class as a function")}(this,t),this.x=n||0,this.y=e||0}return o(t,[{key:"equals",value:function(t){return this.x===t.x&&this.y===t.y}},{key:"angle",value:function(t){return Math.atan2(t.y-this.y,t.x-this.x)}},{key:"distance",value:function(t){var n=t.x-this.x,e=t.y-this.y;return Math.sqrt(n*n+e*e)}},{key:"add",value:function(t){this.x+=t.x,this.y+=t.y}},{key:"subtract",value:function(t){this.x-=t.x,this.y-=t.y}},{key:"clone",value:function(){return new t(this.x,this.y)}}]),t}(),u=function(){function t(t,n){for(var e=0;e<n.length;e++){var r=n[e];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(t,r.key,r)}}return function(n,e,r){return e&&t(n.prototype,e),r&&t(n,r),n}}();var s=function(){function t(n,e){!function(t,n){if(!(t instanceof n))throw new TypeError("Cannot call a class as a function")}(this,t),this.id=n,this.polygon=e,this.edges=e.edges,this.neighbors=[],this.portals=[],this.centroid=this.calculateCentroid(),this.boundingRadius=this.calculateRadius(),this.weight=1}return u(t,[{key:"getPoints",value:function(){return this.polygon.points}},{key:"contains",value:function(t){return this.polygon.contains(t.x,t.y)||this.isPointOnEdge(t)}},{key:"calculateCentroid",value:function(){var t=new a(0,0),n=this.polygon.points.length;return this.polygon.points.forEach(function(n){return t.add(n)}),t.x/=n,t.y/=n,t}},{key:"calculateRadius",value:function(){var t=0,n=!0,e=!1,r=void 0;try{for(var i,o=this.polygon.points[Symbol.iterator]();!(n=(i=o.next()).done);n=!0){var a=i.value,u=this.centroid.distance(a);u>t&&(t=u)}}catch(t){e=!0,r=t}finally{try{!n&&o.return&&o.return()}finally{if(e)throw r}}return t}},{key:"isPointOnEdge",value:function(t){var n=t.x,e=t.y,r=!0,i=!1,o=void 0;try{for(var a,u=this.edges[Symbol.iterator]();!(r=(a=u.next()).done);r=!0){if(a.value.pointOnSegment(n,e))return!0}}catch(t){i=!0,o=t}finally{try{!r&&u.return&&u.return()}finally{if(i)throw o}}return!1}},{key:"destroy",value:function(){this.neighbors=[],this.portals=[]}},{key:"toString",value:function(){return"NavPoly(id: "+this.id+" at: "+this.centroid+")"}},{key:"isWall",value:function(){return 0===this.weight}},{key:"centroidDistance",value:function(t){return this.centroid.distance(t.centroid)}},{key:"getCost",value:function(t){return this.centroidDistance(t)}}]),t}(),h=function(){function t(t,n){for(var e=0;e<n.length;e++){var r=n[e];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(t,r.key,r)}}return function(n,e,r){return e&&t(n.prototype,e),r&&t(n,r),n}}();var l=function(){function t(n){!function(t,n){if(!(t instanceof n))throw new TypeError("Cannot call a class as a function")}(this,t),this.nodes=n,this.init()}return h(t,[{key:"neighbors",value:function(t){return t.neighbors}},{key:"navHeuristic",value:function(t,n){return t.centroidDistance(n)}},{key:"destroy",value:function(){this.cleanDirty(),this.nodes=[]}}]),t}();l.prototype.init=i.a.Graph.prototype.init,l.prototype.cleanDirty=i.a.Graph.prototype.cleanDirty,l.prototype.markDirty=i.a.Graph.prototype.markDirty;var c=l;function f(t,n,e){var r=n.x-t.x,i=n.y-t.y;return(e.x-t.x)*i-r*(e.y-t.y)}function y(t,n){var e=arguments.length>2&&void 0!==arguments[2]?arguments[2]:1e-4;return Math.abs(t-n)<=e}function p(t,n){var e=t-n,r=e+Math.PI,i=2*Math.PI;return e=r-Math.floor(r/i)*i,e-=Math.PI}function v(t,n){var e=arguments.length>2&&void 0!==arguments[2]?arguments[2]:1e-4,r=f(t.start,t.end,n.start),i=f(t.start,t.end,n.end);return!(!y(r,0,e)||!y(i,0,e))}var d=function(){function t(t,n){for(var e=0;e<n.length;e++){var r=n[e];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(t,r.key,r)}}return function(n,e,r){return e&&t(n.prototype,e),r&&t(n,r),n}}();var g=function(){function t(){!function(t,n){if(!(t instanceof n))throw new TypeError("Cannot call a class as a function")}(this,t),this.portals=[]}return d(t,[{key:"push",value:function(t){var n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null;null===n&&(n=t),this.portals.push({left:t,right:n})}},{key:"stringPull",value:function(){var t,n,e,r=this.portals,i=[],o=0,a=0,u=0;t=r[0].left,n=r[0].left,e=r[0].right,i.push(t);for(var s=1;s<r.length;s++){var h=r[s].left,l=r[s].right;if(f(t,e,l)<=0){if(!(t.equals(e)||f(t,n,l)>0)){i.push(n),n=t=n,e=t,a=o=a,u=o,s=o;continue}e=l,u=s}if(f(t,n,h)>=0){if(!(t.equals(n)||f(t,e,h)<0)){i.push(e),n=t=e,e=t,a=o=u,u=o,s=o;continue}n=h,a=s}}return 0!==i.length&&i[i.length-1].equals(r[r.length-1].left)||i.push(r[r.length-1].left),this.path=i,i}}]),t}(),b=function(){function t(t,n){for(var e=0;e<n.length;e++){var r=n[e];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(t,r.key,r)}}return function(n,e,r){return e&&t(n.prototype,e),r&&t(n,r),n}}();var x=function(){function t(n,e,r,i){!function(t,n){if(!(t instanceof n))throw new TypeError("Cannot call a class as a function")}(this,t),this.start=new a(n,e),this.end=new a(r,i),this.left=Math.min(n,r),this.right=Math.max(n,r),this.top=Math.min(e,i),this.bottom=Math.max(e,i)}return b(t,[{key:"pointOnSegment",value:function(t,n){return t>=this.left&&t<=this.right&&n>=this.top&&n<=this.bottom&&this.pointOnLine(t,n)}},{key:"pointOnLine",value:function(t,n){return(t-this.left)*(this.bottom-this.top)==(this.right-this.left)*(n-this.top)}}]),t}(),m=function(){function t(t,n){for(var e=0;e<n.length;e++){var r=n[e];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(t,r.key,r)}}return function(n,e,r){return e&&t(n.prototype,e),r&&t(n,r),n}}();var w=function(){function t(n){var e=!(arguments.length>1&&void 0!==arguments[1])||arguments[1];!function(t,n){if(!(t instanceof n))throw new TypeError("Cannot call a class as a function")}(this,t),this.points=n,this.edges=[];for(var r=1;r<n.length;r++){var i=n[r-1],o=n[r];this.edges.push(new x(i.x,i.y,o.x,o.y))}if(e){var a=n[0],u=n[n.length-1];this.edges.push(new x(a.x,a.y,u.x,u.y))}}return m(t,[{key:"contains",value:function(t,n){for(var e=!1,r=-1,i=this.points.length-1;++r<this.points.length;i=r){var o=this.points[r].x,a=this.points[r].y,u=this.points[i].x,s=this.points[i].y;(a<=n&&n<s||s<=n&&n<a)&&t<(u-o)*(n-a)/(s-a)+o&&(e=!e)}return e}}]),t}(),k=function(){return function(t,n){if(Array.isArray(t))return t;if(Symbol.iterator in Object(t))return function(t,n){var e=[],r=!0,i=!1,o=void 0;try{for(var a,u=t[Symbol.iterator]();!(r=(a=u.next()).done)&&(e.push(a.value),!n||e.length!==n);r=!0);}catch(t){i=!0,o=t}finally{try{!r&&u.return&&u.return()}finally{if(i)throw o}}return e}(t,n);throw new TypeError("Invalid attempt to destructure non-iterable instance")}}(),P=function(){function t(t,n){for(var e=0;e<n.length;e++){var r=n[e];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(t,r.key,r)}}return function(n,e,r){return e&&t(n.prototype,e),r&&t(n,r),n}}();var _=function(){function t(n){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0;!function(t,n){if(!(t instanceof n))throw new TypeError("Cannot call a class as a function")}(this,t),this._meshShrinkAmount=e;var r=n.map(function(t){var n=t.map(function(t){return new a(t.x,t.y)});return new w(n)});this._navPolygons=r.map(function(t,n){return new s(n,t)}),this._calculateNeighbors(),this._graph=new c(this._navPolygons)}return P(t,[{key:"getPolygons",value:function(){return this._navPolygons}},{key:"destroy",value:function(){this._graph.destroy();var t=!0,n=!1,e=void 0;try{for(var r,i=this._navPolygons[Symbol.iterator]();!(t=(r=i.next()).done);t=!0){r.value.destroy()}}catch(t){n=!0,e=t}finally{try{!t&&i.return&&i.return()}finally{if(n)throw e}}this._navPolygons=[]}},{key:"findPath",value:function(t,n){var e=null,r=null,o=Number.MAX_VALUE,u=Number.MAX_VALUE,s=void 0,h=void 0,l=new a(t.x,t.y),c=new a(n.x,n.y),f=!0,y=!1,p=void 0;try{for(var v,d=this._navPolygons[Symbol.iterator]();!(f=(v=d.next()).done);f=!0){var b=v.value;h=b.boundingRadius,(s=b.centroid.distance(l))<=o&&s<=h&&b.contains(l)&&(e=b,o=s),(s=b.centroid.distance(c))<=u&&s<=h&&b.contains(c)&&(r=b,u=s)}}catch(t){y=!0,p=t}finally{try{!f&&d.return&&d.return()}finally{if(y)throw p}}if(!e&&this._meshShrinkAmount>0){var x=!0,m=!1,w=void 0;try{for(var k,P=this._navPolygons[Symbol.iterator]();!(x=(k=P.next()).done);x=!0){var _=k.value;if(h=_.boundingRadius+this._meshShrinkAmount,(s=_.centroid.distance(l))<=h){var S=this._projectPointToPolygon(l,_).distance;S<=this._meshShrinkAmount&&S<o&&(e=_,o=S)}}}catch(t){m=!0,w=t}finally{try{!x&&P.return&&P.return()}finally{if(m)throw w}}}if(!r&&this._meshShrinkAmount>0){var j=!0,M=!1,O=void 0;try{for(var E,D=this._navPolygons[Symbol.iterator]();!(j=(E=D.next()).done);j=!0){var N=E.value;if(h=N.boundingRadius+this._meshShrinkAmount,(s=N.centroid.distance(c))<=h){var A=this._projectPointToPolygon(c,N).distance;A<=this._meshShrinkAmount&&A<u&&(r=N,u=A)}}}catch(t){M=!0,O=t}finally{try{!j&&D.return&&D.return()}finally{if(M)throw O}}}if(!e||!r)return null;if(e===r)return[l,c];var T=i.a.astar.search(this._graph,e,r,{heuristic:this._graph.navHeuristic});if(0===T.length)return null;T.unshift(e);var C=new g;C.push(l);for(var q=0;q<T.length-1;q++){for(var F=T[q],R=T[q+1],U=null,L=0;L<F.neighbors.length;L++)F.neighbors[L].id===R.id&&(U=F.portals[L]);C.push(U.start,U.end)}C.push(c),C.stringPull();var G=null,I=[],V=!0,W=!1,X=void 0;try{for(var z,H=C.path[Symbol.iterator]();!(V=(z=H.next()).done);V=!0){var B=z.value.clone();G&&B.equals(G)||I.push(B),G=B}}catch(t){W=!0,X=t}finally{try{!V&&H.return&&H.return()}finally{if(W)throw X}}return I}},{key:"_calculateNeighbors",value:function(){for(var t=0;t<this._navPolygons.length;t++)for(var n=this._navPolygons[t],e=t+1;e<this._navPolygons.length;e++){var r=this._navPolygons[e];if(!(n.centroid.distance(r.centroid)>n.boundingRadius+r.boundingRadius)){var i=!0,o=!1,a=void 0;try{for(var u,s=n.edges[Symbol.iterator]();!(i=(u=s.next()).done);i=!0){var h=u.value,l=!0,c=!1,f=void 0;try{for(var y,d=r.edges[Symbol.iterator]();!(l=(y=d.next()).done);l=!0){var g=y.value;if(v(h,g)){var b=this._getSegmentOverlap(h,g);if(b){n.neighbors.push(r),r.neighbors.push(n);var m=k(b,2),w=m[0],P=m[1],_=n.centroid.angle(h.start),S=n.centroid.angle(b[0]),j=n.centroid.angle(b[1]),M=p(_,S),O=p(_,j);M<O?n.portals.push(new x(w.x,w.y,P.x,P.y)):n.portals.push(new x(P.x,P.y,w.x,w.y)),_=r.centroid.angle(g.start),S=r.centroid.angle(b[0]),j=r.centroid.angle(b[1]),(M=p(_,S))<(O=p(_,j))?r.portals.push(new x(w.x,w.y,P.x,P.y)):r.portals.push(new x(P.x,P.y,w.x,w.y))}}}}catch(t){c=!0,f=t}finally{try{!l&&d.return&&d.return()}finally{if(c)throw f}}}}catch(t){o=!0,a=t}finally{try{!i&&s.return&&s.return()}finally{if(o)throw a}}}}}},{key:"_getSegmentOverlap",value:function(t,n){var e=[{line:t,point:t.start},{line:t,point:t.end},{line:n,point:n.start},{line:n,point:n.end}];e.sort(function(t,n){return t.point.x<n.point.x?-1:t.point.x>n.point.x?1:t.point.y<n.point.y?-1:t.point.y>n.point.y?1:0});var r=e[0].line===e[1].line,i=e[1].point.equals(e[2].point);return r||i?null:[e[1].point,e[2].point]}},{key:"_projectPointToPolygon",value:function(t,n){var e=null,r=Number.MAX_VALUE,i=!0,o=!1,a=void 0;try{for(var u,s=n.edges[Symbol.iterator]();!(i=(u=s.next()).done);i=!0){var h=u.value,l=this._projectPointToEdge(t,h),c=t.distance(l);(null===e||c<r)&&(r=c,e=l)}}catch(t){o=!0,a=t}finally{try{!i&&s.return&&s.return()}finally{if(o)throw a}}return{point:e,distance:r}}},{key:"_distanceSquared",value:function(t,n){var e=n.x-t.x,r=n.y-t.y;return e*e+r*r}},{key:"_projectPointToEdge",value:function(t,n){var e=n.start,r=n.end,i=this._distanceSquared(e,r),o=((t.x-e.x)*(r.x-e.x)+(t.y-e.y)*(r.y-e.y))/i;return o=function(t,n,e){return t<n&&(t=n),t>e&&(t=e),t}(o,0,1),new a(e.x+o*(r.x-e.x),e.y+o*(r.y-e.y))}}]),t}();n.default=_}]).default}); | ||
!function(t,n){"object"==typeof exports&&"object"==typeof module?module.exports=n():"function"==typeof define&&define.amd?define([],n):"object"==typeof exports?exports.NavMesh=n():t.NavMesh=n()}("undefined"!=typeof self?self:this,function(){return function(t){var n={};function i(e){if(n[e])return n[e].exports;var o=n[e]={i:e,l:!1,exports:{}};return t[e].call(o.exports,o,o.exports,i),o.l=!0,o.exports}return i.m=t,i.c=n,i.d=function(t,n,e){i.o(t,n)||Object.defineProperty(t,n,{enumerable:!0,get:e})},i.r=function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},i.t=function(t,n){if(1&n&&(t=i(t)),8&n)return t;if(4&n&&"object"==typeof t&&t&&t.__esModule)return t;var e=Object.create(null);if(i.r(e),Object.defineProperty(e,"default",{enumerable:!0,value:t}),2&n&&"string"!=typeof t)for(var o in t)i.d(e,o,function(n){return t[n]}.bind(null,o));return e},i.n=function(t){var n=t&&t.__esModule?function(){return t.default}:function(){return t};return i.d(n,"a",n),n},i.o=function(t,n){return Object.prototype.hasOwnProperty.call(t,n)},i.p="",i(i.s=1)}([function(t,n,i){var e,o,s;!function(n){"object"==typeof t.exports?t.exports=n():(o=[],void 0===(s="function"==typeof(e=n)?e.apply(void 0,o):e)||(t.exports=s))}(function(){function t(t){for(var n=t,i=[];n.parent;)i.unshift(n),n=n.parent;return i}var n={search:function(i,e,s,r){i.cleanDirty();var h=(r=r||{}).heuristic||n.heuristics.manhattan,c=r.closest||!1,u=new o(function(t){return t.f}),a=e;for(e.h=h(e,s),i.markDirty(e),u.push(e);u.size()>0;){var l=u.pop();if(l===s)return t(l);l.closed=!0;for(var p=i.neighbors(l),f=0,d=p.length;f<d;++f){var g=p[f];if(!g.closed&&!g.isWall()){var y=l.g+g.getCost(l),x=g.visited;(!x||y<g.g)&&(g.visited=!0,g.parent=l,g.h=g.h||h(g,s),g.g=y,g.f=g.g+g.h,i.markDirty(g),c&&(g.h<a.h||g.h===a.h&&g.g<a.g)&&(a=g),x?u.rescoreElement(g):u.push(g))}}}return c?t(a):[]},heuristics:{manhattan:function(t,n){return Math.abs(n.x-t.x)+Math.abs(n.y-t.y)},diagonal:function(t,n){var i=Math.sqrt(2),e=Math.abs(n.x-t.x),o=Math.abs(n.y-t.y);return 1*(e+o)+(i-2)*Math.min(e,o)}},cleanNode:function(t){t.f=0,t.g=0,t.h=0,t.visited=!1,t.closed=!1,t.parent=null}};function i(t,n){n=n||{},this.nodes=[],this.diagonal=!!n.diagonal,this.grid=[];for(var i=0;i<t.length;i++){this.grid[i]=[];for(var o=0,s=t[i];o<s.length;o++){var r=new e(i,o,s[o]);this.grid[i][o]=r,this.nodes.push(r)}}this.init()}function e(t,n,i){this.x=t,this.y=n,this.weight=i}function o(t){this.content=[],this.scoreFunction=t}return i.prototype.init=function(){this.dirtyNodes=[];for(var t=0;t<this.nodes.length;t++)n.cleanNode(this.nodes[t])},i.prototype.cleanDirty=function(){for(var t=0;t<this.dirtyNodes.length;t++)n.cleanNode(this.dirtyNodes[t]);this.dirtyNodes=[]},i.prototype.markDirty=function(t){this.dirtyNodes.push(t)},i.prototype.neighbors=function(t){var n=[],i=t.x,e=t.y,o=this.grid;return o[i-1]&&o[i-1][e]&&n.push(o[i-1][e]),o[i+1]&&o[i+1][e]&&n.push(o[i+1][e]),o[i]&&o[i][e-1]&&n.push(o[i][e-1]),o[i]&&o[i][e+1]&&n.push(o[i][e+1]),this.diagonal&&(o[i-1]&&o[i-1][e-1]&&n.push(o[i-1][e-1]),o[i+1]&&o[i+1][e-1]&&n.push(o[i+1][e-1]),o[i-1]&&o[i-1][e+1]&&n.push(o[i-1][e+1]),o[i+1]&&o[i+1][e+1]&&n.push(o[i+1][e+1])),n},i.prototype.toString=function(){for(var t=[],n=this.grid,i=0;i<n.length;i++){for(var e=[],o=n[i],s=0;s<o.length;s++)e.push(o[s].weight);t.push(e.join(" "))}return t.join("\n")},e.prototype.toString=function(){return"["+this.x+" "+this.y+"]"},e.prototype.getCost=function(t){return t&&t.x!=this.x&&t.y!=this.y?1.41421*this.weight:this.weight},e.prototype.isWall=function(){return 0===this.weight},o.prototype={push:function(t){this.content.push(t),this.sinkDown(this.content.length-1)},pop:function(){var t=this.content[0],n=this.content.pop();return this.content.length>0&&(this.content[0]=n,this.bubbleUp(0)),t},remove:function(t){var n=this.content.indexOf(t),i=this.content.pop();n!==this.content.length-1&&(this.content[n]=i,this.scoreFunction(i)<this.scoreFunction(t)?this.sinkDown(n):this.bubbleUp(n))},size:function(){return this.content.length},rescoreElement:function(t){this.sinkDown(this.content.indexOf(t))},sinkDown:function(t){for(var n=this.content[t];t>0;){var i=(t+1>>1)-1,e=this.content[i];if(!(this.scoreFunction(n)<this.scoreFunction(e)))break;this.content[i]=n,this.content[t]=e,t=i}},bubbleUp:function(t){for(var n=this.content.length,i=this.content[t],e=this.scoreFunction(i);;){var o,s=t+1<<1,r=s-1,h=null;if(r<n){var c=this.content[r];(o=this.scoreFunction(c))<e&&(h=r)}if(s<n){var u=this.content[s];this.scoreFunction(u)<(null===h?e:o)&&(h=s)}if(null===h)break;this.content[t]=this.content[h],this.content[h]=i,t=h}}},{astar:n,Graph:i}})},function(t,n,i){"use strict";i.r(n);var e=i(0),o=i.n(e);class s{constructor(t,n){this.x=t||0,this.y=n||0}equals(t){return this.x===t.x&&this.y===t.y}angle(t){return Math.atan2(t.y-this.y,t.x-this.x)}distance(t){const n=t.x-this.x,i=t.y-this.y;return Math.sqrt(n*n+i*i)}add(t){this.x+=t.x,this.y+=t.y}subtract(t){this.x-=t.x,this.y-=t.y}clone(){return new s(this.x,this.y)}}class r{constructor(t,n){this.id=t,this.polygon=n,this.edges=n.edges,this.neighbors=[],this.portals=[],this.centroid=this.calculateCentroid(),this.boundingRadius=this.calculateRadius(),this.weight=1}getPoints(){return this.polygon.points}contains(t){return this.polygon.contains(t.x,t.y)||this.isPointOnEdge(t)}calculateCentroid(){const t=new s(0,0),n=this.polygon.points.length;return this.polygon.points.forEach(n=>t.add(n)),t.x/=n,t.y/=n,t}calculateRadius(){let t=0;for(const n of this.polygon.points){const i=this.centroid.distance(n);i>t&&(t=i)}return t}isPointOnEdge({x:t,y:n}){for(const i of this.edges)if(i.pointOnSegment(t,n))return!0;return!1}destroy(){this.neighbors=[],this.portals=[]}toString(){return`NavPoly(id: ${this.id} at: ${this.centroid})`}isWall(){return 0===this.weight}centroidDistance(t){return this.centroid.distance(t.centroid)}getCost(t){return this.centroidDistance(t)}}class h{constructor(t){this.nodes=t,this.init()}neighbors(t){return t.neighbors}navHeuristic(t,n){return t.centroidDistance(n)}destroy(){this.cleanDirty(),this.nodes=[]}}h.prototype.init=o.a.Graph.prototype.init,h.prototype.cleanDirty=o.a.Graph.prototype.cleanDirty,h.prototype.markDirty=o.a.Graph.prototype.markDirty;var c=h;function u(t,n,i){const e=n.x-t.x,o=n.y-t.y;return(i.x-t.x)*o-e*(i.y-t.y)}function a(t,n,i=1e-4){return Math.abs(t-n)<=i}function l(t,n){let i=t-n;const e=i+Math.PI,o=2*Math.PI;return i=e-Math.floor(e/o)*o,i-=Math.PI}function p(t,n,i=1e-4){const e=u(t.start,t.end,n.start),o=u(t.start,t.end,n.end);return!(!a(e,0,i)||!a(o,0,i))}var f=class{constructor(){this.portals=[]}push(t,n=null){null===n&&(n=t),this.portals.push({left:t,right:n})}stringPull(){var t,n,i,e=this.portals,o=[],s=0,r=0,h=0;t=e[0].left,n=e[0].left,i=e[0].right,o.push(t);for(var c=1;c<e.length;c++){var a=e[c].left,l=e[c].right;if(u(t,i,l)<=0){if(!(t.equals(i)||u(t,n,l)>0)){o.push(n),n=t=n,i=t,r=s=r,h=s,c=s;continue}i=l,h=c}if(u(t,n,a)>=0){if(!(t.equals(n)||u(t,i,a)<0)){o.push(i),n=t=i,i=t,r=s=h,h=s,c=s;continue}n=a,r=c}}return 0!==o.length&&o[o.length-1].equals(e[e.length-1].left)||o.push(e[e.length-1].left),this.path=o,o}};class d{constructor(t,n,i,e){this.start=new s(t,n),this.end=new s(i,e),this.left=Math.min(t,i),this.right=Math.max(t,i),this.top=Math.min(n,e),this.bottom=Math.max(n,e)}pointOnSegment(t,n){return t>=this.left&&t<=this.right&&n>=this.top&&n<=this.bottom&&this.pointOnLine(t,n)}pointOnLine(t,n){return(t-this.left)*(this.bottom-this.top)==(this.right-this.left)*(n-this.top)}}class g{constructor(t,n=!0){this.points=t,this.edges=[];for(let n=1;n<t.length;n++){const i=t[n-1],e=t[n];this.edges.push(new d(i.x,i.y,e.x,e.y))}if(n){const n=t[0],i=t[t.length-1];this.edges.push(new d(n.x,n.y,i.x,i.y))}}contains(t,n){let i=!1;for(let e=-1,o=this.points.length-1;++e<this.points.length;o=e){const s=this.points[e].x,r=this.points[e].y,h=this.points[o].x,c=this.points[o].y;(r<=n&&n<c||c<=n&&n<r)&&t<(h-s)*(n-r)/(c-r)+s&&(i=!i)}return i}}n.default=class{constructor(t,n=0){this._meshShrinkAmount=n;const i=t.map(t=>{const n=t.map(t=>new s(t.x,t.y));return new g(n)});this._navPolygons=i.map((t,n)=>new r(n,t)),this._calculateNeighbors(),this._graph=new c(this._navPolygons)}getPolygons(){return this._navPolygons}destroy(){this._graph.destroy();for(const t of this._navPolygons)t.destroy();this._navPolygons=[]}findPath(t,n){let i,e,r=null,h=null,c=Number.MAX_VALUE,u=Number.MAX_VALUE;const a=new s(t.x,t.y),l=new s(n.x,n.y);for(const t of this._navPolygons)e=t.boundingRadius,(i=t.centroid.distance(a))<=c&&i<=e&&t.contains(a)&&(r=t,c=i),(i=t.centroid.distance(l))<=u&&i<=e&&t.contains(l)&&(h=t,u=i);if(!r&&this._meshShrinkAmount>0)for(const t of this._navPolygons)if(e=t.boundingRadius+this._meshShrinkAmount,(i=t.centroid.distance(a))<=e){const{distance:n}=this._projectPointToPolygon(a,t);n<=this._meshShrinkAmount&&n<c&&(r=t,c=n)}if(!h&&this._meshShrinkAmount>0)for(const t of this._navPolygons)if(e=t.boundingRadius+this._meshShrinkAmount,(i=t.centroid.distance(l))<=e){const{distance:n}=this._projectPointToPolygon(l,t);n<=this._meshShrinkAmount&&n<u&&(h=t,u=n)}if(!r||!h)return null;if(r===h)return[a,l];const p=o.a.astar.search(this._graph,r,h,{heuristic:this._graph.navHeuristic});if(0===p.length)return null;p.unshift(r);const d=new f;d.push(a);for(let t=0;t<p.length-1;t++){const n=p[t],i=p[t+1];let e=null;for(let t=0;t<n.neighbors.length;t++)n.neighbors[t].id===i.id&&(e=n.portals[t]);d.push(e.start,e.end)}d.push(l),d.stringPull();let g=null;const y=[];for(const t of d.path){const n=t.clone();g&&n.equals(g)||y.push(n),g=n}return y}_calculateNeighbors(){for(let t=0;t<this._navPolygons.length;t++){const n=this._navPolygons[t];for(let i=t+1;i<this._navPolygons.length;i++){const t=this._navPolygons[i];if(!(n.centroid.distance(t.centroid)>n.boundingRadius+t.boundingRadius))for(const i of n.edges)for(const e of t.edges){if(!p(i,e))continue;const o=this._getSegmentOverlap(i,e);if(!o)continue;n.neighbors.push(t),t.neighbors.push(n);const[s,r]=o;let h=n.centroid.angle(i.start),c=n.centroid.angle(o[0]),u=n.centroid.angle(o[1]),a=l(h,c),f=l(h,u);a<f?n.portals.push(new d(s.x,s.y,r.x,r.y)):n.portals.push(new d(r.x,r.y,s.x,s.y)),h=t.centroid.angle(e.start),c=t.centroid.angle(o[0]),u=t.centroid.angle(o[1]),(a=l(h,c))<(f=l(h,u))?t.portals.push(new d(s.x,s.y,r.x,r.y)):t.portals.push(new d(r.x,r.y,s.x,s.y))}}}}_getSegmentOverlap(t,n){const i=[{line:t,point:t.start},{line:t,point:t.end},{line:n,point:n.start},{line:n,point:n.end}];i.sort(function(t,n){return t.point.x<n.point.x?-1:t.point.x>n.point.x?1:t.point.y<n.point.y?-1:t.point.y>n.point.y?1:0});const e=i[0].line===i[1].line,o=i[1].point.equals(i[2].point);return e||o?null:[i[1].point,i[2].point]}_projectPointToPolygon(t,n){let i=null,e=Number.MAX_VALUE;for(const o of n.edges){const n=this._projectPointToEdge(t,o),s=t.distance(n);(null===i||s<e)&&(e=s,i=n)}return{point:i,distance:e}}_distanceSquared(t,n){const i=n.x-t.x,e=n.y-t.y;return i*i+e*e}_projectPointToEdge(t,n){const i=n.start,e=n.end,o=this._distanceSquared(i,e);let r=((t.x-i.x)*(e.x-i.x)+(t.y-i.y)*(e.y-i.y))/o;return r=function(t,n,i){return t<n&&(t=n),t>i&&(t=i),t}(r,0,1),new s(i.x+r*(e.x-i.x),i.y+r*(e.y-i.y))}}}]).default}); | ||
//# sourceMappingURL=navmesh.min.js.map |
{ | ||
"name": "navmesh", | ||
"version": "2.0.2", | ||
"version": "2.0.3", | ||
"description": "A library for fast pathfinding using navigation meshes in JS", | ||
@@ -16,6 +16,6 @@ "main": "dist/navmesh.min.js", | ||
"devDependencies": { | ||
"babel-core": "^6.26.3", | ||
"@babel/core": "^7.5.5", | ||
"@babel/preset-env": "^7.5.5", | ||
"babel-jest": "^23.2.0", | ||
"babel-loader": "^7.1.4", | ||
"babel-preset-env": "^1.7.0", | ||
"babel-loader": "^8.0.6", | ||
"jest": "^23.2.0", | ||
@@ -43,3 +43,4 @@ "uglifyjs-webpack-plugin": "^1.2.7", | ||
}, | ||
"homepage": "https://github.com/mikewesthad/phaser-navmesh-plugin#readme" | ||
"homepage": "https://github.com/mikewesthad/phaser-navmesh-plugin#readme", | ||
"gitHead": "f5fdc676b88a7ac85cf2c169428efb7851de7f5d" | ||
} |
@@ -9,4 +9,8 @@ # NavMesh | ||
Version 2.0.3 - 2019-08-04 | ||
- Bug: fixed webpack config so that it applied babel transform and so that it worked under node environments, thanks to [@will-hart](https://github.com/will-hart) | ||
Version 2.0.2 - 2018-01-03 | ||
- Initial publish of changelog |
@@ -21,3 +21,4 @@ /* eslint-env node */ | ||
libraryTarget: "umd", | ||
libraryExport: "default" | ||
libraryExport: "default", | ||
globalObject: '(typeof self !== "undefined" ? self : this)' | ||
}, | ||
@@ -32,3 +33,3 @@ optimization: { | ||
exclude: /node_modules/, | ||
use: ["babel-loader"] | ||
use: { loader: "babel-loader", options: { root: "../../" } } | ||
} | ||
@@ -35,0 +36,0 @@ ] |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
19
16
206449
1969