UNPKG

@theatrejs/theatrejs

Version:

🎮 A JavaScript 2D Game Engine focused on creating pixel art games.

206 lines (147 loc) • 5.81 kB
import {EVENT_CODES, EVENT_TYPES, EventGravityAnalog, EventGravityDigital, Vector3} from '../index.js'; /** * The ordered list of the gravity event codes. * @type {Array<Array<string>>} * @constant * @private */ const $GRAVITY_DIRECTIONS = [ [EVENT_CODES.GRAVITY.DIRECTION_X_NEGATIVE, EVENT_CODES.GRAVITY.DIRECTION_X_POSITIVE], [EVENT_CODES.GRAVITY.DIRECTION_Y_NEGATIVE, EVENT_CODES.GRAVITY.DIRECTION_Y_POSITIVE], [EVENT_CODES.GRAVITY.DIRECTION_Z_NEGATIVE, EVENT_CODES.GRAVITY.DIRECTION_Z_POSITIVE] ]; /** * Creates gravity extensions. * * @example * * ExtensionGravity.activate(); */ class ExtensionGravity { /** * Stores the activated status. * @type {boolean} * @private * @static */ static $activated = false; /** * Stores the gravity. * @type {GravitySensor} * @private */ $gravity; /** * Stores the gravity state. * @type {Object<string, boolean>} * @private */ $stateGravity; /** * Creates a new gravity extension. * @protected */ constructor() { this.$stateGravity = {}; [...$GRAVITY_DIRECTIONS.flat()].forEach(($code) => { this.$stateGravity[$code] = false; }); this.$gravity = new GravitySensor({ 'frequency': 60 }); window.addEventListener(EVENT_TYPES.NATIVE.BLUR, this.$onBlur.bind(this)); this.$gravity.addEventListener(EVENT_TYPES.NATIVE.READING, this.$onGravity.bind(this)); this.$gravity.start(); } /** * Called when the focus is lost. * @private */ $onBlur() { $GRAVITY_DIRECTIONS.forEach(($pair) => { const [directionMinimum, directionMaximum] = $pair; if (this.$stateGravity[directionMinimum] === true) { this.$stateGravity[directionMinimum] = false; window.dispatchEvent(new EventGravityDigital(EVENT_TYPES.GRAVITY.GRAVITY_UP, directionMinimum)); } if (this.$stateGravity[directionMaximum] === true) { this.$stateGravity[directionMaximum] = false; window.dispatchEvent(new EventGravityDigital(EVENT_TYPES.GRAVITY.GRAVITY_UP, directionMaximum)); } }); } /** * Called when the gravity is updated. * @private */ $onGravity() { const gravity = new Vector3(this.$gravity.x, this.$gravity.y, this.$gravity.z).scale(-1); const gravityNormalized = gravity.normalize(); const gravityAnalog = [gravityNormalized.x, gravityNormalized.y, gravityNormalized.z]; const gravityMaximum = [0, 0, 0]; const lengthX = Math.abs(gravity.x); const lengthY = Math.abs(gravity.y); const lengthZ = Math.abs(gravity.z); const lengthMaximum = Math.max(lengthX, lengthY, lengthZ); if (lengthX === lengthMaximum) { gravityMaximum[0] = Math.sign(gravity.x); } else if (lengthY === lengthMaximum) { gravityMaximum[1] = Math.sign(gravity.y); } else if (lengthZ === lengthMaximum) { gravityMaximum[2] = Math.sign(gravity.z); } gravityMaximum.forEach(($direction, $index) => { const [directionMinimum, directionMaximum] = $GRAVITY_DIRECTIONS[$index]; if ($direction < 0) { if (this.$stateGravity[directionMaximum] === true) { this.$stateGravity[directionMaximum] = false; window.dispatchEvent(new EventGravityDigital(EVENT_TYPES.GRAVITY.GRAVITY_UP, directionMaximum)); } this.$stateGravity[directionMinimum] = true; window.dispatchEvent(new EventGravityDigital(EVENT_TYPES.GRAVITY.GRAVITY_DOWN, directionMinimum)); window.dispatchEvent(new EventGravityAnalog(EVENT_TYPES.GRAVITY.GRAVITY_ANALOG, directionMinimum, - gravityAnalog[$index])); } else if ($direction > 0) { if (this.$stateGravity[directionMinimum] === true) { this.$stateGravity[directionMinimum] = false; window.dispatchEvent(new EventGravityDigital(EVENT_TYPES.GRAVITY.GRAVITY_UP, directionMinimum)); } this.$stateGravity[directionMaximum] = true; window.dispatchEvent(new EventGravityDigital(EVENT_TYPES.GRAVITY.GRAVITY_DOWN, directionMaximum)); window.dispatchEvent(new EventGravityAnalog(EVENT_TYPES.GRAVITY.GRAVITY_ANALOG, directionMaximum, gravityAnalog[$index])); } else { if (this.$stateGravity[directionMinimum] === true) { this.$stateGravity[directionMinimum] = false; window.dispatchEvent(new EventGravityDigital(EVENT_TYPES.GRAVITY.GRAVITY_UP, directionMinimum)); } if (this.$stateGravity[directionMaximum] === true) { this.$stateGravity[directionMaximum] = false; window.dispatchEvent(new EventGravityDigital(EVENT_TYPES.GRAVITY.GRAVITY_UP, directionMaximum)); window.dispatchEvent(new EventGravityAnalog(EVENT_TYPES.GRAVITY.GRAVITY_ANALOG, directionMaximum, gravityAnalog[$index])); } } }); } /** * Activates the extension. * @public * @static */ static activate() { if (typeof window.GravitySensor === 'undefined') { return; } if (ExtensionGravity.$activated === true) { return; } new ExtensionGravity(); ExtensionGravity.$activated = true; } } export { ExtensionGravity }; export default ExtensionGravity;