phaser3-merged-input
Version:
A Phaser 3 plugin to handle input from keyboard, gamepad & mouse, allowing for easy key definition and multiplayer input
1,202 lines (1,123 loc) • 96.5 kB
JavaScript
(function webpackUniversalModuleDefinition(root, factory) {
if(typeof exports === 'object' && typeof module === 'object')
module.exports = factory();
else if(typeof define === 'function' && define.amd)
define("MergedInput", [], factory);
else if(typeof exports === 'object')
exports["MergedInput"] = factory();
else
root["MergedInput"] = factory();
})(self, () => {
return /******/ (() => { // webpackBootstrap
/******/ var __webpack_modules__ = ({
/***/ 348:
/***/ ((module) => {
/**
* @author Richard Davey <rich@photonstorm.com>
* @copyright 2013-2023 Photon Storm Ltd.
* @license {@link https://opensource.org/licenses/MIT|MIT License}
*/
/**
* Used internally by the KeyCombo class.
* Return `true` if it reached the end of the combo, `false` if not.
*
* @function Phaser.Input.Keyboard.AdvanceKeyCombo
* @private
* @since 3.0.0
*
* @param {KeyboardEvent} event - The native Keyboard Event.
* @param {Phaser.Input.Keyboard.KeyCombo} combo - The KeyCombo object to advance.
*
* @return {boolean} `true` if it reached the end of the combo, `false` if not.
*/
var AdvanceKeyCombo = function (event, combo)
{
combo.timeLastMatched = event.timeStamp;
combo.index++;
if (combo.index === combo.size)
{
return true;
}
else
{
combo.current = combo.keyCodes[combo.index];
return false;
}
};
module.exports = AdvanceKeyCombo;
/***/ }),
/***/ 353:
/***/ ((module) => {
/**
* @author Richard Davey <rich@photonstorm.com>
* @copyright 2013-2023 Photon Storm Ltd.
* @license {@link https://opensource.org/licenses/MIT|MIT License}
*/
/**
* Used internally by the KeyCombo class.
*
* @function Phaser.Input.Keyboard.ResetKeyCombo
* @private
* @since 3.0.0
*
* @param {Phaser.Input.Keyboard.KeyCombo} combo - The KeyCombo to reset.
*
* @return {Phaser.Input.Keyboard.KeyCombo} The KeyCombo.
*/
var ResetKeyCombo = function (combo)
{
combo.current = combo.keyCodes[0];
combo.index = 0;
combo.timeLastMatched = 0;
combo.matched = false;
combo.timeMatched = 0;
return combo;
};
module.exports = ResetKeyCombo;
/***/ }),
/***/ 399:
/***/ ((module) => {
/**
* Generic pad mapping
*/
module.exports = {
padID: 'Xbox 360 controller (XInput STANDARD GAMEPAD)',
padType: 'xbox',
gamepadMapping: {
RC_S: 0,
RC_E: 1,
RC_W: 2,
RC_N: 3,
START: 9,
SELECT: 8,
LB: 4,
RB: 5,
LT: 6,
RT: 7,
LS: 10,
RS: 11,
LC_N: 12,
LC_S: 13,
LC_W: 14,
LC_E: 15,
MENU: 16
}
};
/***/ }),
/***/ 436:
/***/ ((module) => {
/**
* 081f-e401 - UnlicensedSNES
*/
module.exports = {
padID: '081f-e401',
padType: 'snes',
gamepadMapping: {
RC_S: 2,
RC_E: 1,
RC_W: 3,
RC_N: 0,
START: 9,
SELECT: 8,
LB: 4,
RB: 5,
LC_N: 12,
LC_S: 13,
LC_W: 14,
LC_E: 15
}
};
/***/ }),
/***/ 518:
/***/ ((module) => {
/**
* Generic pad mapping
*/
module.exports = {
padID: 'Generic',
padType: 'generic',
gamepadMapping: {
RC_S: 0,
RC_E: 1,
RC_W: 2,
RC_N: 3,
START: 9,
SELECT: 8,
LB: 4,
RB: 5,
LT: 6,
RT: 7,
LS: 10,
RS: 11,
LC_N: 12,
LC_S: 13,
LC_W: 14,
LC_E: 15
}
};
/***/ }),
/***/ 635:
/***/ ((module) => {
/**
* Dualshock mapping
*/
module.exports = {
padID: 'Dualshock',
padType: 'Sony',
gamepadMapping: {
RC_S: 0,
RC_E: 1,
RC_W: 2,
RC_N: 3,
START: 9,
// Options
SELECT: 8,
// Share
LB: 4,
RB: 5,
LT: 6,
RT: 7,
LS: 10,
RS: 11,
LC_N: 12,
LC_S: 13,
LC_W: 14,
LC_E: 15,
MENU: 16,
TOUCH: 17
}
};
/***/ }),
/***/ 806:
/***/ ((module) => {
var bearings = {
'-180': 'W',
'-168.75': 'WBN',
'-157.5': 'WNW',
'-146.25': 'NWBW',
'-135': 'NW',
'-123.75': 'NWBN',
'-112.5': 'NNW',
'-101.25': 'NBW',
'-90': 'N',
'-78.75': 'NBE',
'-67.5': 'NNE',
'-56.25': 'NEBN',
'-45': 'NE',
'-33.75': 'NEBE',
'-22.5': 'ENE',
'-11.25': 'EBN',
'0': 'E',
'11.25': 'EBS',
'22.5': 'ESE',
'33.75': 'SEBE',
'45': 'SE',
'56.25': 'SEBS',
'67.5': 'SSE',
'78.75': 'SBE',
'90': 'S',
'101.25': 'SBW',
'112.5': 'SSW',
'123.75': 'SWBS',
'135': 'SW',
'146.25': 'SWBW',
'157.5': 'WSW',
'168.75': 'WBS',
'180': 'W'
};
module.exports = bearings;
/***/ })
/******/ });
/************************************************************************/
/******/ // The module cache
/******/ var __webpack_module_cache__ = {};
/******/
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/ // Check if module is in cache
/******/ var cachedModule = __webpack_module_cache__[moduleId];
/******/ if (cachedModule !== undefined) {
/******/ return cachedModule.exports;
/******/ }
/******/ // Create a new module (and put it into the cache)
/******/ var module = __webpack_module_cache__[moduleId] = {
/******/ // no module.id needed
/******/ // no module.loaded needed
/******/ exports: {}
/******/ };
/******/
/******/ // Execute the module function
/******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__);
/******/
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/
/************************************************************************/
/******/ /* webpack/runtime/compat get default export */
/******/ (() => {
/******/ // getDefaultExport function for compatibility with non-harmony modules
/******/ __webpack_require__.n = (module) => {
/******/ var getter = module && module.__esModule ?
/******/ () => (module['default']) :
/******/ () => (module);
/******/ __webpack_require__.d(getter, { a: getter });
/******/ return getter;
/******/ };
/******/ })();
/******/
/******/ /* webpack/runtime/define property getters */
/******/ (() => {
/******/ // define getter functions for harmony exports
/******/ __webpack_require__.d = (exports, definition) => {
/******/ for(var key in definition) {
/******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
/******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
/******/ }
/******/ }
/******/ };
/******/ })();
/******/
/******/ /* webpack/runtime/hasOwnProperty shorthand */
/******/ (() => {
/******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))
/******/ })();
/******/
/******/ /* webpack/runtime/make namespace object */
/******/ (() => {
/******/ // define __esModule on exports
/******/ __webpack_require__.r = (exports) => {
/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
/******/ }
/******/ Object.defineProperty(exports, '__esModule', { value: true });
/******/ };
/******/ })();
/******/
/************************************************************************/
var __webpack_exports__ = {};
// This entry needs to be wrapped in an IIFE because it needs to be in strict mode.
(() => {
"use strict";
// ESM COMPAT FLAG
__webpack_require__.r(__webpack_exports__);
// EXPORTS
__webpack_require__.d(__webpack_exports__, {
"default": () => (/* binding */ MergedInput)
});
// EXTERNAL MODULE: ./configs/bearings.js
var bearings = __webpack_require__(806);
var bearings_default = /*#__PURE__*/__webpack_require__.n(bearings);
// EXTERNAL MODULE: ./configs/pad_generic.js
var pad_generic = __webpack_require__(518);
var pad_generic_default = /*#__PURE__*/__webpack_require__.n(pad_generic);
// EXTERNAL MODULE: ./configs/pad_unlicensedSNES.js
var pad_unlicensedSNES = __webpack_require__(436);
var pad_unlicensedSNES_default = /*#__PURE__*/__webpack_require__.n(pad_unlicensedSNES);
// EXTERNAL MODULE: ./configs/pad_xbox360.js
var pad_xbox360 = __webpack_require__(399);
var pad_xbox360_default = /*#__PURE__*/__webpack_require__.n(pad_xbox360);
// EXTERNAL MODULE: ./configs/pad_dualshock.js
var pad_dualshock = __webpack_require__(635);
var pad_dualshock_default = /*#__PURE__*/__webpack_require__.n(pad_dualshock);
;// ./controlManager.js
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); }
var controlManager = /*#__PURE__*/function () {
function controlManager() {
_classCallCheck(this, controlManager);
}
return _createClass(controlManager, [{
key: "mapGamepad",
value: function mapGamepad(id) {
id = id.toLowerCase();
var padConfig = (pad_generic_default());
if (id.includes('081f') && id.includes('e401')) {
padConfig = (pad_unlicensedSNES_default());
} else if (id.includes('xbox') && id.includes('360')) {
padConfig = (pad_xbox360_default());
} else if (id.includes('054c')) {
padConfig = (pad_dualshock_default());
} else {}
return padConfig;
}
}, {
key: "getBaseControls",
value: function getBaseControls() {
return {
'direction': {
'UP': 0,
'DOWN': 0,
'LEFT': 0,
'RIGHT': 0,
'BEARING': '',
'BEARING_LAST': '',
'DEGREES': 0,
'DEGREES_LAST': 0,
'TIMESTAMP': 0
},
'direction_secondary': {
'UP': 0,
'DOWN': 0,
'LEFT': 0,
'RIGHT': 0,
'BEARING': '',
'DEGREES': 0,
'BEARING_LAST': '',
'DEGREES_LAST': 0,
'TIMESTAMP': 0
},
'buttons': {},
'timers': {},
'gamepadMapping': {
RC_S: 0,
RC_E: 1,
RC_W: 2,
RC_N: 3,
START: 9,
SELECT: 8,
LB: 4,
RB: 5,
LT: 6,
RT: 7,
LS: 10,
RS: 11,
LC_N: 12,
LC_S: 13,
LC_W: 14,
LC_E: 15,
MENU: 16
},
'pointer': {
'M1': 0,
'M2': 0,
'M3': 0,
'M4': 0,
'M5': 0,
'BEARING': '',
'BEARING_DEGREES': 0,
'ANGLE': 0,
'TIMESTAMP': 0
},
'position': {
x: 0,
y: 0
},
'position_last': {
x: 0,
y: 0
},
'gamepad': {},
'keys': {
'UP': [],
'DOWN': [],
'LEFT': [],
'RIGHT': []
},
'internal': {
'fakedpadBuffer': [],
'fakedpadPressed': [],
'fakedpadReleased': []
},
'interaction': {
'buffer': [],
'pressed': [],
'released': [],
'last': '',
'lastPressed': '',
'lastReleased': '',
'device': ''
},
'interaction_mapped': {
'pressed': [],
'released': [],
'last': '',
'lastPressed': '',
'lastReleased': '',
'gamepadType': ''
},
'buttons_mapped': {
RC_S: 0,
RC_E: 0,
RC_W: 0,
RC_N: 0,
START: 0,
SELECT: 0,
MENU: 0,
LB: 0,
RB: 0,
LT: 0,
RT: 0,
LS: 0,
RS: 0,
LC_N: 0,
LC_S: 0,
LC_W: 0,
LC_E: 0
}
};
}
/**
* Returns a struct to hold input control information
* Set up a struct for each player in the game
* Direction and Buttons contain the input from the devices
* The keys struct contains arrays of keyboard characters that will trigger the action
*/
}, {
key: "setupControls",
value: function setupControls(numberOfButtons) {
numberOfButtons = numberOfButtons || 16;
var controls = this.getBaseControls();
// Add buttons
for (var i = 0; i <= numberOfButtons; i++) {
controls.buttons['B' + i] = 0;
controls.keys['B' + i] = [];
}
// Add timers
for (var _i = 0; _i <= numberOfButtons; _i++) {
controls.timers['B' + _i] = {
'pressed': 0,
'released': 0,
'duration': 0
};
}
for (var _i2 = 0, _arr = ['UP', 'DOWN', 'LEFT', 'RIGHT', 'ALT_UP', 'ALT_DOWN', 'ALT_LEFT', 'ALT_RIGHT']; _i2 < _arr.length; _i2++) {
var thisDirection = _arr[_i2];
controls.timers[thisDirection] = {
'pressed': 0,
'released': 0,
'duration': 0
};
}
for (var _i3 = 0, _arr2 = ['M1', 'M2', 'M3', 'M4', 'M5']; _i3 < _arr2.length; _i3++) {
var thisPointer = _arr2[_i3];
controls.timers[thisPointer] = {
'pressed': 0,
'released': 0,
'duration': 0
};
}
controls.setPosition = function (x, y) {
this.position.x = x;
this.position.y = y;
};
return controls;
}
}]);
}();
// EXTERNAL MODULE: ../node_modules/phaser/src/input/keyboard/combo/AdvanceKeyCombo.js
var AdvanceKeyCombo = __webpack_require__(348);
var AdvanceKeyCombo_default = /*#__PURE__*/__webpack_require__.n(AdvanceKeyCombo);
// EXTERNAL MODULE: ../node_modules/phaser/src/input/keyboard/combo/ResetKeyCombo.js
var ResetKeyCombo = __webpack_require__(353);
var ResetKeyCombo_default = /*#__PURE__*/__webpack_require__.n(ResetKeyCombo);
;// ./ButtonCombo.js
function ButtonCombo_typeof(o) { "@babel/helpers - typeof"; return ButtonCombo_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; }, ButtonCombo_typeof(o); }
function ButtonCombo_classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); }
function ButtonCombo_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, ButtonCombo_toPropertyKey(o.key), o); } }
function ButtonCombo_createClass(e, r, t) { return r && ButtonCombo_defineProperties(e.prototype, r), t && ButtonCombo_defineProperties(e, t), Object.defineProperty(e, "prototype", { writable: !1 }), e; }
function ButtonCombo_toPropertyKey(t) { var i = ButtonCombo_toPrimitive(t, "string"); return "symbol" == ButtonCombo_typeof(i) ? i : i + ""; }
function ButtonCombo_toPrimitive(t, r) { if ("object" != ButtonCombo_typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != ButtonCombo_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" == ButtonCombo_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 _superPropGet(t, o, e, r) { var p = _get(_getPrototypeOf(1 & r ? t.prototype : t), o, e); return 2 & r && "function" == typeof p ? function (t) { return p.apply(e, t); } : p; }
function _get() { return _get = "undefined" != typeof Reflect && Reflect.get ? Reflect.get.bind() : function (e, t, r) { var p = _superPropBase(e, t); if (p) { var n = Object.getOwnPropertyDescriptor(p, t); return n.get ? n.get.call(arguments.length < 3 ? e : r) : n.value; } }, _get.apply(null, arguments); }
function _superPropBase(t, o) { for (; !{}.hasOwnProperty.call(t, o) && null !== (t = _getPrototypeOf(t));); 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); }
var ButtonCombo = /*#__PURE__*/function (_Phaser$Input$Keyboar) {
function ButtonCombo(mergedInput, player, buttons, config) {
var _this;
ButtonCombo_classCallCheck(this, ButtonCombo);
_this = _callSuper(this, ButtonCombo, [mergedInput.systems.input.keyboard, buttons, config]);
_this.player = player;
_this.mergedInput = mergedInput;
_this.keyCodes = buttons; // KeyCombo expects this to be an array of keycodes, we'll be checking against button names
mergedInput.events.on('gamepad_buttondown', _this.onButtonDown, _this);
_this.current = _this.keyCodes[0];
return _this;
}
_inherits(ButtonCombo, _Phaser$Input$Keyboar);
return ButtonCombo_createClass(ButtonCombo, [{
key: "onButtonDown",
value: function onButtonDown(event) {
if (this.matched || !this.enabled) {
return;
}
var matched = this.ProcessButtonCombo(event, this);
if (matched) {
this.mergedInput.eventEmitter.emit('mergedInput', {
combo: this,
player: this.player,
action: 'Button combo matched'
});
this.mergedInput.events.emit('buttoncombomatch', {
player: this.player,
combo: this
});
if (this.resetOnMatch) {
ResetKeyCombo_default()(this);
} else if (this.deleteOnMatch) {
this.destroy();
}
}
}
}, {
key: "ProcessButtonCombo",
value: function ProcessButtonCombo(event, combo) {
// Set a timestamp from the gamepad
event.timeStamp = this.mergedInput.systems.time.now;
// Don't check buttons on a different pad
if (combo.player.index !== event.player) {
return false;
}
// Check matched
if (combo.matched) {
return true;
}
// Compare the current action with the button pressed
var buttonMatch = false;
if (event.button === combo.current) {
buttonMatch = true;
}
var mappedButton = this.mergedInput.getMappedButton(combo.player, event.button);
if (mappedButton === combo.current) {
buttonMatch = true;
}
var unMappedButton = this.mergedInput.getUnmappedButton(combo.player, mappedButton);
if (unMappedButton === combo.current) {
buttonMatch = true;
}
var comboMatched = false;
var keyMatched = false;
if (buttonMatch) {
// Button was correct
if (combo.index > 0 && combo.maxKeyDelay > 0) {
// We have to check to see if the delay between
// the new key and the old one was too long (if enabled)
var timeLimit = combo.timeLastMatched + combo.maxKeyDelay;
// Check if they pressed it in time or not
if (event.timeStamp <= timeLimit) {
keyMatched = true;
comboMatched = AdvanceKeyCombo_default()(event, combo);
}
} else {
keyMatched = true;
// We don't check the time for the first key pressed, so just advance it
comboMatched = AdvanceKeyCombo_default()(event, combo);
}
}
if (!keyMatched && combo.resetOnWrongKey) {
// Wrong key was pressed
combo.index = 0;
combo.current = combo.keyCodes[0];
}
if (comboMatched) {
combo.timeLastMatched = event.timeStamp;
combo.matched = true;
combo.timeMatched = event.timeStamp;
}
return comboMatched;
}
}, {
key: "destroy",
value: function destroy() {
this.mergedInput.events.off('gamepad_buttondown', this.onButtonDown);
_superPropGet(ButtonCombo, "destroy", this, 3)([]);
}
}]);
}(Phaser.Input.Keyboard.KeyCombo);
;// ./main.js
function _toConsumableArray(r) { return _arrayWithoutHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _nonIterableSpread(); }
function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
function _iterableToArray(r) { if ("undefined" != typeof Symbol && null != r[Symbol.iterator] || null != r["@@iterator"]) return Array.from(r); }
function _arrayWithoutHoles(r) { if (Array.isArray(r)) return _arrayLikeToArray(r); }
function main_typeof(o) { "@babel/helpers - typeof"; return main_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; }, main_typeof(o); }
function _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }
function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t["return"] && (u = t["return"](), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }
function _arrayWithHoles(r) { if (Array.isArray(r)) return r; }
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; }
function main_classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); }
function main_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, main_toPropertyKey(o.key), o); } }
function main_createClass(e, r, t) { return r && main_defineProperties(e.prototype, r), t && main_defineProperties(e, t), Object.defineProperty(e, "prototype", { writable: !1 }), e; }
function main_toPropertyKey(t) { var i = main_toPrimitive(t, "string"); return "symbol" == main_typeof(i) ? i : i + ""; }
function main_toPrimitive(t, r) { if ("object" != main_typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != main_typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
function main_callSuper(t, o, e) { return o = main_getPrototypeOf(o), main_possibleConstructorReturn(t, main_isNativeReflectConstruct() ? Reflect.construct(o, e || [], main_getPrototypeOf(t).constructor) : o.apply(t, e)); }
function main_possibleConstructorReturn(t, e) { if (e && ("object" == main_typeof(e) || "function" == typeof e)) return e; if (void 0 !== e) throw new TypeError("Derived constructors may only return object or undefined"); return main_assertThisInitialized(t); }
function main_assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); return e; }
function main_isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (main_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }
function main_getPrototypeOf(t) { return main_getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, main_getPrototypeOf(t); }
function main_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 && main_setPrototypeOf(t, e); }
function main_setPrototypeOf(t, e) { return main_setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, main_setPrototypeOf(t, e); }
var MergedInput = /*#__PURE__*/function (_Phaser$Plugins$Scene) {
/**
* The Merged Input plugin is designed to run in the background and handle input.
* Upon detecting a keypress or gamepad interaction, the plugin will update a player object and emit global events.
*
* @extends Phaser.Plugins.ScenePlugin
* @param {*} scene
* @param {*} pluginManager
*/
function MergedInput(scene, pluginManager) {
var _this;
main_classCallCheck(this, MergedInput);
_this = main_callSuper(this, MergedInput, [scene, pluginManager]);
_this.scene = scene;
// Players
_this.players = [];
// Gamepads
_this.gamepads = [];
// Keys object to store Phaser key objects. We'll check these during update
_this.keys = {};
_this.bearings = (bearings_default());
_this.dpadMappings = {
'UP': 12,
'DOWN': 13,
'LEFT': 14,
'RIGHT': 15
};
// A threshold (between 0 and 1) below which analog stick input will be ignored
_this.axisThreshold = 0;
// The number of directions to snap to when mapping input to bearings (Defaults to 32)
_this.numDirections = Object.keys(_this.bearings).length - 1;
_this.controlManager = new controlManager();
return _this;
}
main_inherits(MergedInput, _Phaser$Plugins$Scene);
return main_createClass(MergedInput, [{
key: "boot",
value: function boot() {
var _this2 = this;
// Scene event emitter
this.eventEmitter = this.systems.events;
// Plugin event emitter
this.events = new Phaser.Events.EventEmitter();
this.game.events.on(Phaser.Core.Events.PRE_STEP, this.preupdate, this);
this.game.events.on(Phaser.Core.Events.POST_STEP, this.postupdate, this);
// Handle the game losing focus
this.game.events.on(Phaser.Core.Events.BLUR, function () {
_this2.loseFocus();
});
// Gamepad
if (typeof this.systems.input.gamepad !== 'undefined') {
this.systems.input.gamepad.on('connected', function (thisGamepad) {
this.refreshGamepads();
this.setupGamepad(thisGamepad);
}, this);
// Check to see if the gamepad has already been setup by the browser
this.systems.input.gamepad.refreshPads();
if (this.systems.input.gamepad.total) {
this.refreshGamepads();
var _iterator = _createForOfIteratorHelper(this.gamepads),
_step;
try {
for (_iterator.s(); !(_step = _iterator.n()).done;) {
var thisGamepad = _step.value;
this.systems.input.gamepad.emit('connected', thisGamepad);
}
} catch (err) {
_iterator.e(err);
} finally {
_iterator.f();
}
}
this.systems.input.gamepad.on('down', this.gamepadButtonDown, this);
this.systems.input.gamepad.on('up', this.gamepadButtonUp, this);
}
// Keyboard
this.systems.input.keyboard.on('keydown', this.keyboardKeyDown, this);
this.systems.input.keyboard.on('keyup', this.keyboardKeyUp, this);
// Pointer
this.systems.input.mouse.disableContextMenu();
}
}, {
key: "preupdate",
value: function preupdate() {
// If the first player has moved, we want to update the pointer position
if (typeof this.players[0] !== 'undefined') {
if (this.players[0].position.x !== this.players[0].position_last.x || this.players[0].position.y !== this.players[0].position_last.y) {
this.pointerMove(this.systems.input.activePointer);
}
}
this.players[0].position_last.x = this.players[0].position.x;
this.players[0].position_last.y = this.players[0].position.y;
this.checkKeyboardInput();
this.checkGamepadInput();
this.checkPointerInput();
// Loop through players and handle input
var _iterator2 = _createForOfIteratorHelper(this.players),
_step2;
try {
for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
var thisPlayer = _step2.value;
// If the pointer hasn't moved, and the scene has changed, this can end up as undefined
thisPlayer.pointer.BEARING = typeof thisPlayer.pointer.BEARING != 'undefined' ? thisPlayer.pointer.BEARING : '';
thisPlayer.pointer.BEARING_DEGREES = typeof thisPlayer.pointer.BEARING_DEGREES != 'undefined' ? thisPlayer.pointer.BEARING_DEGREES : 0;
thisPlayer.pointer.ANGLE = typeof thisPlayer.pointer.ANGLE != 'undefined' ? thisPlayer.pointer.ANGLE : '';
thisPlayer.pointer.DEGREES = typeof thisPlayer.pointer.DEGREES != 'undefined' ? thisPlayer.pointer.DEGREES : 0;
thisPlayer.pointer.POINTERANGLE = typeof thisPlayer.pointer.POINTERANGLE != 'undefined' ? thisPlayer.pointer.POINTERANGLE : '';
thisPlayer.pointer.POINTERDIRECTION = typeof thisPlayer.pointer.POINTERDIRECTION != 'undefined' ? thisPlayer.pointer.POINTERDIRECTION : '';
thisPlayer.pointer.PLAYERPOS = typeof thisPlayer.pointer.PLAYERPOS != 'undefined' ? thisPlayer.pointer.PLAYERPOS : '';
thisPlayer.direction.ANGLE = this.mapDirectionsToAngle(thisPlayer.direction);
thisPlayer.direction.ANGLE_LAST = thisPlayer.direction.ANGLE != '' ? thisPlayer.direction.ANGLE : thisPlayer.direction.ANGLE_LAST;
thisPlayer.direction.DEGREES = thisPlayer.direction.ANGLE !== -1 ? Math.round(Phaser.Math.RadToDeg(thisPlayer.direction.ANGLE) * 100) / 100 : -1;
thisPlayer.direction.DEGREES_LAST = thisPlayer.direction.DEGREES != -1 ? thisPlayer.direction.DEGREES : thisPlayer.direction.DEGREES_LAST;
thisPlayer.direction.BEARING = thisPlayer.direction.ANGLE !== -1 ? this.getBearingFromAngle(thisPlayer.direction.ANGLE) : '';
thisPlayer.direction.BEARING_LAST = thisPlayer.direction.BEARING != '' ? thisPlayer.direction.BEARING : thisPlayer.direction.BEARING_LAST;
thisPlayer.direction.BEARING_DEGREES = thisPlayer.direction.BEARING != '' ? parseFloat(this.mapBearingToDegrees(thisPlayer.direction.BEARING)) : 0;
thisPlayer.direction.BEARING_DEGREES_LAST = thisPlayer.direction.BEARING_LAST != '' ? parseFloat(this.mapBearingToDegrees(thisPlayer.direction.BEARING_LAST)) : 0;
thisPlayer.direction_secondary.ANGLE = this.mapDirectionsToAngle(thisPlayer.direction_secondary);
thisPlayer.direction_secondary.ANGLE_LAST = thisPlayer.direction_secondary.ANGLE != '' ? thisPlayer.direction_secondary.ANGLE : thisPlayer.direction_secondary.ANGLE_LAST;
thisPlayer.direction_secondary.DEGREES = thisPlayer.direction_secondary.ANGLE !== -1 ? Math.round(Phaser.Math.RadToDeg(thisPlayer.direction_secondary.ANGLE) * 100) / 100 : -1;
thisPlayer.direction_secondary.DEGREES_LAST = thisPlayer.direction_secondary.DEGREES != -1 ? thisPlayer.direction_secondary.DEGREES : thisPlayer.direction_secondary.DEGREES_LAST;
thisPlayer.direction_secondary.BEARING = thisPlayer.direction_secondary.ANGLE !== -1 ? this.getBearingFromAngle(thisPlayer.direction_secondary.ANGLE) : '';
thisPlayer.direction_secondary.BEARING_LAST = thisPlayer.direction_secondary.BEARING != '' ? thisPlayer.direction_secondary.BEARING : thisPlayer.direction_secondary.BEARING_LAST;
thisPlayer.direction_secondary.BEARING_DEGREES = thisPlayer.direction_secondary.BEARING != '' ? parseFloat(this.mapBearingToDegrees(thisPlayer.direction_secondary.BEARING)) : 0;
thisPlayer.direction_secondary.BEARING_DEGREES_LAST = thisPlayer.direction_secondary.BEARING_LAST != '' ? parseFloat(this.mapBearingToDegrees(thisPlayer.direction_secondary.BEARING_LAST)) : 0;
}
} catch (err) {
_iterator2.e(err);
} finally {
_iterator2.f();
}
}
}, {
key: "postupdate",
value: function postupdate() {
// Loop through players and manage buffered input
var _iterator3 = _createForOfIteratorHelper(this.players),
_step3;
try {
for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
var thisPlayer = _step3.value;
// Clear the interaction buffer
this.clearBuffer(thisPlayer);
}
} catch (err) {
_iterator3.e(err);
} finally {
_iterator3.f();
}
}
/**
* Clear the interaction buffer for the given player
* In the case of 'fake' DPad presses, we're using some convoluted buffers to keep the 'pressed' and 'released' values around for an extra tick
* As they're created in this update loop, they're otherwise cleared before the consumer can use them.
* @param {*} thisPlayer
*/
}, {
key: "clearBuffer",
value: function clearBuffer(thisPlayer) {
if (thisPlayer.interaction.pressed.length > 0 && thisPlayer.internal.fakedpadPressed.length == 0) {
thisPlayer.interaction.buffer = [];
}
if (thisPlayer.interaction.buffer.length == 0) {
thisPlayer.interaction.pressed = [];
thisPlayer.interaction_mapped.pressed = [];
if (thisPlayer.internal.fakedpadReleased.length == 0) {
thisPlayer.interaction.released = [];
thisPlayer.interaction_mapped.released = [];
}
}
thisPlayer.internal.fakedpadPressed = [];
thisPlayer.internal.fakedpadReleased = [];
}
/**
* Function to run when the game loses focus
* We want to fake releasing the buttons here, so that they're not stuck down without an off event when focus returns to the game
*/
}, {
key: "loseFocus",
value: function loseFocus() {
// Loop through defined keys and reset them
for (var thisKey in this.keys) {
this.keys[thisKey].reset();
}
}
/**
* Set up the gamepad and associate with a player object
*/
}, {
key: "setupGamepad",
value: function setupGamepad(thisGamepad) {
this.eventEmitter.emit('mergedInput', {
device: 'gamepad',
id: thisGamepad.id,
player: thisGamepad.index,
action: 'Connected'
});
this.events.emit('gamepad_connected', thisGamepad);
if (typeof this.players[thisGamepad.index] === 'undefined') {
this.addPlayer();
}
var gamepadID = thisGamepad.id.toLowerCase();
this.players[thisGamepad.index].gamepad = thisGamepad;
// Map the gamepad buttons
var mappedPad = this.controlManager.mapGamepad(gamepadID);
this.players[thisGamepad.index].gamepadMapping = mappedPad.gamepadMapping;
this.players[thisGamepad.index].interaction_mapped.gamepadType = mappedPad.padType;
for (var thisButton in this.players[thisGamepad.index].gamepadMapping) {
this.players[thisGamepad.index].buttons_mapped[thisButton] = 0;
}
}
/**
* Set a threshold (between 0 and 1) below which analog stick input will be ignored
* @param {*} value
* @returns
*/
}, {
key: "setAxisThreshold",
value: function setAxisThreshold(value) {
this.axisThreshold = value;
return this;
}
/**
* Set the number of directions to snap to when mapping input to bearings
*/
}, {
key: "setNumDirections",
value: function setNumDirections(value) {
if (typeof value === 'number' && value > 0) {
this.numDirections = value;
}
return this;
}
}, {
key: "refreshGamepads",
value: function refreshGamepads() {
// Sometimes, gamepads are undefined. For some reason.
this.gamepads = this.systems.input.gamepad.gamepads.filter(function (el) {
return el != null;
});
var _iterator4 = _createForOfIteratorHelper(this.gamepads.entries()),
_step4;
try {
for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) {
var _step4$value = _slicedToArray(_step4.value, 2),
index = _step4$value[0],
thisGamepad = _step4$value[1];
thisGamepad.index = index; // Overwrite the gamepad index, in case we had undefined gamepads earlier
/**
* Some cheap gamepads use the first axis as a dpad, in which case we won't have the dpad buttons 12-15
*/
thisGamepad.fakedpad = thisGamepad.buttons.length < 15;
}
} catch (err) {
_iterator4.e(err);
} finally {
_iterator4.f();
}
}
/**
* Add a new player object to the players array
* @param {number} index Player index - if a player object at this index already exists, it will be returned instead of creating a new player object
* @param {number} numberOfButtons The number of buttons to assign to the player object. Defaults to 16. Fewer than 16 is not recommended, as gamepad DPads typically map to buttons 12-15
*/
}, {
key: "addPlayer",
value: function addPlayer(index, numberOfButtons) {
numberOfButtons = numberOfButtons || 16;
if (main_typeof(Number.isInteger(index)) && typeof this.players[index] !== 'undefined') {
return this.players[index];
} else {
// Set up player object
var newPlayer = this.controlManager.setupControls(numberOfButtons);
// Add helper functions to the player object
this.addPlayerHelperFunctions(newPlayer);
// Push new player to players array
this.players.push(newPlayer);
this.players[this.players.length - 1].index = this.players.length - 1;
// If this is the first player, add the pointer events
if (this.players.length == 1) {
this.systems.input.on('pointermove', function (pointer) {
this.pointerMove(pointer);
}, this);
this.systems.input.on('pointerdown', function (pointer) {
this.pointerDown(pointer);
}, this);
this.systems.input.on('pointerup', function (pointer) {
this.pointerUp(pointer);
}, this);
}
return this.players[this.players.length - 1];
}
}
/**
* Add helper functions to the player object
* @param {*} player
*/
}, {
key: "addPlayerHelperFunctions",
value: function addPlayerHelperFunctions(player) {
var _this3 = this;
/**
* Pass a button name, or an array of button names to check if any were pressed in this update step.
* This will only fire once per button press. If you need to check for a button being held down, use isDown instead.
* Returns the name of the matched button(s), in case you need it.
*/
player.interaction.isPressed = function (button) {
button = typeof button === 'string' ? Array(button) : button;
var matchedButtons = button.filter(function (x) {
return player.interaction.pressed.includes(x);
});
return matchedButtons.length ? matchedButtons : false;
},
/**
* Pass a button name, or an array of button names to check if any are currently pressed in this update step.
* This differs from the isPressed function in that it will return true if the button is currently pressed, even if it was pressed in a previous update step.
* Returns the name of the matched button(s), in case you need it.
*/
player.interaction.isDown = function (button) {
button = typeof button === 'string' ? Array(button) : button;
var matchedButtons = button.filter(function (x) {
return player.buttons[x];
});
var matchedDirections = button.filter(function (x) {
return player.direction[x];
});
var matchedPointer = button.filter(function (x) {
return player.pointer[x];
});
var matchedAll = [].concat(_toConsumableArray(matchedButtons), _toConsumableArray(matchedDirections), _toConsumableArray(matchedPointer));
return matchedAll.length ? matchedAll : false;
},
/**
* Pass a button name, or an array of button names to check if any were released in this update step.
* Returns the name of the matched button(s), in case you need it.
*/
player.interaction.isReleased = function (button) {
button = typeof button === 'string' ? Array(button) : button;
var matchedButtons = button.filter(function (x) {
return player.interaction.released.includes(x);
});
return matchedButtons.length ? matchedButtons : false;
};
/**
* Pass a mapped button name, or an array of mapped button names to check if any were pressed in this update step.
* This will only fire once per button press. If you need to check for a button being held down, use isDown instead.
* Returns the name of the matched mapped button(s), in case you need it.
*/
player.interaction_mapped.isPressed = function (button) {
button = typeof button === 'string' ? Array(button) : button;
var matchedButtons = button.filter(function (x) {
return player.interaction_mapped.pressed.includes(x);
});
return matchedButtons.length ? matchedButtons : false;
},
/**
* Pass a mapped button name, or an array of mapped button names to check if any are currently pressed in this update step.
* This differs from the isPressed function in that it will return true if the button is currently pressed, even if it was pressed in a previous update step.
* Returns the name of the matched button(s), in case you need it.
*/
player.interaction_mapped.isDown = function (button) {
button = typeof button === 'string' ? Array(button) : button;
var matchedButtons = button.filter(function (x) {
return player.buttons_mapped[x];
});
return matchedButtons.length ? matchedButtons : false;
},
/**
* Pass a mapped button name, or an array of mapped button names to check if any were released in this update step.
* Returns the name of the matched mapped button(s), in case you need it.
*/
player.interaction_mapped.isReleased = function (button) {
button = typeof button === 'string' ? Array(button) : button;
var matchedButtons = button.filter(function (x) {
return player.interaction_mapped.released.includes(x);
});
return matchedButtons.length ? matchedButtons : false;
};
/**
* Pass a button name, or an array of button names to check if any are currently pressed in this update step.
* Similar to Phaser's keyboard plugin, the checkDown function can accept a 'duration' parameter, and will only register a press once every X milliseconds.
* Returns the name of the matched button(s)
*
* @param {string|array} button Array of buttons to check
* @param {number} duration The duration which must have elapsed before this button is considered as being down.
* @param {boolean} includeFirst - When true, the initial press of the button will be included in the results. Defaults to false.
*/
player.interaction.checkDown = function (button, duration, includeFirst) {
if (includeFirst === undefined) {
includeFirst = false;
}
if (duration === undefined) {
duration = 0;
}
var matchedButtons = [];
var downButtons = player.interaction.isDown(button);
if (downButtons.length) {
var _iterator5 = _createForOfIteratorHelper(downButtons),
_step5;
try {
var _loop = function _loop() {
var thisButton = _step5.value;
if (typeof player.timers[thisButton]._tick === 'undefined') {
player.timers[thisButton]._tick = 0;
if (includeFirst) {
matchedButtons.push(thisButton);
}
}
var t = Phaser.Math.Snap.Floor(_this3.scene.sys.time.now - player.timers[thisButton].pressed, duration);
if (t > player.timers[thisButton]._tick) {
_this3.game.events.once(Phaser.Core.Events.POST_STEP, function () {
player.timers[thisButton]._tick = t;
});
matchedButtons.push(thisButton);
}
};
for (_iterator5.s(); !(_step5 = _iterator5.n()).done;) {
_loop();
}
} catch (err) {
_iterator5.e(err);
} finally {
_iterator5.f();
}
}
return matchedButtons.length ? matchedButtons : false;
},
/**
* Mapped version of the checkDown version - resolves mapped button names and calls the checkDown function
*/
player.interaction_mapped.checkDown = function (button, duration, includeFirst) {
if (includeFirst === undefined) {
includeFirst = false;
}
var unmappedButtons = [];
// Resolve the unmapped button names to a new array
var _iterator6 = _createForOfIteratorHelper(button),
_step6;
try {
for (_iterator6.s(); !(_step6 = _iterator6.n()).done;) {
var thisButton = _step6.value;
var unmappedButton = _this3.getUnmappedButton(player, thisButton);
if (unmappedButton) {
unmappedButtons.push(unmappedButton);
}
}
} catch (err) {
_iterator6.e(err);
} finally {
_iterator6.f();
}
var downButtons = player.interaction.checkDown(unmappedButtons, duration, includeFirst);
return downButtons.length ? downButtons.map(function (x) {
return _this3.getMappedButton(player, x);
}) : false;
};
/**
* The previous functions are specific to the interaction and interaction_mapped definition of buttons.
* In general you would pick a definition scheme and query that object (interaction or interaction_mapped), just for ease though, we'll add some functions that accept either type of convention
*/
/**
* Pass a button name, or an array of button names to check if any were pressed in