UNPKG

phaser4-rex-plugins

Version:
1,596 lines (1,358 loc) 501 kB
(function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : typeof define === 'function' && define.amd ? define(factory) : (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.rexboardplugin = factory()); })(this, (function () { 'use strict'; class ObjectFactory { constructor(scene) { this.scene = scene; scene.sys.events.once('destroy', this.destroy, this); } destroy() { this.scene = null; } static register(type, callback) { ObjectFactory.prototype[type] = callback; } } function getDefaultExportFromCjs (x) { return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x; } var eventemitter3 = {exports: {}}; (function (module) { var has = Object.prototype.hasOwnProperty , prefix = '~'; /** * Constructor to create a storage for our `EE` objects. * An `Events` instance is a plain object whose properties are event names. * * @constructor * @private */ function Events() {} // // We try to not inherit from `Object.prototype`. In some engines creating an // instance in this way is faster than calling `Object.create(null)` directly. // If `Object.create(null)` is not supported we prefix the event names with a // character to make sure that the built-in object properties are not // overridden or used as an attack vector. // if (Object.create) { Events.prototype = Object.create(null); // // This hack is needed because the `__proto__` property is still inherited in // some old browsers like Android 4, iPhone 5.1, Opera 11 and Safari 5. // if (!new Events().__proto__) prefix = false; } /** * Representation of a single event listener. * * @param {Function} fn The listener function. * @param {*} context The context to invoke the listener with. * @param {Boolean} [once=false] Specify if the listener is a one-time listener. * @constructor * @private */ function EE(fn, context, once) { this.fn = fn; this.context = context; this.once = once || false; } /** * Add a listener for a given event. * * @param {EventEmitter} emitter Reference to the `EventEmitter` instance. * @param {(String|Symbol)} event The event name. * @param {Function} fn The listener function. * @param {*} context The context to invoke the listener with. * @param {Boolean} once Specify if the listener is a one-time listener. * @returns {EventEmitter} * @private */ function addListener(emitter, event, fn, context, once) { if (typeof fn !== 'function') { throw new TypeError('The listener must be a function'); } var listener = new EE(fn, context || emitter, once) , evt = prefix ? prefix + event : event; if (!emitter._events[evt]) emitter._events[evt] = listener, emitter._eventsCount++; else if (!emitter._events[evt].fn) emitter._events[evt].push(listener); else emitter._events[evt] = [emitter._events[evt], listener]; return emitter; } /** * Clear event by name. * * @param {EventEmitter} emitter Reference to the `EventEmitter` instance. * @param {(String|Symbol)} evt The Event name. * @private */ function clearEvent(emitter, evt) { if (--emitter._eventsCount === 0) emitter._events = new Events(); else delete emitter._events[evt]; } /** * Minimal `EventEmitter` interface that is molded against the Node.js * `EventEmitter` interface. * * @constructor * @public */ function EventEmitter() { this._events = new Events(); this._eventsCount = 0; } /** * Return an array listing the events for which the emitter has registered * listeners. * * @returns {Array} * @public */ EventEmitter.prototype.eventNames = function eventNames() { var names = [] , events , name; if (this._eventsCount === 0) return names; for (name in (events = this._events)) { if (has.call(events, name)) names.push(prefix ? name.slice(1) : name); } if (Object.getOwnPropertySymbols) { return names.concat(Object.getOwnPropertySymbols(events)); } return names; }; /** * Return the listeners registered for a given event. * * @param {(String|Symbol)} event The event name. * @returns {Array} The registered listeners. * @public */ EventEmitter.prototype.listeners = function listeners(event) { var evt = prefix ? prefix + event : event , handlers = this._events[evt]; if (!handlers) return []; if (handlers.fn) return [handlers.fn]; for (var i = 0, l = handlers.length, ee = new Array(l); i < l; i++) { ee[i] = handlers[i].fn; } return ee; }; /** * Return the number of listeners listening to a given event. * * @param {(String|Symbol)} event The event name. * @returns {Number} The number of listeners. * @public */ EventEmitter.prototype.listenerCount = function listenerCount(event) { var evt = prefix ? prefix + event : event , listeners = this._events[evt]; if (!listeners) return 0; if (listeners.fn) return 1; return listeners.length; }; /** * Calls each of the listeners registered for a given event. * * @param {(String|Symbol)} event The event name. * @returns {Boolean} `true` if the event had listeners, else `false`. * @public */ EventEmitter.prototype.emit = function emit(event, a1, a2, a3, a4, a5) { var evt = prefix ? prefix + event : event; if (!this._events[evt]) return false; var listeners = this._events[evt] , len = arguments.length , args , i; if (listeners.fn) { if (listeners.once) this.removeListener(event, listeners.fn, undefined, true); switch (len) { case 1: return listeners.fn.call(listeners.context), true; case 2: return listeners.fn.call(listeners.context, a1), true; case 3: return listeners.fn.call(listeners.context, a1, a2), true; case 4: return listeners.fn.call(listeners.context, a1, a2, a3), true; case 5: return listeners.fn.call(listeners.context, a1, a2, a3, a4), true; case 6: return listeners.fn.call(listeners.context, a1, a2, a3, a4, a5), true; } for (i = 1, args = new Array(len -1); i < len; i++) { args[i - 1] = arguments[i]; } listeners.fn.apply(listeners.context, args); } else { var length = listeners.length , j; for (i = 0; i < length; i++) { if (listeners[i].once) this.removeListener(event, listeners[i].fn, undefined, true); switch (len) { case 1: listeners[i].fn.call(listeners[i].context); break; case 2: listeners[i].fn.call(listeners[i].context, a1); break; case 3: listeners[i].fn.call(listeners[i].context, a1, a2); break; case 4: listeners[i].fn.call(listeners[i].context, a1, a2, a3); break; default: if (!args) for (j = 1, args = new Array(len -1); j < len; j++) { args[j - 1] = arguments[j]; } listeners[i].fn.apply(listeners[i].context, args); } } } return true; }; /** * Add a listener for a given event. * * @param {(String|Symbol)} event The event name. * @param {Function} fn The listener function. * @param {*} [context=this] The context to invoke the listener with. * @returns {EventEmitter} `this`. * @public */ EventEmitter.prototype.on = function on(event, fn, context) { return addListener(this, event, fn, context, false); }; /** * Add a one-time listener for a given event. * * @param {(String|Symbol)} event The event name. * @param {Function} fn The listener function. * @param {*} [context=this] The context to invoke the listener with. * @returns {EventEmitter} `this`. * @public */ EventEmitter.prototype.once = function once(event, fn, context) { return addListener(this, event, fn, context, true); }; /** * Remove the listeners of a given event. * * @param {(String|Symbol)} event The event name. * @param {Function} fn Only remove the listeners that match this function. * @param {*} context Only remove the listeners that have this context. * @param {Boolean} once Only remove one-time listeners. * @returns {EventEmitter} `this`. * @public */ EventEmitter.prototype.removeListener = function removeListener(event, fn, context, once) { var evt = prefix ? prefix + event : event; if (!this._events[evt]) return this; if (!fn) { clearEvent(this, evt); return this; } var listeners = this._events[evt]; if (listeners.fn) { if ( listeners.fn === fn && (!once || listeners.once) && (!context || listeners.context === context) ) { clearEvent(this, evt); } } else { for (var i = 0, events = [], length = listeners.length; i < length; i++) { if ( listeners[i].fn !== fn || (once && !listeners[i].once) || (context && listeners[i].context !== context) ) { events.push(listeners[i]); } } // // Reset the array, or remove it completely if we have no more listeners. // if (events.length) this._events[evt] = events.length === 1 ? events[0] : events; else clearEvent(this, evt); } return this; }; /** * Remove all listeners, or those of the specified event. * * @param {(String|Symbol)} [event] The event name. * @returns {EventEmitter} `this`. * @public */ EventEmitter.prototype.removeAllListeners = function removeAllListeners(event) { var evt; if (event) { evt = prefix ? prefix + event : event; if (this._events[evt]) clearEvent(this, evt); } else { this._events = new Events(); this._eventsCount = 0; } return this; }; // // Alias methods names because people roll like that. // EventEmitter.prototype.off = EventEmitter.prototype.removeListener; EventEmitter.prototype.addListener = EventEmitter.prototype.on; // // Expose the prefix. // EventEmitter.prefixed = prefix; // // Allow `EventEmitter` to be imported as module namespace. // EventEmitter.EventEmitter = EventEmitter; // // Expose the module. // { module.exports = EventEmitter; } } (eventemitter3)); var eventemitter3Exports = eventemitter3.exports; var EE = /*@__PURE__*/getDefaultExportFromCjs(eventemitter3Exports); class EventEmitter extends EE { shutdown() { this.removeAllListeners(); } destroy() { this.removeAllListeners(); } } var GetValue$c = function (source, key, defaultValue) { if (!source || typeof source === 'number') { return defaultValue; } if (typeof (key) === 'string') { if (source.hasOwnProperty(key)) { return source[key]; } if (key.indexOf('.') !== -1) { key = key.split('.'); } else { return defaultValue; } } var keys = key; var parent = source; var value = defaultValue; // Use for loop here so we can break early for (var i = 0; i < keys.length; i++) { key = keys[i]; if (parent.hasOwnProperty(key)) { // Yes it has a key property, let's carry on down value = parent[key]; parent = value; } else { // Can't go any further, so reset to default value = defaultValue; break; } } return value; }; class Bank { constructor(config) { this.nextId = GetValue$c(config, 'start', 1); // start index this.uidKey = GetValue$c(config, 'uidKey', '$uid'); this.autoRemove = GetValue$c(config, 'remove', true); this.refs = {}; this.count = 0; } add(gameObject, uid) { var refs = this.refs; var uidKey = this.uidKey; if (uidKey) { if (gameObject.hasOwnProperty('uidKey') && gameObject[uidKey] != null) { return this; } } if (uid == null) { do { uid = this.nextId; this.nextId++; } while (refs.hasOwnProperty(uid)) } if (!refs.hasOwnProperty(uid)) { refs[uid] = gameObject; this.count++; if (uidKey) { gameObject[uidKey] = uid; } if (this.autoRemove && gameObject.on) { gameObject.once('destroy', function () { this.remove(uid); }, this); } } else { uid = null; } if (uidKey) { return this; } else { return uid; } } addMultiple(objects) { for (var i = 0, cnt = objects.length; i < cnt; i++) { this.add(objects[i]); } return this; } get(uid) { return this.refs[uid]; } has(uid) { return this.refs.hasOwnProperty(uid); } remove(uid) { var refs = this.refs; if (refs.hasOwnProperty(uid)) { if (this.uidKey) { var gameObject = refs[uid]; gameObject[this.uidKey] = undefined; } delete refs[uid]; this.count--; } return this; } forEach(callback, scope) { var refs = this.refs, gameObject; for (var uid in refs) { gameObject = refs[uid]; if (scope) { callback.call(scope, gameObject, uid); } else { callback(gameObject, uid); } } } clear() { this.forEach(function (gameObject) { this.remove(gameObject); }, this); } } var ChessBank = new Bank({ uidKey: '$uid', remove: false, // remove uid manually }); var EventEmitterMethods$1 = { setEventEmitter(eventEmitter, EventEmitterClass) { if (EventEmitterClass === undefined) { EventEmitterClass = Phaser.Events.EventEmitter; // Use built-in EventEmitter class by default } this._privateEE = (eventEmitter === true) || (eventEmitter === undefined); this._eventEmitter = (this._privateEE) ? (new EventEmitterClass()) : eventEmitter; return this; }, destroyEventEmitter() { if (this._eventEmitter && this._privateEE) { this._eventEmitter.shutdown(); } return this; }, getEventEmitter() { return this._eventEmitter; }, on() { if (this._eventEmitter) { this._eventEmitter.on.apply(this._eventEmitter, arguments); } return this; }, once() { if (this._eventEmitter) { this._eventEmitter.once.apply(this._eventEmitter, arguments); } return this; }, off() { if (this._eventEmitter) { this._eventEmitter.off.apply(this._eventEmitter, arguments); } return this; }, emit(event) { if (this._eventEmitter && event) { this._eventEmitter.emit.apply(this._eventEmitter, arguments); } return this; }, addListener() { if (this._eventEmitter) { this._eventEmitter.addListener.apply(this._eventEmitter, arguments); } return this; }, removeListener() { if (this._eventEmitter) { this._eventEmitter.removeListener.apply(this._eventEmitter, arguments); } return this; }, removeAllListeners() { if (this._eventEmitter) { this._eventEmitter.removeAllListeners.apply(this._eventEmitter, arguments); } return this; }, listenerCount() { if (this._eventEmitter) { return this._eventEmitter.listenerCount.apply(this._eventEmitter, arguments); } return 0; }, listeners() { if (this._eventEmitter) { return this._eventEmitter.listeners.apply(this._eventEmitter, arguments); } return []; }, eventNames() { if (this._eventEmitter) { return this._eventEmitter.eventNames.apply(this._eventEmitter, arguments); } return []; }, }; const SceneClass = Phaser.Scene; var IsSceneObject = function (object) { return (object instanceof SceneClass); }; var GetSceneObject = function (object) { if ((object == null) || (typeof (object) !== 'object')) { return null; } else if (IsSceneObject(object)) { // object = scene return object; } else if (object.scene && IsSceneObject(object.scene)) { // object = game object return object.scene; } else if (object.parent && object.parent.scene && IsSceneObject(object.parent.scene)) { // parent = bob object return object.parent.scene; } else { return null; } }; const GameClass = Phaser.Game; var IsGame = function (object) { return (object instanceof GameClass); }; var GetGame = function (object) { if ((object == null) || (typeof (object) !== 'object')) { return null; } else if (IsGame(object)) { return object; } else if (IsGame(object.game)) { return object.game; } else if (IsSceneObject(object)) { // object = scene object return object.sys.game; } else if (IsSceneObject(object.scene)) { // object = game object return object.scene.sys.game; } }; const GetValue$b = Phaser.Utils.Objects.GetValue; class ComponentBase { constructor(parent, config) { this.setParent(parent); // gameObject, scene, or game this.isShutdown = false; // Event emitter, default is private event emitter this.setEventEmitter(GetValue$b(config, 'eventEmitter', true)); // Register callback of parent destroy event, also see `shutdown` method if (this.parent) { if (this.parent === this.scene) { // parent is a scene this.scene.sys.events.once('shutdown', this.onEnvDestroy, this); } else if (this.parent === this.game) { // parent is game this.game.events.once('shutdown', this.onEnvDestroy, this); } else if (this.parent.once) { // parent is game object or something else this.parent.once('destroy', this.onParentDestroy, this); } // bob object does not have event emitter } } shutdown(fromScene) { // Already shutdown if (this.isShutdown) { return; } // parent might not be shutdown yet if (this.parent) { if (this.parent === this.scene) { // parent is a scene this.scene.sys.events.off('shutdown', this.onEnvDestroy, this); } else if (this.parent === this.game) { // parent is game this.game.events.off('shutdown', this.onEnvDestroy, this); } else if (this.parent.once) { // parent is game object or something else this.parent.off('destroy', this.onParentDestroy, this); } // bob object does not have event emitter } this.destroyEventEmitter(); this.parent = undefined; this.scene = undefined; this.game = undefined; this.isShutdown = true; } destroy(fromScene) { this.shutdown(fromScene); } onEnvDestroy() { this.destroy(true); } onParentDestroy(parent, fromScene) { this.destroy(fromScene); } setParent(parent) { this.parent = parent; // gameObject, scene, or game this.scene = GetSceneObject(parent); this.game = GetGame(parent); return this; } } Object.assign( ComponentBase.prototype, EventEmitterMethods$1 ); var GetTileDirection = function(tileX, tileY) { var board = this.board; if (board === null) { return null; } globTileXY$i.x = tileX; globTileXY$i.y = tileY; return board.getNeighborTileDirection(this.tileXYZ, globTileXY$i); }; var globTileXY$i = { x: 0, y: 0 }; var IsPlainObject = function (obj) { // Not plain objects: // - Any object or value whose internal [[Class]] property is not "[object Object]" // - DOM nodes // - window if (typeof(obj) !== 'object' || obj.nodeType || obj === obj.window) { return false; } // Support: Firefox <20 // The try/catch suppresses exceptions thrown when attempting to access // the "constructor" property of certain host objects, ie. |window.location| // https://bugzilla.mozilla.org/show_bug.cgi?id=814622 try { if (obj.constructor && !({}).hasOwnProperty.call(obj.constructor.prototype, 'isPrototypeOf')) { return false; } } catch (e) { return false; } // If the function hasn't returned already, we're confident that // |obj| is a plain object, created by {} or constructed with new Object return true; }; const uidKey$1 = ChessBank.uidKey; class Chess extends ComponentBase { constructor(parent, uid) { super(parent, { eventEmitter: false }); // this.parent ChessBank.add(this, uid); // uid is stored in `this.$uid` this.board = null; this.blocker = false; } shutdown(fromScene) { // Already shutdown if (this.isShutdown) { return; } if (this.board) { this.board.removeChess(this[uidKey$1]); } ChessBank.remove(this[uidKey$1]); this.board = null; super.shutdown(fromScene); } setBoard(board) { this.board = board; return this; } get tileXYZ() { if (this.board == null) { return null; } return this.board.chessToTileXYZ(this[uidKey$1]); } setTileZ(tileZ) { if (this.board == null) { return this; } this.board.setChessTileZ(this.parent, tileZ); return this; } setBlocker(value) { if (value === undefined) { value = true; } this.blocker = value; return this; } setBlockEdge(direction, value) { if (this.blocker === false) { this.blocker = {}; } var blocker = this.blocker; if (IsPlainObject(direction)) { var blockEdges = direction; for (direction in blockEdges) { blocker[direction] = blockEdges[direction]; } } else { if (value === undefined) { value = true; } blocker[direction] = value; } return this; } getBlockEdge(direction) { var blocker = this.blocker; if (blocker === false) { return false; } if (!blocker.hasOwnProperty(direction)) { return false; } else { return blocker[direction]; } } } var methods$7 = { getTileDirection: GetTileDirection }; Object.assign( Chess.prototype, methods$7 ); var IsUID = function (object) { var type = typeof (object); return (type === 'number') || (type === 'string'); }; var GetChessData = function (gameObject) { // game object or uid if (IsUID(gameObject)) { // uid return ChessBank.get(gameObject); } else { // game object if (!gameObject.hasOwnProperty('rexChess') || !gameObject.rexChess) { gameObject.rexChess = new Chess(gameObject); } return gameObject.rexChess; } }; const uidKey = ChessBank.uidKey; var GetChessUID = function (gameObject) { // Game object or uid var uid; if (IsUID(gameObject)) { uid = gameObject; } else { uid = GetChessData(gameObject)[uidKey]; } return uid; }; var SetBoardWidth = function (width) { if (this.infinityMode) { return this; } if ((this.width === undefined) || (this.width <= width)) { this.width = width; return this; } // this.width > width : collapse var tileX, tileY, tileZ, tileZToUIDs; for (tileX = width; tileX < this.width; tileX++) { for (tileY = 0; tileY < this.height; tileY++) { tileZToUIDs = this.boardData.getUID(tileX, tileY); for (tileZ in tileZToUIDs) { this.RemoveChess(false, tileX, tileY, tileZ); } } } this.width = width; return this; }; var SetBoardHeight = function (height) { if (this.infinityMode) { return this; } if ((this.height === undefined) || (this.height <= height)) { this.height = height; return this; } // this.height > height : collapse var tileX, tileY, tileZ, tileZToUIDs; for (tileY = height; tileY < this.height; tileY++) { for (tileX = 0; tileX < this.width; tileX++) { tileZToUIDs = this.boardData.getUID(tileX, tileY); for (tileZ in tileZToUIDs) { this.RemoveChess(false, tileX, tileY, tileZ); } } } this.height = height; return this; }; var TileXYZToKey = function (tileX, tileY, tileZ, separator) { if (separator === undefined) { separator = ','; } return `${tileX}${separator}${tileY}${separator}${tileZ}`; }; var TileXYToKey = function (tileX, tileY, separator) { if (separator === undefined) { separator = ','; } return `${tileX}${separator}${tileY}`; }; var KeyToTileXYZ = function (key, out, separator) { if (out === undefined) { out = {}; } else if (out === true) { out = globTileXYZ$1; } if (separator === undefined) { separator = ','; } var items = key.split(separator); out.x = items[0]; out.y = items[1]; out.z = items[2]; return out; }; var globTileXYZ$1 = {}; var TileXYToWorldX = function (tileX, tileY) { // console.warn('Use board.tileXYToWorldXY instead of (board.tileXYToWorldX, board.tileXYToWorldY)'); return this.tileXYToWorldXY(tileX, tileY, true).x; }; var TileXYToWorldY = function (tileX, tileY) { // console.warn('Use board.tileXYToWorldXY instead of (board.tileXYToWorldX, board.tileXYToWorldY)'); return this.tileXYToWorldXY(tileX, tileY, true).y; }; var TileXYToWorldXY = function (tileX, tileY, out) { return this.grid.getWorldXY(tileX, tileY, out); }; var TileXYArrayToWorldXYArray = function (tileXYArray, out) { if (out === undefined) { out = []; } var tileXY; for (var i = 0, cnt = tileXYArray.length; i < cnt; i++) { tileXY = tileXYArray[i]; out.push(this.tileXYToWorldXY(tileXY.x, tileXY.y)); } return out; }; var WorldXYToTileX = function (worldX, worldY) { // console.warn('Use board.worldXYToTileXY instead of (board.worldXYToTileX, board.worldXYToTileY)'); return this.worldXYToTileXY(worldX, worldY, true).x; }; var WorldXYToTileY = function (worldX, worldY) { // console.warn('Use board.worldXYToTileXY instead of (board.worldXYToTileX, board.worldXYToTileY)'); return this.worldXYToTileXY(worldX, worldY, true).y; }; var WorldXYToTileXY = function (worldX, worldY, out) { return this.grid.getTileXY(worldX, worldY, out); }; var WorldXYToChessArray = function (worldX, worldY, out) { var tileXY = this.worldXYToTileXY(worldX, worldY, true); return this.tileXYToChessArray(tileXY.x, tileXY.y, out) }; var WorldXYToChess$1 = function (worldX, worldY, tileZ) { var tileXY = this.worldXYToTileXY(worldX, worldY, true); if (tileZ !== undefined) { return this.tileXYZToChess(tileXY.x, tileXY.y, tileZ) } else { var tileZToUIDs = this.boardData.getUID(tileXY.x, tileXY.y); if (tileZToUIDs == null) { return null; } for (var tileZ in tileZToUIDs) { return this.uidToChess(tileZToUIDs[tileZ]); } } }; var WorldXYSnapToGrid = function (worldX, worldY, out) { if (out === undefined) { out = {}; } else if (out === true) { out = globWorldXY$4; } this.worldXYToTileXY(worldX, worldY, out); this.tileXYToWorldXY(out.x, out.y, out); return out; }; var globWorldXY$4 = {}; /** * @author Richard Davey <rich@photonstorm.com> * @copyright 2018 Photon Storm Ltd. * @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License} */ /** * Find the angle of a segment from (x1, y1) -> (x2, y2). * * @function Phaser.Math.Angle.Between * @since 3.0.0 * * @param {number} x1 - The x coordinate of the first point. * @param {number} y1 - The y coordinate of the first point. * @param {number} x2 - The x coordinate of the second point. * @param {number} y2 - The y coordinate of the second point. * * @return {number} The angle in radians. */ var Between$1 = function (x1, y1, x2, y2) { return Math.atan2(y2 - y1, x2 - x1); }; var AngleBetween$2 = function (tileA, tileB) { tileA = this.chessToTileXYZ(tileA); tileB = this.chessToTileXYZ(tileB); var out = this.tileXYToWorldXY(tileA.x, tileA.y, true); var x0 = out.x; var y0 = out.y; out = this.tileXYToWorldXY(tileB.x, tileB.y, true); var x1 = out.x; var y1 = out.y; return Between$1(x0, y0, x1, y1); // -PI~PI }; /** * @author Richard Davey <rich@photonstorm.com> * @copyright 2019 Photon Storm Ltd. * @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License} */ /** * Normalize an angle to the [0, 2pi] range. * * @function Phaser.Math.Angle.Normalize * @since 3.0.0 * * @param {number} angle - The angle to normalize, in radians. * * @return {number} The normalized angle, in radians. */ var Normalize = function (angle) { angle = angle % (2 * Math.PI); if (angle >= 0) { return angle; } else { return angle + 2 * Math.PI; } }; /** * @author Richard Davey <rich@photonstorm.com> * @copyright 2019 Photon Storm Ltd. * @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License} */ /** * Check whether the given values are fuzzily equal. * * Two numbers are fuzzily equal if their difference is less than `epsilon`. * * @function Phaser.Math.Fuzzy.Equal * @since 3.0.0 * * @param {number} a - The first value. * @param {number} b - The second value. * @param {number} [epsilon=0.0001] - The epsilon. * * @return {boolean} `true` if the values are fuzzily equal, otherwise `false`. */ var Equal = function (a, b, epsilon) { if (epsilon === undefined) { epsilon = 0.0001; } return Math.abs(a - b) < epsilon; }; var IsAngleInCone = function (chessA, chessB, face, cone) { var tileXYA = this.chessToTileXYZ(chessA); var tileXYB = this.chessToTileXYZ(chessB); var targetAngle = this.angleBetween(tileXYA, tileXYB); // -PI~PI targetAngle = Normalize(targetAngle); // 0~2PI var deltaAngle = Math.abs(targetAngle - face); deltaAngle = Math.min(deltaAngle, PI2 - deltaAngle); var halfCone = cone / 2; return Equal(deltaAngle, halfCone) || (deltaAngle < halfCone); }; const PI2 = Math.PI * 2; var AngleToward = function (tileXY, direction) { if (tileXY === undefined) { tileXY = zeroTileXY; } // Save wrapMode, infinityMode and clear them var wrapModeSave = this.wrapMode; var infinityModeSave = this.infinityMode; this.wrapMode = false; this.infinityMode = true; // Get neighborTileXY var neighborTileXY = this.getNeighborTileXY(tileXY, direction, true); // Restore wrapMode, infinityMode and clear them this.wrapMode = wrapModeSave; this.infinityMode = infinityModeSave; return this.angleBetween(tileXY, neighborTileXY); // -PI~PI }; var zeroTileXY = { x: 0, y: 0 }; /** * @author Richard Davey <rich@photonstorm.com> * @copyright 2018 Photon Storm Ltd. * @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License} */ var RAD_TO_DEG = 180 / Math.PI; /** * Convert the given angle in radians, to the equivalent angle in degrees. * * @function Phaser.Math.RadToDeg * @since 3.0.0 * * @param {number} radians - The angle in radians to convert ot degrees. * * @return {integer} The given angle converted to degrees. */ var RadToDeg$2 = function (radians) { return radians * RAD_TO_DEG; }; /** * @author Richard Davey <rich@photonstorm.com> * @copyright 2019 Photon Storm Ltd. * @license {@link https://opensource.org/licenses/MIT|MIT License} */ /** * Gets the shortest angle between `angle1` and `angle2`. * * Both angles must be in the range -180 to 180, which is the same clamped * range that `sprite.angle` uses, so you can pass in two sprite angles to * this method and get the shortest angle back between the two of them. * * The angle returned will be in the same range. If the returned angle is * greater than 0 then it's a counter-clockwise rotation, if < 0 then it's * a clockwise rotation. * * TODO: Wrap the angles in this function? * * @function Phaser.Math.Angle.ShortestBetween * @since 3.0.0 * * @param {number} angle1 - The first angle in the range -180 to 180. * @param {number} angle2 - The second angle in the range -180 to 180. * * @return {number} The shortest angle, in degrees. If greater than zero it's a counter-clockwise rotation. */ var ShortestBetween = function (angle1, angle2) { var difference = angle2 - angle1; if (difference === 0) { return 0; } var times = Math.floor((difference - (-180)) / 360); return difference - (times * 360); }; var AngleSnapToDirection = function (tileXY, angle) { angle = RadToDeg$2(angle); // -180~180 var directions = this.grid.allDirections; var neighborAngle, deltaAngle; var minDeltaAngle = Infinity, direction = undefined; for (var i = 0, cnt = directions.length; i < cnt; i++) { neighborAngle = RadToDeg$2(this.angleToward(tileXY, directions[i])); // -PI~PI -> -180~180 deltaAngle = Math.abs(ShortestBetween(angle, neighborAngle)); if (deltaAngle < minDeltaAngle) { minDeltaAngle = deltaAngle; direction = i; } } return direction; }; var IsOverlappingPoint = function (worldX, worldY, tileZ) { if (this.infinityMode && (tileZ === undefined)) { return true; } var out = this.worldXYToTileXY(worldX, worldY, true); return this.contains(out.x, out.y, tileZ); }; var GridAlign = function (gameObject, tileX, tileY) { if (gameObject === undefined) { var chess = this.getAllChess(); for (var i = 0, cnt = chess.length; i < cnt; i++) { this.gridAlign(chess[i]); } } else { if (IsUID(gameObject)) { gameObject = this.uidToChess(gameObject); } if (tileX === undefined) { var tileXYZ = this.chessToTileXYZ(gameObject); tileX = tileXYZ.x; tileY = tileXYZ.y; } this.tileXYToWorldXY(tileX, tileY, gameObject); } return this; }; var GetGridPoints$2 = function (tileX, tileY, points) { if (tileX && (typeof (tileX) !== 'number')) { points = tileY; var tileXY = this.chessToTileXYZ(tileX); // tileX is a Chess or TileXY tileX = tileXY.x; tileY = tileXY.y; } return this.grid.getGridPoints(tileX, tileY, points); }; var GetGridBounds = function (tileX, tileY, out) { if (tileX && (typeof (tileX) !== 'number')) { out = tileY; var tileXY = this.chessToTileXYZ(tileX); // tileX is a Chess or TileXY tileX = tileXY.x; tileY = tileXY.y; } return this.grid.getBounds(tileX, tileY, out); }; /** * @author Richard Davey <rich@photonstorm.com> * @copyright 2019 Photon Storm Ltd. * @license {@link https://opensource.org/licenses/MIT|MIT License} */ // Taken from klasse by mattdesl https://github.com/mattdesl/klasse function hasGetterOrSetter (def) { return (!!def.get && typeof def.get === 'function') || (!!def.set && typeof def.set === 'function'); } function getProperty (definition, k, isClassDescriptor) { // This may be a lightweight object, OR it might be a property that was defined previously. // For simple class descriptors we can just assume its NOT previously defined. var def = (isClassDescriptor) ? definition[k] : Object.getOwnPropertyDescriptor(definition, k); if (!isClassDescriptor && def.value && typeof def.value === 'object') { def = def.value; } // This might be a regular property, or it may be a getter/setter the user defined in a class. if (def && hasGetterOrSetter(def)) { if (typeof def.enumerable === 'undefined') { def.enumerable = true; } if (typeof def.configurable === 'undefined') { def.configurable = true; } return def; } else { return false; } } function hasNonConfigurable (obj, k) { var prop = Object.getOwnPropertyDescriptor(obj, k); if (!prop) { return false; } if (prop.value && typeof prop.value === 'object') { prop = prop.value; } if (prop.configurable === false) { return true; } return false; } /** * Extends the given `myClass` object's prototype with the properties of `definition`. * * @function extend * @param {Object} ctor The constructor object to mix into. * @param {Object} definition A dictionary of functions for the class. * @param {boolean} isClassDescriptor Is the definition a class descriptor? * @param {Object} [extend] The parent constructor object. */ function extend (ctor, definition, isClassDescriptor, extend) { for (var k in definition) { if (!definition.hasOwnProperty(k)) { continue; } var def = getProperty(definition, k, isClassDescriptor); if (def !== false) { // If Extends is used, we will check its prototype to see if the final variable exists. var parent = extend || ctor; if (hasNonConfigurable(parent.prototype, k)) { // Just skip the final property if (Class.ignoreFinals) { continue; } // We cannot re-define a property that is configurable=false. // So we will consider them final and throw an error. This is by // default so it is clear to the developer what is happening. // You can set ignoreFinals to true if you need to extend a class // which has configurable=false; it will simply not re-define final properties. throw new Error('cannot override final property \'' + k + '\', set Class.ignoreFinals = true to skip'); } Object.defineProperty(ctor.prototype, k, def); } else { ctor.prototype[k] = definition[k]; } } } /** * Applies the given `mixins` to the prototype of `myClass`. * * @function mixin * @param {Object} myClass The constructor object to mix into. * @param {Object|Array<Object>} mixins The mixins to apply to the constructor. */ function mixin (myClass, mixins) { if (!mixins) { return; } if (!Array.isArray(mixins)) { mixins = [ mixins ]; } for (var i = 0; i < mixins.length; i++) { extend(myClass, mixins[i].prototype || mixins[i]); } } /** * Creates a new class with the given descriptor. * The constructor, defined by the name `initialize`, * is an optional function. If unspecified, an anonymous * function will be used which calls the parent class (if * one exists). * * You can also use `Extends` and `Mixins` to provide subclassing * and inheritance. * * @class Phaser.Class * @constructor * @param {Object} definition a dictionary of functions for the class * @example * * var MyClass = new Phaser.Class({ * * initialize: function() { * this.foo = 2.0; * }, * * bar: function() { * return this.foo + 5; * } * }); */ function Class (definition) { if (!definition) { definition = {}; } // The variable name here dictates what we see in Chrome debugger var initialize; var Extends; if (definition.initialize) { if (typeof definition.initialize !== 'function') { throw new Error('initialize must be a function'); } initialize = definition.initialize; // Usually we should avoid 'delete' in V8 at all costs. // However, its unlikely to make any performance difference // here since we only call this on class creation (i.e. not object creation). delete definition.initialize; } else if (definition.Extends) { var base = definition.Extends; initialize = function () { base.apply(this, arguments); }; } else { initialize = function () {}; } if (definition.Extends) { initialize.prototype = Object.create(definition.Extends.prototype); initialize.prototype.constructor = initialize; // For getOwnPropertyDescriptor to work, we need to act directly on the Extends (or Mixin) Extends = definition.Extends; delete definition.Extends; } else { initialize.prototype.constructor = initialize; } // Grab the mixins, if they are specified... var mixins = null; if (definition.Mixins) { mixins = definition.Mixins; delete definition.Mixins; } // First, mixin if we can. mixin(initialize, mixins); // Now we grab the actual definition which defines the overrides. extend(initialize, definition, true, Extends); return initialize; } Class.extend = extend; Class.mixin = mixin; Class.ignoreFinals = false; /** * @author Richard Davey <rich@photonstorm.com> * @copyright 2019 Photon Storm Ltd. * @license {@link https://opensource.org/licenses/MIT|MIT License} */ /** * Checks if a given point is inside a Rectangle's bounds. * * @function Phaser.Geom.Rectangle.Contains * @since 3.0.0 * * @param {Phaser.Geom.Rectangle} rect - The Rectangle to check. * @param {number} x - The X coordinate of the point to check. * @param {number} y - The Y coordinate of the point to check. * * @return {boolean} `true` if the point is within the Rectangle's bounds, otherwise `false`. */ var Contains$1 = function (rect, x, y) { if (rect.width <= 0 || rect.height <= 0) { return false; } return (rect.x <= x && rect.