UNPKG

phaser-raycaster

Version:
1,201 lines (1,129 loc) 192 kB
(function webpackUniversalModuleDefinition(root, factory) { if(typeof exports === 'object' && typeof module === 'object') module.exports = factory(); else if(typeof define === 'function' && define.amd) define("PhaserRaycaster", [], factory); else if(typeof exports === 'object') exports["PhaserRaycaster"] = factory(); else root["PhaserRaycaster"] = factory(); })(self, function() { return /******/ (function() { // webpackBootstrap /******/ var __webpack_modules__ = ({ /***/ "./src/main.js": /*!*********************!*\ !*** ./src/main.js ***! \*********************/ /***/ (function(module, __unused_webpack_exports, __webpack_require__) { function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); } function _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); } function _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } } function _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", { writable: !1 }), e; } function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; } function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } function _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); } function _possibleConstructorReturn(t, e) { if (e && ("object" == _typeof(e) || "function" == typeof e)) return e; if (void 0 !== e) throw new TypeError("Derived constructors may only return object or undefined"); return _assertThisInitialized(t); } function _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); return e; } function _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); } function _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); } function _inherits(t, e) { if ("function" != typeof e && null !== e) throw new TypeError("Super expression must either be null or a function"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, "prototype", { writable: !1 }), e && _setPrototypeOf(t, e); } function _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); } /** * @author Marcin Walczak <contact@marcin-walczak.pl> * @copyright 2023 Marcin Walczak * @license {@link https://github.com/wiserim/phaser-raycaster/blob/master/LICENSE|MIT License} */ /** * Point object * @typedef {Object} Point * @property {number} x * @property {number} y */ /** * @classdesc * * Raycaster plugin class. * * @namespace PhaserRaycaster * @class PhaserRaycaster * @extends Phaser.Plugins.ScenePlugin * @constructor * @since 0.6.0 * * @param {Phaser.Scene} scene * @param {Phaser.Plugins.PluginManager} pluginManager */ var PhaserRaycaster = /*#__PURE__*/function (_Phaser$Plugins$Scene) { function PhaserRaycaster(scene, pluginManager) { var _this; _classCallCheck(this, PhaserRaycaster); _this = _callSuper(this, PhaserRaycaster, [scene, pluginManager]); _this._Raycaster = (__webpack_require__(/*! ./raycaster-core.js */ "./src/raycaster-core.js").Raycaster); return _this; } /** * Create Raycaster object. * * @method PhaserRaycaster#createRaycaster * @memberof PhaserRaycaster * @instance * @since 0.6.0 * * @param {object} [options] - Raycaster's congfiguration options. May include: * @param {number} [options.mapSegmentCount = 0] - Number of segments of circle maps. If set to 0, map will be teste * @param {(object|object[])} [options.objects] - Game object or array of game objects to map. * @param {Phaser.Geom.Rectangle} [options.boundingBox] - Raycaster's bounding box. If not passed, {@link Raycaster Raycaster} will set it's bounding box based on Arcade Physics / Matter physics world bounds. * @param {boolean} [options.autoUpdate = true] - If set true, automatically update dynamic maps on scene update event. * @param {boolean|object} [options.debug] - Enable debug mode or configure it {@link Raycaster#debugOptions debugOptions}. * * @return {Raycaster} {@link Raycaster Raycaster} instance */ _inherits(PhaserRaycaster, _Phaser$Plugins$Scene); return _createClass(PhaserRaycaster, [{ key: "createRaycaster", value: function createRaycaster() { var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; options.scene = this.scene; return new this._Raycaster(options); } }]); }(Phaser.Plugins.ScenePlugin); //Make sure you export the plugin for webpack to expose module.exports = PhaserRaycaster; /***/ }), /***/ "./src/map/boundingBox.js": /*!********************************!*\ !*** ./src/map/boundingBox.js ***! \********************************/ /***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ getBoundingBox: function() { return /* binding */ getBoundingBox; } /* harmony export */ }); /** * Get mapped object's bounding box. * * @method Raycaster.Map#matterBody.getBoundingBox * @memberof Raycaster.Map * @instance * @private * @since 0.9.0 * * @return {Phaser.Geom.Rectangle} - Mapped object's bounding box. */ function getBoundingBox() { return this.object.getBounds(); } /***/ }), /***/ "./src/map/config.js": /*!***************************!*\ !*** ./src/map/config.js ***! \***************************/ /***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ config: function() { return /* binding */ config; } /* harmony export */ }); var rectangle = __webpack_require__(/*! ./map-rectangle-methods.js */ "./src/map/map-rectangle-methods.js"); var line = __webpack_require__(/*! ./map-line-methods.js */ "./src/map/map-line-methods.js"); var polygon = __webpack_require__(/*! ./map-polygon-methods.js */ "./src/map/map-polygon-methods.js"); var arc = __webpack_require__(/*! ./map-circle-methods.js */ "./src/map/map-circle-methods.js"); var container = __webpack_require__(/*! ./map-container-methods.js */ "./src/map/map-container-methods.js"); var tilemap = __webpack_require__(/*! ./map-tilemap-methods.js */ "./src/map/map-tilemap-methods.js"); var matterBody = __webpack_require__(/*! ./map-matterBody-methods.js */ "./src/map/map-matterBody-methods.js"); var segmentCount = __webpack_require__(/*! ./segmentsCount.js */ "./src/map/segmentsCount.js"); var boundingBox = __webpack_require__(/*! ./boundingBox.js */ "./src/map/boundingBox.js"); /** * Configure map. * * @method Raycaster.Map#config * @memberof Raycaster.Map * @instance * @since 0.6.0 * * @param {object} [options] - Map's congfiguration options. May include: * @param {object} options.object - Game object to map * @param {string} [options.type] - Map type. If not defined, it will be determined based on object. * @param {boolean} [options.dynamic = false] - If set true, map will be dynamic (updated on scene update event). * @param {boolean} [options.active = true] - If set true, map will be active (will provide points, segments and will be updated). * @param {number} [options.segmentCount] - Circle map's segment count. If set to 0, map won't be generating segments and relay only on tangent points calculated for currently testing ray. * @param {object} [options.mapChild] - Container's child. If set, only set child will be mapped. * @param {boolean} [options.forceConvex] - If set true, matter body map will use convex body (hull) for non-covex bodies. * @param {boolean} [options.forceVerticesMapping] - If set true, matter body map will use only vertices for mapping circle bodies. * * @return {Raycaster.Map} {@link Raycaster.Map Raycaster.Map} instance */ function config(options) { this.object = options.object; //object type if (options.type === undefined) options.type = options.object.type; if (options.type === 'body' || options.type === 'composite') options.type = 'MatterBody'; this.type = options.type; switch (options.type) { case 'Polygon': this.getPoints = polygon.getPoints; this.getSegments = polygon.getSegments; this.getBoundingBox = boundingBox.getBoundingBox; this.updateMap = polygon.updateMap; break; case 'Arc': //circle segments count this.segmentCount = options.segmentCount ? options.segmentCount : 0; this.circle = options.segmentCount ? false : true; this.getPoints = arc.getPoints; this.getSegments = arc.getSegments; this.getBoundingBox = boundingBox.getBoundingBox; this.updateMap = arc.updateMap; this.setSegmentCount = segmentCount.setSegmentCount; break; case 'Line': this.getPoints = line.getPoints; this.getSegments = line.getSegments; this.getBoundingBox = boundingBox.getBoundingBox; this.updateMap = line.updateMap; break; case 'Container': //container's child this.mapChild = options.mapChild ? options.mapChild : null; //circle segments count this.segmentCount = options.segmentCount ? options.segmentCount : 0; //transformed container's circle children this._circles = []; this.getPoints = container.getPoints; this.getSegments = container.getSegments; this.getBoundingBox = boundingBox.getBoundingBox; this.updateMap = container.updateMap; this._updateChildMap = container._updateChildMap; this.setSegmentCount = segmentCount.setSegmentCount; break; case 'StaticTilemapLayer': //ray colliding tiles this.collisionTiles = options.collisionTiles ? options.collisionTiles : []; this.getPoints = tilemap.getPoints; this.getSegments = tilemap.getSegments; this.getBoundingBox = boundingBox.getBoundingBox; this.updateMap = tilemap.updateMap; this.setCollisionTiles = tilemap.setCollisionTiles; //reset tilemap origin this.object.setOrigin(0, 0); break; case 'DynamicTilemapLayer': //ray colliding tiles this.collisionTiles = options.collisionTiles ? options.collisionTiles : []; this.getPoints = tilemap.getPoints; this.getSegments = tilemap.getSegments; this.getBoundingBox = boundingBox.getBoundingBox; this.updateMap = tilemap.updateMap; this.setCollisionTiles = tilemap.setCollisionTiles; //reset tilemap origin this.object.setOrigin(0, 0); break; case 'TilemapLayer': //ray colliding tiles this.collisionTiles = options.collisionTiles ? options.collisionTiles : []; this.getPoints = tilemap.getPoints; this.getSegments = tilemap.getSegments; this.getBoundingBox = boundingBox.getBoundingBox; this.updateMap = tilemap.updateMap; this.setCollisionTiles = tilemap.setCollisionTiles; //reset tilemap origin this.object.setOrigin(0, 0); break; case 'MatterBody': //force convex body (hull) mapping this.forceConvex = options.forceConvex ? true : false; //force mapping by vertices this.forceVerticesMapping = options.forceVerticesMapping ? true : false; this.circle = false; this.getPoints = matterBody.getPoints; this.getSegments = matterBody.getSegments; this.getBoundingBox = matterBody.getBoundingBox; this.updateMap = matterBody.updateMap; break; default: this.getPoints = rectangle.getPoints; this.getSegments = rectangle.getSegments; this.getBoundingBox = boundingBox.getBoundingBox; this.updateMap = rectangle.updateMap; } //if object is not supported if (this.type != 'MatterBody' && typeof this.object.getBounds !== 'function') { this.notSupported = true; } //dynamic map this.dynamic = options.dynamic == true ? true : false; //enable/disable map this.active = options.active !== undefined ? options.active : true; return this; } /***/ }), /***/ "./src/map/destroy.js": /*!****************************!*\ !*** ./src/map/destroy.js ***! \****************************/ /***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ destroy: function() { return /* binding */ destroy; } /* harmony export */ }); /** * Destroy object * * @method Raycaster.Map#destroy * @memberof Raycaster.Map * @instance * @since 0.10.3 */ function destroy() { //destroy reference to map object in mapped object if (this.object.type === 'body' || this.object.type === 'composite') { delete this.object.raycasterMap; } else if (this.object.data) { this.object.data.remove('raycasterMap'); } for (var key in this) { delete this[key]; } } /***/ }), /***/ "./src/map/map-circle-methods.js": /*!***************************************!*\ !*** ./src/map/map-circle-methods.js ***! \***************************************/ /***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ getPoints: function() { return /* binding */ getPoints; }, /* harmony export */ getSegments: function() { return /* binding */ getSegments; }, /* harmony export */ updateMap: function() { return /* binding */ updateMap; } /* harmony export */ }); function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t.return || t.return(); } finally { if (u) throw o; } } }; } function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } } function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; } /*Map methods for circles*/ /** * Get array of mapped circle's vertices used as rays targets. * If {@link Raycaster.Map#segmentCount Raycaster.Map#segmentCount} is set to 0, it'll calculatoe tangent points for passed ray. * * @method Raycaster.Map#arc.getPoints * @memberof Raycaster.Map * @instance * @private * @since 0.6.0 * * @param {Raycaster.Ray} [ray] - {Raycaster.Ray} object used in some some types of maps. * * @return {Phaser.Geom.Point[]} - Array of mapped object's vertices. */ function getPoints() { var ray = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false; if (!this.active) return []; if (this._points.length > 0) return this._points; var points = []; var offset = new Phaser.Geom.Point(); offset.x = this.object.x - this.object.displayWidth * (this.object.originX - 0.5); offset.y = this.object.y - this.object.displayHeight * (this.object.originY - 0.5); //calculate tangent rays if (ray) { var rayA = new Phaser.Geom.Line(); var rayB = new Phaser.Geom.Line(); var c; var rotation = this.object.rotation; if (rotation !== 0) { var vector = new Phaser.Geom.Line(this.object.x, this.object.y, offset.x, offset.y); Phaser.Geom.Line.SetToAngle(vector, this.object.x, this.object.y, Phaser.Geom.Line.Angle(vector) + rotation, Phaser.Geom.Line.Length(vector)); var cB = vector.getPointB(); c = new Phaser.Geom.Line(ray.origin.x, ray.origin.y, cB.x, cB.y); } else { c = new Phaser.Geom.Line(ray.origin.x, ray.origin.y, offset.x, offset.y); } var rayLength = Math.sqrt(Math.pow(Phaser.Geom.Line.Length(c), 2) - Math.pow(this.object.radius * this.object.scaleX, 2)); //ray angle var angle = Phaser.Geom.Line.Angle(c); var dAngle = Math.asin(this.object.radius * this.object.scaleX / Phaser.Geom.Line.Length(c)); Phaser.Geom.Line.SetToAngle(rayA, ray.origin.x, ray.origin.y, angle - dAngle, rayLength); Phaser.Geom.Line.SetToAngle(rayB, ray.origin.x, ray.origin.y, angle + dAngle, rayLength); //add tangent points points.push(rayA.getPointB()); points.push(rayB.getPointB()); //assign neighbours points[0].neighbours = [points[1]]; points[1].neighbours = [points[0]]; } return points; } ; /** * Get array of mapped circle's segments used to test object's intersection with ray. * If {@link Raycaster.Map#segmentCount Raycaster.Map#segmentCount} is set to 0, it'll return empty array. * * @method Raycaster.Map#arc.getSegments * @memberof Raycaster.Map * @instance * @private * @since 0.6.0 * * @return {Phaser.Geom.Line[]} - Array of mapped object's segments. */ function getSegments() { if (!this.active) return []; return this._segments; } ; /** * Update circles's map of points and segments. * * @method Raycaster.Map#arc.updateMap * @memberof Raycaster.Map * @instance * @private * @since 0.6.0 * * @return {Raycaster.Map} {@link Raycaster.Map Raycaster.Map} instance */ function updateMap() { if (!this.active) return this; if (!this.segmentCount) { this._points = []; this._segments = []; return this; } //calculate offset based on object position and origin point var offset = new Phaser.Geom.Point(); offset.x = this.object.x - this.object.displayWidth * this.object.originX + this.object.radius * this.object.scaleX; offset.y = this.object.y - this.object.displayHeight * this.object.originY + this.object.radius * this.object.scaleY; //get points surrounding circle var points = this.object.geom.getPoints(this.segmentCount); var segments = []; //set points //calculate positions after object's rotation var rotation = this.object.rotation; if (rotation !== 0) { var newPoints = []; var _iterator = _createForOfIteratorHelper(points), _step; try { for (_iterator.s(); !(_step = _iterator.n()).done;) { var point = _step.value; var vector = new Phaser.Geom.Line(this.object.x, this.object.y, this.object.x + (point.x + this.object.radius) * this.object.scaleX, this.object.y + (point.y + this.object.radius) * this.object.scaleY); Phaser.Geom.Line.SetToAngle(vector, this.object.x, this.object.y, Phaser.Geom.Line.Angle(vector) + rotation, Phaser.Geom.Line.Length(vector)); newPoints.push(vector.getPointB()); } } catch (err) { _iterator.e(err); } finally { _iterator.f(); } points = newPoints; } //if rotation === 0 else { var _iterator2 = _createForOfIteratorHelper(points), _step2; try { for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) { var _point = _step2.value; _point.x = _point.x * this.object.scaleX + offset.x; _point.y = _point.y * this.object.scaleY + offset.y; } } catch (err) { _iterator2.e(err); } finally { _iterator2.f(); } } //set segments for (var i = 0, length = points.length; i < length; i++) { var prevPoint = i > 0 ? points[i - 1] : points.slice(-1)[0], nextPoint = i < length - 1 ? points[i + 1] : points[0]; segments.push(new Phaser.Geom.Line(points[i].x, points[i].y, nextPoint.x, nextPoint.y)); points[i].neighbours = [prevPoint, nextPoint]; } this._points = points; this._segments = segments; return this; } ; /***/ }), /***/ "./src/map/map-container-methods.js": /*!******************************************!*\ !*** ./src/map/map-container-methods.js ***! \******************************************/ /***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ _updateChildMap: function() { return /* binding */ _updateChildMap; }, /* harmony export */ getPoints: function() { return /* binding */ getPoints; }, /* harmony export */ getSegments: function() { return /* binding */ getSegments; }, /* harmony export */ updateMap: function() { return /* binding */ updateMap; } /* harmony export */ }); function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t.return || t.return(); } finally { if (u) throw o; } } }; } function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } } function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; } /*Map methods for containers*/ /** * Get array of mapped container's and its children vertices used as rays targets. * * @method Raycaster.Map#container.getPoints * @memberof Raycaster.Map * @instance * @private * @since 0.7.1 * * @param {Raycaster.Ray} [ray] - {Raycaster.Ray} object used in some some types of maps. * @param {boolean} [isChild] - Flag definig if it is child container. * * @return {Phaser.Geom.Point[]} - Array of mapped object's vertices. */ function getPoints() { var ray = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false; var isChild = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; if (!this.active) return []; var points = this._points; //calculate offset based on container position and origin point var offset = new Phaser.Geom.Point(); offset.x = this.object.x - this.object.displayWidth * this.object.originX; offset.y = this.object.y - this.object.displayHeight * this.object.originY; //get tangent points of container's circles if (this.segmentCount == 0 && !isChild) { if (ray) { //create temporary ray var vector = new Phaser.Geom.Line(0, 0, ray.origin.x - offset.x, ray.origin.y - offset.y); Phaser.Geom.Line.SetToAngle(vector, 0, 0, Phaser.Geom.Line.Angle(vector) - this.object.rotation, Phaser.Geom.Line.Length(vector)); //calculate tangent rays var rayA = new Phaser.Geom.Line(), rayB = new Phaser.Geom.Line(), c; var _iterator = _createForOfIteratorHelper(this._circles), _step; try { for (_iterator.s(); !(_step = _iterator.n()).done;) { var circle = _step.value; circle.points = []; c = new Phaser.Geom.Line(ray.origin.x, ray.origin.y, circle.x, circle.y); var rayLength = Math.sqrt(Math.pow(Phaser.Geom.Line.Length(c), 2) - Math.pow(circle.radius, 2)); //ray angle var angle = Phaser.Geom.Line.Angle(c); var dAngle = Math.asin(circle.radius / Phaser.Geom.Line.Length(c)); Phaser.Geom.Line.SetToAngle(rayA, ray.origin.x, ray.origin.y, angle - dAngle, rayLength); Phaser.Geom.Line.SetToAngle(rayB, ray.origin.x, ray.origin.y, angle + dAngle, rayLength); //adding tangent points circle.points.push(rayA.getPointB()); circle.points.push(rayB.getPointB()); points.push(rayA.getPointB()); points.push(rayB.getPointB()); } } catch (err) { _iterator.e(err); } finally { _iterator.f(); } } } return points; } ; /** * Get array of mapped container's and its children segments used to test object's intersection with ray. * * @method Raycaster.Map#container.getSegments * @memberof Raycaster.Map * @instance * @private * @since 0.7.1 * * @return {Phaser.Geom.Line[]} - Array of mapped object's segments. */ function getSegments() { if (!this.active) return []; return this._segments; } ; /** * Update container's and its children maps of points and segments. * * @method Raycaster.Map#container.updateMap * @memberof Raycaster.Map * @instance * @private * @since 0.7.1 * * @return {Raycaster.Map} {@link Raycaster.Map Raycaster.Map} instance */ function updateMap() { if (!this.active) return this; var points = []; var segments = []; var container = this.object; this._circles = []; //calculate offset based on container position and origin point var offset = new Phaser.Geom.Point(); offset.x = this.object.x - this.object.displayWidth * this.object.originX; offset.y = this.object.y - this.object.displayHeight * this.object.originY; var rotation = container.rotation; if (this.mapChild) { this._updateChildMap(this.mapChild, points, segments, rotation, offset); } else { //iterate through container's children container.iterate(function (child) { this._updateChildMap(child, points, segments, rotation, offset); }.bind(this)); //get children intersections for (var i = 0, iLength = container.list.length; i < iLength; i++) { var childA = container.list[i]; var mapA = childA.data.get('raycasterMap'); if (!mapA) continue; for (var j = i + 1, jLength = container.list.length; j < jLength; j++) { var childB = container.list[j]; var mapB = childB.data.get('raycasterMap'); //check if bounding boxes overlap if (!mapB || !Phaser.Geom.Intersects.RectangleToRectangle(childA.getBounds(), childB.getBounds())) continue; //find objects intersections var _iterator2 = _createForOfIteratorHelper(mapA.getSegments()), _step2; try { for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) { var segmentA = _step2.value; var _iterator3 = _createForOfIteratorHelper(mapB.getSegments()), _step3; try { for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) { var segmentB = _step3.value; var intersection = []; if (!Phaser.Geom.Intersects.LineToLine(segmentA, segmentB, intersection)) continue; //calculate positions after container's rotation if (rotation !== 0) { var vector = new Phaser.Geom.Line(container.x, container.y, intersection.x * container.scaleX + offset.x, intersection.y * container.scaleY + offset.y); Phaser.Geom.Line.SetToAngle(vector, this.object.x, this.object.y, Phaser.Geom.Line.Angle(vector) + rotation, Phaser.Geom.Line.Length(vector)); points.push(vector.getPointB()); } //if rotation === 0 else points.push(new Phaser.Geom.Point(intersection.x * container.scaleX + offset.x, intersection.y * container.scaleX + offset.y)); } } catch (err) { _iterator3.e(err); } finally { _iterator3.f(); } } } catch (err) { _iterator2.e(err); } finally { _iterator2.f(); } } } } this._points = points; this._segments = segments; return this; } ; /** * Update container's child map of points and segments. * * @method Raycaster.Map#container._updateChildMap * @memberof Raycaster.Map * @instance * @private * @since 0.10.3 * * @param {object} [child] - Container's child object. * @param {Phaser.Geom.Point[]} [points] - Container's mapped points. * @param {Phaser.Geom.Line[]} [segments] - Container's mapped segments. * @param {number} [rotation] - Container's rotation. * @param {Phaser.Geom.Point} [offset] - Container's offset. */ function _updateChildMap(child, points, segments, rotation, offset) { if (!child.data) child.setDataEnabled(); //if object is not supported if (child.data.get('raycasterMapNotSupported')) return; //get child map var map = child.data.get('raycasterMap'); if (!map) { map = new this.constructor({ object: child, segmentCount: this.segmentCount }); if (map.notSupported) { map.destroy(); child.data.set('raycasterMapNotSupported', true); return; } child.data.set('raycasterMap', map); } else map.updateMap(); //add child points var childPoints = []; var _iterator4 = _createForOfIteratorHelper(map.getPoints(false, true)), _step4; try { for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) { var point = _step4.value; var childPoint = void 0; //calculate positions after container's rotation if (rotation !== 0) { var _vector2 = new Phaser.Geom.Line(this.object.x, this.object.y, point.x * this.object.scaleX + offset.x, point.y * this.object.scaleY + offset.y); Phaser.Geom.Line.SetToAngle(_vector2, this.object.x, this.object.y, Phaser.Geom.Line.Angle(_vector2) + rotation, Phaser.Geom.Line.Length(_vector2)); childPoint = _vector2.getPointB(); } //if rotation === 0 else childPoint = new Phaser.Geom.Point(point.x * this.object.scaleX + offset.x, point.y * this.object.scaleX + offset.y); //add neighbour points childPoint.neighbours = []; if (childPoints.length > 0) { var previousPoint = childPoints.slice(-1)[0]; previousPoint.neighbours.push(childPoint); childPoint.neighbours.push(previousPoint); } childPoints.push(childPoint); points.push(childPoint); } //add neighbour point to last child point } catch (err) { _iterator4.e(err); } finally { _iterator4.f(); } if (childPoints.length > 0) { childPoints.slice(-1)[0].neighbours.push(childPoints[0]); } //add child segments var _iterator5 = _createForOfIteratorHelper(map.getSegments()), _step5; try { for (_iterator5.s(); !(_step5 = _iterator5.n()).done;) { var segment = _step5.value; //calculate positions after container's rotation if (rotation !== 0) { var pointA = segment.getPointA(); var pointB = segment.getPointB(); var vectorA = new Phaser.Geom.Line(this.object.x, this.object.y, pointA.x * this.object.scaleX + offset.x, pointA.y * this.object.scaleY + offset.y); var vectorB = new Phaser.Geom.Line(this.object.x, this.object.y, pointB.x * this.object.scaleX + offset.x, pointB.y * this.object.scaleY + offset.y); Phaser.Geom.Line.SetToAngle(vectorA, this.object.x, this.object.y, Phaser.Geom.Line.Angle(vectorA) + rotation, Phaser.Geom.Line.Length(vectorA)); Phaser.Geom.Line.SetToAngle(vectorB, this.object.x, this.object.y, Phaser.Geom.Line.Angle(vectorB) + rotation, Phaser.Geom.Line.Length(vectorB)); segments.push(new Phaser.Geom.Line(vectorA.getPointB().x, vectorA.getPointB().y, vectorB.getPointB().x, vectorB.getPointB().y)); } //if rotation === 0 else segments.push(new Phaser.Geom.Line(segment.getPointA().x * this.object.scaleX + offset.x, segment.getPointA().y * this.object.scaleY + offset.y, segment.getPointB().x * this.object.scaleX + offset.x, segment.getPointB().y * this.object.scaleY + offset.y)); } //if child's map is a circle and this.segmentsCount == 0, store transformed circles in this._circles array. } catch (err) { _iterator5.e(err); } finally { _iterator5.f(); } if (map.type == 'Arc' && this.segmentCount == 0) { var circleOffset = new Phaser.Geom.Point(); circleOffset.x = (map.object.x - map.object.displayWidth * (map.object.originX - 0.5)) * this.object.scaleX + offset.x; circleOffset.y = (map.object.y - map.object.displayHeight * (map.object.originY - 0.5)) * this.object.scaleY + offset.y; if (rotation !== 0) { var vector = new Phaser.Geom.Line(this.object.x, this.object.y, circleOffset.x, circleOffset.y); Phaser.Geom.Line.SetToAngle(vector, this.object.x, this.object.y, Phaser.Geom.Line.Angle(vector) + rotation, Phaser.Geom.Line.Length(vector)); circleOffset = vector.getPointB(); } this._circles.push(new Phaser.Geom.Circle(circleOffset.x, circleOffset.y, map.object.radius * map.object.scaleX * this.object.scaleX)); } else if (map.type === 'Container') { var _iterator6 = _createForOfIteratorHelper(map._circles), _step6; try { for (_iterator6.s(); !(_step6 = _iterator6.n()).done;) { var childMapCircle = _step6.value; var _circleOffset = new Phaser.Geom.Point(); _circleOffset.x = childMapCircle.x * this.object.scaleX + offset.x; _circleOffset.y = childMapCircle.y * this.object.scaleY + offset.y; if (rotation !== 0) { var _vector = new Phaser.Geom.Line(this.object.x, this.object.y, _circleOffset.x, _circleOffset.y); Phaser.Geom.Line.SetToAngle(_vector, this.object.x, this.object.y, Phaser.Geom.Line.Angle(_vector) + rotation, Phaser.Geom.Line.Length(_vector)); _circleOffset = _vector.getPointB(); } this._circles.push(new Phaser.Geom.Circle(_circleOffset.x, _circleOffset.y, childMapCircle.radius * this.object.scaleX)); } } catch (err) { _iterator6.e(err); } finally { _iterator6.f(); } } } /***/ }), /***/ "./src/map/map-core.js": /*!*****************************!*\ !*** ./src/map/map-core.js ***! \*****************************/ /***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ Map: function() { return /* binding */ Map; } /* harmony export */ }); /** * @classdesc * * Map class responsible for mapping game objects. * * @namespace Raycaster.Map * @class Raycaster.Map * @constructor * @since 0.6.0 * * @param {object} options - Map specific configuration settings. * @param {Raycaster} [raycaster] - Parent raycaster object. */ function Map(options, raycaster) { /** * Reference to parent Raycaster object. * * @name Raycaster.Map#_raycaster * @type {Raycaster} * @private * @since 0.9.0 */ this._raycaster = raycaster ? raycaster : false; /** * Mapped object's type * * @name Raycaster.Map#type * @type {string} * @readonly * @since 0.6.0 */ this.type; /** * If set true, map will be tested by ray. Otherwise it will be ignored. * * @name Raycaster.Map#active * @type {boolean} * @default true * @since 0.7.2 */ this.active; /** * If set true, map will be automatically updated on scene update event. * * @name Raycaster.Map_dynamic * @type {boolean} * @default false * @since 0.6.0 */ this._dynamic = false; /** * If set true, map will be treated by ray as circle. Set automaticalyy on map update. * * @name Raycaster.Map#circle * @type {boolean} * @default false * @since 0.9.0 */ this.circle = false; /** * Reference to mapped object. * * @name Raycaster.Map#object * @type {object} * @readonly * @since 0.6.0 */ this.object; /** * Array of mapped object's vertices used as rays targets. * * @name Raycaster.Map#_points * @type {array} * @private * @since 0.6.0 */ this._points = []; /** * Array of mapped object's segments used to test object's intersection with ray. * * @name Raycaster.Map#_segments * @type {array} * @private * @since 0.6.0 */ this._segments = []; /** * Get array of mapped object's vertices used as rays targets. * * @method Raycaster.Map#getPoints * @memberof Raycaster.Map * @instance * @since 0.6.0 * * @param {Raycaster.Ray} [ray] - {@link Raycaster.Ray Raycaster.Ray} object used in some some types of maps. * * @return {Phaser.Geom.Point[]} Array of mapped object's vertices. */ this.getPoints; /** * Get array of mapped object's segments used to test object's intersection with ray. * * @method Raycaster.Map#getSegments * @memberof Raycaster.Map * @instance * @since 0.6.0 * * @param {Raycaster.Ray} [ray] - {@link Raycaster.Ray Raycaster.Ray} object used in some some types of maps. * * @return {Phaser.Geom.Line[]} Array of mapped object's segments. */ this.getSegments; /** * Get mapped object's bounding box. * * @method Raycaster.Map#getBoundingBox * @memberof Raycaster.Map * @instance * @since 0.9.0 * * @return {Phaser.Geom.Rectangle} Mapped object's bounding box. */ this.getBoundingBox; /** * Update object's map of points and segments. * * @method Raycaster.Map#updateMap * @memberof Raycaster.Map * @instance * @since 0.6.0 * * @return {Raycaster.Map} {@link Raycaster.Map Raycaster.Map} instance */ this.updateMap; this.config(options); if (!this.notSupported) this.updateMap(); return this; } ; Map.prototype = { config: (__webpack_require__(/*! ./config.js */ "./src/map/config.js").config), destroy: (__webpack_require__(/*! ./destroy.js */ "./src/map/destroy.js").destroy), get dynamic() { return this._dynamic; }, set dynamic(dynamic) { if (this._dynamic == dynamic) return this; if (dynamic) { this._dynamic = true; //add object to raycaster's dynamic objects list if (this._raycaster) { this._raycaster.dynamicMappedObjects.push(this.object); this._raycaster._stats.mappedObjects.dynamic = this._raycaster.dynamicMappedObjects.length; this._raycaster._stats.mappedObjects.static = this._raycaster._stats.mappedObjects.total - this._raycaster._stats.mappedObjects.dynamic; } } else { this._dynamic = false; //remove object from reycasters' dynamic objects list if (this._raycaster) { var index = this._raycaster.dynamicMappedObjects.indexOf(this.object); if (index >= 0) this._raycaster.dynamicMappedObjects.splice(index, 1); this._raycaster._stats.mappedObjects.dynamic = this._raycaster.dynamicMappedObjects.length; this._raycaster._stats.mappedObjects.static = this._raycaster._stats.mappedObjects.total - this._raycaster._stats.mappedObjects.dynamic; } } return this; } }; Map.prototype.constructor = Map; /***/ }), /***/ "./src/map/map-line-methods.js": /*!*************************************!*\ !*** ./src/map/map-line-methods.js ***! \*************************************/ /***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ getPoints: function() { return /* binding */ getPoints; }, /* harmony export */ getSegments: function() { return /* binding */ getSegments; }, /* harmony export */ updateMap: function() { return /* binding */ updateMap; } /* harmony export */ }); /*Map methods for lines*/ /** * Get array of mapped line's vertices used as rays targets. * * @method Raycaster.Map#line.getPoints * @memberof Raycaster.Map * @instance * @private * @since 0.6.0 * * @param {Raycaster.Ray} [ray] - {Raycaster.Ray} object used in some some types of maps. * * @return {Phaser.Geom.Point[]} - Array of mapped object's vertices. */ function getPoints() { var ray = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false; if (!this.active) return []; return this._points; } ; /** * Get array of mapped line's segments used to test object's intersection with ray. * * @method Raycaster.Map#line.getSegments * @memberof Raycaster.Map * @instance * @private * @since 0.6.0 * * @return {Phaser.Geom.Line[]} - Array of mapped object's segments. */ function getSegments() { if (!this.active) return []; return this._segments; } ; /** * Update line's map of points and segments. * * @method Raycaster.Map#line.updateMap * @memberof Raycaster.Map * @instance * @private * @since 0.6.0 * * @return {Raycaster.Map} {@link Raycaster.Map Raycaster.Map} instance */ function updateMap() { if (!this.active) return this; var points = []; var segments = []; //calculate offset based on object position and origin point var offset = new Phaser.Geom.Point(); offset.x = this.object.x - this.object.displayWidth * this.object.originX; offset.y = this.object.y - this.object.displayHeight * this.object.originY; var pointA = this.object.geom.getPointA(); var pointB = this.object.geom.getPointB(); //calculate positions after object's rotation var rotation = this.object.rotation; if (rotation !== 0) { var vectorA = new Phaser.Geom.Line(this.object.x, this.object.y, pointA.x * this.object.scaleX + offset.x, pointA.y * this.object.scaleY + offset.y); Phaser.Geom.Line.SetToAngle(vectorA, this.object.x, this.object.y, Phaser.Geom.Line.Angle(vectorA) + rotation, Phaser.Geom.Line.Length(vectorA)); pointA = vectorA.getPointB(); var vectorB = new Phaser.Geom.Line(this.object.x, this.object.y, pointB.x * this.object.scaleX + offset.x, pointB.y * this.object.scaleY + offset.y); Phaser.Geom.Line.SetToAngle(vectorB, this.object.x, this.object.y, Phaser.Geom.Line.Angle(vectorB) + rotation, Phaser.Geom.Line.Length(vectorB)); pointB = vectorB.getPointB(); //set points points.push(new Phaser.Geom.Point(pointA.x, pointA.y)); points.push(new Phaser.Geom.Point(pointB.x, pointB.y)); //set segment segments.push(new Phaser.Geom.Line(pointA.x, pointA.y, pointB.x, pointB.y)); } //if rotation === 0 else { //set points points.push(new Phaser.Geom.Point(pointA.x * this.object.scaleX + offset.x, pointA.y * this.object.scaleY + offset.y)); points.push(new Phaser.Geom.Point(pointB.x * this.object.scaleX + offset.x, pointB.y * this.object.scaleY + offset.y)); //set segment segments.push(new Phaser.Geom.Line(pointA.x * this.object.scaleX + offset.x, pointA.y * this.object.scaleY + offset.y, pointB.x + offset.x * this.object.scaleX, pointB.y * this.object.scaleY + offset.y)); } //assign neighbours points[0].neighbours = [points[1]]; points[1].neighbours = [points[0]]; this._points = points; this._segments = segments; return this; } ; /***/ }), /***/ "./src/map/map-matterBody-methods.js": /*!*******************************************!*\ !*** ./src/map/map-matterBody-methods.js ***! \*******************************************/ /***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ getBoundingBox: function() { return /* binding */ getBoundingBox; }, /* harmony export */ getPoints: function() { return /* binding */ getPoints; }, /* harmony export */ getSegments: function() { return /* binding */ getSegments; }, /* harmony export */ updateMap: function() { return /* binding */ updateMap; } /* harmony export */ }); function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t.return || t.return(); } finally { if (u) throw o; } } }; } function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } } function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; } /*Map methods for matter body*/ /** * Get array of mapped matter body's vertices used as rays targets. * * @method Raycaster.Map#matterBody.getPoints * @memberof Raycaster.Map * @instance * @private * @since 0.9.0 * * @param {Raycaster.Ray} [ray] - {Raycaster.Ray} object used in some some types of maps. * * @return {Phaser.Geom.Point[]} - Array of mapped object's vertices. */ function getPoints() { var ray = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false; if (!this.active) return []; var body = this.object.type === 'body' || this.object.type === 'composite' ? this.object : this.object.body; //calculate tangent rays if (ray && !this.forceVerticesMapping && body.circleRadius > 0) { var points = []; var rayA = new Phaser.Geom.Line(); var rayB = new Phaser.Geom.Line(); var c = new Phaser.Geom.Line(ray.origin.x, ray.origin.y, body.position.x, body.position.y); var rayLength = Math.sqrt(Math.pow(Phaser.Geom.Line.Length(c), 2) - Math.pow(body.circleRadius * body.scale.x, 2)); //ray angle var angle = Phaser.Geom.Line.Angle(c); var dAngle = Math.asin(body.circleRadius * body.scale.x / Phaser.Geom.Line.Length(c)); Phaser.Geom.Line.SetToAngle(rayA, ray.origin.x, ray.origin.y, angle - dAngle, rayLength); Phaser.Geom.Line.SetToAngle(rayB, ray.origin.x, ray.origin.y, angle + dAngle, rayLength); //adding tangent points points.push(rayA.getPointB(), rayB.getPointB()); return points; } return this._points; } ; /** * Get array of mapped matter body's segments used to test object's intersection with ray. * * @method Raycaster.Map#matterBody.getSegments * @memberof Raycaster.Map * @instance * @private * @since 0.9.0 * * @return {Phaser.Geom.Line[]} - Array of mapped object's segments. */ function getSegments() { if (!this.active) return []; return this._segments; } ; /** * Update matter body's map of points and segments. * * @method Raycaster.Map#matterBody.updateMap * @memberof Raycaster.Map * @instance * @private * @since 0.9.0 * * @return {Raycaster.Map} {@link Raycaster.Map Raycaster.Map} instance */ function updateMap() { if (!this.active) return this; var points = []; var segments = []; var body = this.object.type === 'body' || this.object.type === 'composite' ? this.object : this.object.body; var bodies = [body]; var generateBounds = false; if (body.circleRadius > 0 && !this.forceVerticesMapping) { this.circle = true; this._points = points; this._segments = segments; return this; } this.circle = false; if (body.type == 'composite') bodies = body.bodies; if (body.bounds === undefined && body.type ==