UNPKG

@sacredcasuals/shared-lib

Version:

Shared game utilities and UI components for Sacred Casuals apps

1,649 lines (1,619 loc) 216 kB
"use strict"; var __create = Object.create; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __getProtoOf = Object.getPrototypeOf; var __hasOwnProp = Object.prototype.hasOwnProperty; var __commonJS = (cb, mod) => function __require() { return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports; }; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( // If the importer is in node compatibility mode or this is not an ESM // file that has been converted to a CommonJS file using a Babel- // compatible transform (i.e. "__esModule" has not been set), then set // "default" to the CommonJS "module.exports" for node compatibility. isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, mod )); var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); // node_modules/typed-signals/dist/Collector.js var require_Collector = __commonJS({ "node_modules/typed-signals/dist/Collector.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.Collector = void 0; var Collector = class { /** * Create a new collector. * * @param signal The signal to emit. */ constructor(signal) { this.emit = (...args) => { signal["emitCollecting"](this, args); }; } }; exports2.Collector = Collector; } }); // node_modules/typed-signals/dist/CollectorArray.js var require_CollectorArray = __commonJS({ "node_modules/typed-signals/dist/CollectorArray.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.CollectorArray = void 0; var Collector_1 = require_Collector(); var CollectorArray = class extends Collector_1.Collector { constructor() { super(...arguments); this.result = []; } handleResult(result) { this.result.push(result); return true; } /** * Get the list of results from the signal handlers. */ getResult() { return this.result; } /** * Reset the result */ reset() { this.result.length = 0; } }; exports2.CollectorArray = CollectorArray; } }); // node_modules/typed-signals/dist/CollectorLast.js var require_CollectorLast = __commonJS({ "node_modules/typed-signals/dist/CollectorLast.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.CollectorLast = void 0; var Collector_1 = require_Collector(); var CollectorLast = class extends Collector_1.Collector { handleResult(result) { this.result = result; return true; } /** * Get the result of the last signal handler. */ getResult() { return this.result; } /** * Reset the result */ reset() { delete this.result; } }; exports2.CollectorLast = CollectorLast; } }); // node_modules/typed-signals/dist/CollectorUntil0.js var require_CollectorUntil0 = __commonJS({ "node_modules/typed-signals/dist/CollectorUntil0.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.CollectorUntil0 = void 0; var Collector_1 = require_Collector(); var CollectorUntil0 = class extends Collector_1.Collector { constructor() { super(...arguments); this.result = false; } handleResult(result) { this.result = result; return this.result; } /** * Get the result of the last signal handler. */ getResult() { return this.result; } /** * Reset the result */ reset() { this.result = false; } }; exports2.CollectorUntil0 = CollectorUntil0; } }); // node_modules/typed-signals/dist/CollectorWhile0.js var require_CollectorWhile0 = __commonJS({ "node_modules/typed-signals/dist/CollectorWhile0.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.CollectorWhile0 = void 0; var Collector_1 = require_Collector(); var CollectorWhile0 = class extends Collector_1.Collector { constructor() { super(...arguments); this.result = false; } handleResult(result) { this.result = result; return !this.result; } /** * Get the result of the last signal handler. */ getResult() { return this.result; } /** * Reset the result */ reset() { this.result = false; } }; exports2.CollectorWhile0 = CollectorWhile0; } }); // node_modules/typed-signals/dist/SignalConnection.js var require_SignalConnection = __commonJS({ "node_modules/typed-signals/dist/SignalConnection.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.SignalConnectionImpl = void 0; var SignalConnectionImpl = class { /** * @param link The actual link of the connection. * @param parentCleanup Callback to cleanup the parent signal when a connection is disconnected */ constructor(link, parentCleanup) { this.link = link; this.parentCleanup = parentCleanup; } disconnect() { if (this.link !== null) { this.link.unlink(); this.link = null; this.parentCleanup(); this.parentCleanup = null; return true; } return false; } set enabled(enable) { if (this.link) this.link.setEnabled(enable); } get enabled() { return this.link !== null && this.link.isEnabled(); } }; exports2.SignalConnectionImpl = SignalConnectionImpl; } }); // node_modules/typed-signals/dist/SignalLink.js var require_SignalLink = __commonJS({ "node_modules/typed-signals/dist/SignalLink.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.SignalLink = void 0; var SignalLink = class _SignalLink { constructor(prev = null, next = null, order = 0) { this.enabled = true; this.newLink = false; this.callback = null; this.prev = prev !== null && prev !== void 0 ? prev : this; this.next = next !== null && next !== void 0 ? next : this; this.order = order; } isEnabled() { return this.enabled && !this.newLink; } setEnabled(flag) { this.enabled = flag; } unlink() { this.callback = null; this.next.prev = this.prev; this.prev.next = this.next; } insert(callback, order) { let after = this.prev; while (after !== this) { if (after.order <= order) break; after = after.prev; } const link = new _SignalLink(after, after.next, order); link.callback = callback; after.next = link; link.next.prev = link; return link; } }; exports2.SignalLink = SignalLink; } }); // node_modules/typed-signals/dist/Signal.js var require_Signal = __commonJS({ "node_modules/typed-signals/dist/Signal.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.Signal = void 0; var SignalConnection_1 = require_SignalConnection(); var SignalLink_1 = require_SignalLink(); var Signal3 = class { constructor() { this.head = new SignalLink_1.SignalLink(); this.hasNewLinks = false; this.emitDepth = 0; this.connectionsCount = 0; } /** * @returns The number of connections on this signal. */ getConnectionsCount() { return this.connectionsCount; } /** * @returns true if this signal has connections. */ hasConnections() { return this.connectionsCount > 0; } /** * Subscribe to this signal. * * @param callback This callback will be run when emit() is called. * @param order Handlers with a higher order value will be called later. */ connect(callback, order = 0) { this.connectionsCount++; const link = this.head.insert(callback, order); if (this.emitDepth > 0) { this.hasNewLinks = true; link.newLink = true; } return new SignalConnection_1.SignalConnectionImpl(link, () => this.decrementConnectionCount()); } decrementConnectionCount() { this.connectionsCount--; } /** * Unsubscribe from this signal with the original callback instance. * While you can use this method, the SignalConnection returned by connect() will not be updated! * * @param callback The callback you passed to connect(). */ disconnect(callback) { for (let link = this.head.next; link !== this.head; link = link.next) { if (link.callback === callback) { this.decrementConnectionCount(); link.unlink(); return true; } } return false; } /** * Disconnect all handlers from this signal event. */ disconnectAll() { while (this.head.next !== this.head) { this.head.next.unlink(); } this.connectionsCount = 0; } /** * Publish this signal event (call all handlers). */ emit(...args) { this.emitDepth++; for (let link = this.head.next; link !== this.head; link = link.next) { if (link.isEnabled() && link.callback) link.callback.apply(null, args); } this.emitDepth--; this.unsetNewLink(); } emitCollecting(collector, args) { this.emitDepth++; for (let link = this.head.next; link !== this.head; link = link.next) { if (link.isEnabled() && link.callback) { const result = link.callback.apply(null, args); if (!collector.handleResult(result)) break; } } this.emitDepth--; this.unsetNewLink(); } unsetNewLink() { if (this.hasNewLinks && this.emitDepth === 0) { for (let link = this.head.next; link !== this.head; link = link.next) link.newLink = false; this.hasNewLinks = false; } } }; exports2.Signal = Signal3; } }); // node_modules/typed-signals/dist/SignalConnections.js var require_SignalConnections = __commonJS({ "node_modules/typed-signals/dist/SignalConnections.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.SignalConnections = void 0; var SignalConnections = class { constructor() { this.list = []; } /** * Add a connection to the list. * @param connection */ add(connection) { this.list.push(connection); } /** * Disconnect all connections in the list and empty the list. */ disconnectAll() { for (const connection of this.list) { connection.disconnect(); } this.list = []; } /** * @returns The number of connections in this list. */ getCount() { return this.list.length; } /** * @returns true if this list is empty. */ isEmpty() { return this.list.length === 0; } }; exports2.SignalConnections = SignalConnections; } }); // node_modules/typed-signals/dist/index.js var require_dist = __commonJS({ "node_modules/typed-signals/dist/index.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.SignalConnections = exports2.Signal = exports2.CollectorWhile0 = exports2.CollectorUntil0 = exports2.CollectorLast = exports2.CollectorArray = exports2.Collector = void 0; var Collector_1 = require_Collector(); Object.defineProperty(exports2, "Collector", { enumerable: true, get: function() { return Collector_1.Collector; } }); var CollectorArray_1 = require_CollectorArray(); Object.defineProperty(exports2, "CollectorArray", { enumerable: true, get: function() { return CollectorArray_1.CollectorArray; } }); var CollectorLast_1 = require_CollectorLast(); Object.defineProperty(exports2, "CollectorLast", { enumerable: true, get: function() { return CollectorLast_1.CollectorLast; } }); var CollectorUntil0_1 = require_CollectorUntil0(); Object.defineProperty(exports2, "CollectorUntil0", { enumerable: true, get: function() { return CollectorUntil0_1.CollectorUntil0; } }); var CollectorWhile0_1 = require_CollectorWhile0(); Object.defineProperty(exports2, "CollectorWhile0", { enumerable: true, get: function() { return CollectorWhile0_1.CollectorWhile0; } }); var Signal_1 = require_Signal(); Object.defineProperty(exports2, "Signal", { enumerable: true, get: function() { return Signal_1.Signal; } }); var SignalConnections_1 = require_SignalConnections(); Object.defineProperty(exports2, "SignalConnections", { enumerable: true, get: function() { return SignalConnections_1.SignalConnections; } }); } }); // src/index.ts var index_exports = {}; __export(index_exports, { AbstractApp: () => AbstractApp, AbstractInfoDialog: () => AbstractInfoDialog, AbstractPixiRoot: () => AbstractPixiRoot, AbstractPreferencesManager: () => AbstractPreferencesManager, Align: () => Align, ArrayUtils: () => ArrayUtils, AtlasMold: () => AtlasMold, AtlasTextureMold: () => AtlasTextureMold, BUTTON_EVENTS: () => BUTTON_EVENTS, BackgroundEffect: () => BackgroundEffect, BackgroundEffectParticle: () => BackgroundEffectParticle, Button: () => Button, Checkbox: () => Checkbox, ClickArea: () => ClickArea, Container: () => Container3, DateUtils: () => DateUtils, DeviceDetectorService: () => DeviceDetectorService, DeviceManager: () => DeviceManager, ErrorInfo: () => ErrorInfo, ErrorManager: () => ErrorManager, FrameMold: () => FrameMold, FuncUtil: () => FuncUtil, GameDelayCall: () => GameDelayCall, GameDialog: () => GameDialog, GameDialogLayer: () => GameDialogLayer, GameDispatcher: () => GameDispatcher, GameJuggler: () => GameJuggler, GameObject: () => GameObject, GamePool: () => GamePool, GameQuadtreeView: () => GameQuadtreeView, GameScreen: () => GameScreen, GameScreenLayer: () => GameScreenLayer, GameScreenNavigator: () => GameScreenNavigator, GameSplashScreen: () => GameSplashScreen, GameSprite: () => GameSprite, GameTween: () => GameTween, GameView: () => GameView, GameWaiter: () => GameWaiter, Input: () => Input2, KeyframeMold: () => KeyframeMold, LibraryFlump: () => LibraryFlump, LibraryMold: () => LibraryMold, LibrarySpine: () => LibrarySpine, LibraryText: () => LibraryText, List: () => List, LocaleManager: () => LocaleManager, MathUtils: () => MathUtils, Movie: () => Movie, MovieLayer: () => MovieLayer, MovieLayerMold: () => MovieLayerMold, MovieMold: () => MovieMold, NetworkManager: () => NetworkManager, ObjectUtils: () => ObjectUtils, PixiAssetsLoader: () => PixiAssetsLoader, Placer: () => Placer, Quadtree: () => Quadtree, QuadtreeNode: () => QuadtreeNode, RectangleUtils: () => RectangleUtils, ScaleMode: () => ScaleMode, ScrollBox: () => ScrollBox, SlidingNumber: () => SlidingNumber, SoundManager: () => SoundManager, SpineMovie: () => SpineMovie, SplashLayer: () => SplashLayer, Spring: () => Spring, TabButton: () => TabButton, TextInput: () => TextInput, TextureGroupMold: () => TextureGroupMold, Trackpad: () => Trackpad, UILayer: () => UILayer, ViewUtils: () => ViewUtils, WaiterLayer: () => WaiterLayer, centerElement: () => centerElement, centerView: () => centerView, cleanup: () => cleanup, defaultTextStyle: () => defaultTextStyle, fitToView: () => fitToView, getTextView: () => getTextView, getView: () => getView }); module.exports = __toCommonJS(index_exports); // src/managers/DeviceManager.ts var import_device = require("@capacitor/device"); var import_app = require("@capacitor/app"); var import_capacitor_plugin_safe_area = require("capacitor-plugin-safe-area"); var import_capacitor_secure_storage_plugin = require("capacitor-secure-storage-plugin"); // src/pixi/AbstractPixiRoot.ts var PIXI7 = __toESM(require("pixi.js"), 1); // src/pixi/base/GameView.ts var PIXI = __toESM(require("pixi.js"), 1); var import_tween = require("@tweenjs/tween.js"); var GameView = class extends PIXI.Container { constructor(...args) { super(); } onResize() { } set interactive(value) { super.interactive = value; this.interactiveChildren = value; } get pulsatingDisplayObject() { return this; } startPulsating(scaleDiff = 0.03, time = 0.6) { this._pulsateTween?.destroy(); this._pulsateTween = this.juggler.tween(this.pulsatingDisplayObject, 2, { scale: { y: this.pulsatingDisplayObject.scale.y - scaleDiff, x: this.pulsatingDisplayObject.scale.x - scaleDiff * 3 } }).repeat(Infinity).yoyoFix((t) => import_tween.Easing.Linear.InOut(t)).start(); } continuePulsating() { if (this._pulsateTween) { this.juggler.addAnimatable(this._pulsateTween); } } stopPulsating() { if (this._pulsateTween) { this.juggler.removeAnimatable(this._pulsateTween); } } advanceTime(delta) { } addToJuggler() { this.juggler?.addAnimatable(this); } removeFromJuggler() { this.juggler?.removeAnimatable(this); } onRemovedFromJuggler() { } get juggler() { return this._juggler || this.root?.juggler; } set juggler(value) { this._juggler = value; } destroyChildren() { while (this.children.length > 0) { const child = this.removeChildAt(0); if ("destroy" in child && typeof child.destroy === "function") { child.destroy({ children: true }); } } } destroy() { if (this.destroyed) { return; } this._pulsateTween?.destroy(); this.removeFromJuggler(); this.removeFromParent(); this.destroyChildren(); super.destroy({ children: true }); } }; // src/pixi/base/GameObject.ts var PIXI2 = __toESM(require("pixi.js"), 1); var isIDestroy = (obj) => { return obj && typeof obj.destroy === "function" && typeof obj.destroyed === "boolean"; }; var GameObject = class _GameObject { constructor() { this._isDestroyed = false; this._juggler = null; } advanceTime(delta) { } addToJuggler() { this.juggler?.addAnimatable(this); } onRemovedFromJuggler() { } removeFromJuggler() { this.juggler?.removeAnimatable(this); } get juggler() { return this._juggler; } set juggler(value) { this._juggler = value; } get destroyed() { return this._isDestroyed; } static destroy(object) { if (!object) { return null; } if (object instanceof _GameObject || object instanceof GameView) { object.destroy(); return null; } if (isIDestroy(object)) { object.destroy(); return null; } if (Array.isArray(object)) { const objects = object; if (objects) { while (objects.length) { this.destroy(objects.pop()); } } return null; } if (object instanceof PIXI2.Container) { let container = object; container.removeFromParent(); container.destroy({ children: true }); } return null; } onReturnToPool() { } onGetFromPool(pool) { } destroy() { if (!this._isDestroyed) { this._isDestroyed = true; this.removeFromJuggler(); } } }; // src/pixi/base/GameDispatcher.ts var GameDispatcher = class extends GameObject { constructor(sender) { super(); this._sender = sender; this._listeners = /* @__PURE__ */ new Map(); } add(listener, context) { if (this._isDestroyed || !listener) { return; } if (!this._listeners.has(listener)) { const boundListener = context ? listener.bind(context) : listener; this._listeners.set(listener, boundListener); } } remove(listener) { if (this.destroyed || !listener) { return; } if (this._listeners.has(listener)) { this._listeners.delete(listener); } } dispatch(argument) { if (this._isDestroyed || !this._listeners) { return; } for (const [, boundListener] of this._listeners) { boundListener(this._sender, argument); } } hasListener(listener) { if (this.destroyed || !listener) { return false; } return this._listeners.has(listener); } removeAllListeners() { if (this._listeners) { this._listeners.clear(); } } destroy() { if (this._listeners) { this._listeners.clear(); this._listeners = null; } this._sender = null; super.destroy(); } }; // src/pixi/base/GameScreen.ts var PIXI5 = __toESM(require("pixi.js"), 1); // src/pixi/effects/BackgroundEffect.ts var PIXI3 = __toESM(require("pixi.js"), 1); // src/utils/MathUtils.ts var _MathUtils = class _MathUtils { static getMidPoint(startX, startY, endX, endY) { const distance = _MathUtils.getDistance(startX, startY, endX, endY); const point = { x: (startX + endX) / 2, y: (startY + endY) / 2 }; if (_MathUtils.getRandomInt(0, 1) === 0) { point.x += 0.01 * _MathUtils.getRandomInt(10, 20) * distance; } else { point.x -= 0.01 * _MathUtils.getRandomInt(10, 20) * distance; } return point; } static getRandomElementOf(array) { const idx = Math.floor(Math.random() * array.length); return array[idx]; } static toArray(iterable) { return Array.from(iterable); } static isEvenInt(value) { return value % 2 === 0; } static getDistance(x1, y1, x2, y2) { return Math.sqrt((y2 - y1) ** 2 + (x2 - x1) ** 2); } static getRandomInt(fromNum, toNum) { if (fromNum === toNum) { return fromNum; } return Math.floor(fromNum + Math.random() * (toNum - fromNum + 1)); } static getRandomNumber(fromNum, toNum) { if (fromNum === toNum) { return fromNum; } return fromNum + Math.random() * (toNum - fromNum); } static getAngle(x1, y1, x2, y2) { if (x2 !== x1) { let angle = 180 / Math.PI * Math.atan((y2 - y1) / (x2 - x1)); if (x1 < x2) angle += 180; if (angle < 0) angle += 360; return angle; } else { return y1 < y2 ? 270 : 90; } } static generateRandomArray(length) { const array = Array.from({ length }, (_, i) => i); for (let i = 0; i < length; i++) { const r = _MathUtils.generateRandom(0, length); [array[i], array[r]] = [array[r], array[i]]; } return array; } static generateRandom(min, max) { if (min === max) return min; if (max > min) return _MathUtils.randomInt() % (max - min) + min; return _MathUtils.randomInt() % (min - max) + max; } static randomBoolean() { return _MathUtils.randomInt() % 2 === 0; } static chance(chance) { if (chance < 2) return true; return _MathUtils.randomInt() % chance === 0; } static chooseWeighedItem(weights) { const totalWeight = weights.reduce((sum, weight) => sum + weight, 0); if (totalWeight === 0) return 0; let randomWeight = _MathUtils.randomInt() % totalWeight; for (let i = 0; i < weights.length; i++) { randomWeight -= weights[i]; if (randomWeight < 0) return i; } return 0; } static randomInt() { return Math.round(Math.random() * Number.MAX_SAFE_INTEGER); } static deg2rad(degrees) { return degrees * _MathUtils.DEG_TO_RAD; } static int(num) { return Math.floor(num); } static float(num, decimals) { const multiplier = Math.pow(10, decimals); return Math.round(num * multiplier) / multiplier; } static distance(point1, point2) { if (point1 && point2) { const dx = point2.x - point1.x; const dy = point2.y - point1.y; return Math.sqrt(dx * dx + dy * dy); } return 0; } }; _MathUtils.DEG_TO_RAD = Math.PI / 180; var MathUtils = _MathUtils; // src/pixi/effects/BackgroundEffect.ts var BackgroundEffectParticle = class extends GameView { constructor(root, layerNum) { super(); this._dx = 0; this._dy = 0; this._rotSpeed = 0; this.root = root; let image = this.createParticleImage(); image.anchor.set(0.5); this.addChild(image); this.x = MathUtils.getRandomInt(0, this.root.fixedStageWidth); this.y = MathUtils.getRandomInt(-32 * this.root.scaleFactor / 4, this.root.fixedStageHeight); let minSpeed = 0; let maxSpeed = 0; switch (layerNum) { case 1: this.scale = MathUtils.getRandomInt(20, 30) * 0.01; minSpeed = 3; maxSpeed = 4; break; case 2: this.scale = MathUtils.getRandomInt(40, 60) * 0.01; minSpeed = 4; maxSpeed = 6; break; case 3: this.scale = MathUtils.getRandomInt(70, 80) * 0.01; minSpeed = 7; maxSpeed = 9; break; } if (layerNum == 2 || layerNum == 3) { if (MathUtils.getRandomInt(0, 1) == 1) { this._rotSpeed = MathUtils.deg2rad(0.1 * MathUtils.getRandomInt(10, 20)); } else { this._rotSpeed = MathUtils.deg2rad(0.1 * MathUtils.getRandomInt(-20, -10)); } } minSpeed *= this.root.scaleFactor / 4; maxSpeed *= this.root.scaleFactor / 4; let fallSpeed = 0.75; let speed = MathUtils.getRandomInt(minSpeed, maxSpeed) * fallSpeed; let angle = MathUtils.getRandomInt(250, 290); this._dx = speed * Math.cos((180 - angle) * Math.PI / 180); this._dy = -speed * Math.sin((180 - angle) * Math.PI / 180); } get horizontalForce() { return 0; } update() { this.x += this._dx + this.horizontalForce * this.scale.x; this.y += this._dy; if (this._rotSpeed != 0) { this.rotation += this._rotSpeed; } if (this.y > this.root.fixedStageHeight || this.x > this.root.fixedStageWidth || this.x < 0) { this.x = MathUtils.getRandomInt(0, this.root.fixedStageWidth); this.y = -32 * this.root.scaleFactor / 4; } } createParticleImage() { return new PIXI3.Sprite(this.root.uiLib.getTexture("petal")); } }; var BackgroundEffect = class extends GameView { constructor(root, particlesCount) { super(); this._particles = []; this.root = root; let particle; let distribution = this.distribution(); let layer1Count = distribution[0] * particlesCount * 0.01; let layer2Count = distribution[1] * particlesCount * 0.01; for (let i = 0; i < particlesCount; i++) { if (i < layer1Count) particle = this.createParticle(1); else if (i > layer1Count && i < layer1Count + layer2Count) particle = this.createParticle(2); else particle = this.createParticle(3); this.addChild(particle); this._particles.push(particle); } this.addToJuggler(); } advanceTime() { for (let i = 0; i < this._particles.length; i++) { this._particles[i].update(); } } destroy() { GameObject.destroy(this._particles); super.destroy(); } createParticle(layer) { return new BackgroundEffectParticle(this.root, layer); } distribution() { return [30, 40, 50]; } }; // src/pixi/utils/RectangleUtils.ts var PIXI4 = __toESM(require("pixi.js"), 1); var ScaleMode = /* @__PURE__ */ ((ScaleMode2) => { ScaleMode2["SHOW_ALL"] = "SHOW_ALL"; ScaleMode2["NO_BORDER"] = "NO_BORDER"; return ScaleMode2; })(ScaleMode || {}); var RectangleUtils = class { static fitRectangle(source, target, scaleMode) { const sourceAspect = source.width / source.height; const targetAspect = target.width / target.height; let scale; if (scaleMode === "NO_BORDER" /* NO_BORDER */) { scale = sourceAspect > targetAspect ? target.height / source.height : target.width / source.width; } else { scale = sourceAspect > targetAspect ? target.width / source.width : target.height / source.height; } const width = source.width * scale; const height = source.height * scale; const x = (target.width - width) / 2; const y = (target.height - height) / 2; return new PIXI4.Rectangle(x, y, width, height); } }; // src/pixi/base/GameScreen.ts var GameScreen = class extends GameView { constructor() { super(); this.assetsLoader = null; this._bgImage = null; this._bgParticleEffect = null; this._isAdded = false; } getAreaForHtml() { return this.boundsArea; } get screenID() { return "GameScreen"; } destroy() { super.destroy(); this._bgImage = GameObject.destroy(this._bgImage); this._bgParticleEffect = GameObject.destroy(this._bgParticleEffect); this.assetsLoader = GameObject.destroy(this.assetsLoader); } async onAdded() { this._isAdded = true; } getStateDescription() { return "GameScreen: "; } async loadAssets(onLoad) { if (onLoad) { onLoad(); } } createBg() { this._bgImage = new PIXI5.Sprite(this.getBgTexture()); this._bgImage.interactive = false; const launchImageSize = RectangleUtils.fitRectangle( new PIXI5.Rectangle(0, 0, this._bgImage.width, this._bgImage.height), new PIXI5.Rectangle(0, 0, this.root.fixedStageWidth, this.root.fixedStageHeight), "NO_BORDER" /* NO_BORDER */ ); this._bgImage.width = launchImageSize.width; this._bgImage.height = launchImageSize.height; this.addChild(this._bgImage); } getBgTexture() { return this.assetsLoader?.getTextureByName("bg"); } createBgEffect() { this._bgParticleEffect = new BackgroundEffect(this.root, 80); this.addChild(this._bgParticleEffect); } onActivate() { } onDeActivate() { } onExit() { } }; // src/pixi/utils/ViewUtils.ts var import_pixi = require("pixi.js"); var Align = /* @__PURE__ */ ((Align2) => { Align2["LEFT"] = "left"; Align2["CENTER"] = "center"; Align2["RIGHT"] = "right"; Align2["TOP"] = "top"; Align2["BOTTOM"] = "bottom"; return Align2; })(Align || {}); var ViewUtils = class { // Функция возвращает видимое расстояние между двумя контейнерами static getVisibleGap(containerA, containerB) { const boundsA = containerA.getBounds(); const boundsB = containerB.getBounds(); let horizontalGap = 0; if (boundsA.right < boundsB.left) { horizontalGap = boundsB.left - boundsA.right; } else if (boundsB.right < boundsA.left) { horizontalGap = boundsA.left - boundsB.right; } let verticalGap = 0; if (boundsA.bottom < boundsB.top) { verticalGap = boundsB.top - boundsA.bottom; } else if (boundsB.bottom < boundsA.top) { verticalGap = boundsA.top - boundsB.bottom; } return { horizontal: horizontalGap, vertical: verticalGap }; } // Функция для выравнивания pivot static alignPivot(displayObject, horizontalAlign = "center" /* CENTER */, verticalAlign = "center" /* CENTER */) { if (displayObject) { const bounds = displayObject.getLocalBounds(); let pivotX = 0; let pivotY = 0; if (horizontalAlign === "left" /* LEFT */) { pivotX = bounds.x; } else if (horizontalAlign === "center" /* CENTER */) { pivotX = bounds.x + bounds.width / 2; } else if (horizontalAlign === "right" /* RIGHT */) { pivotX = bounds.x + bounds.width; } if (verticalAlign === "top" /* TOP */) { pivotY = bounds.y; } else if (verticalAlign === "center" /* CENTER */) { pivotY = bounds.y + bounds.height / 2; } else if (verticalAlign === "bottom" /* BOTTOM */) { pivotY = bounds.y + bounds.height; } displayObject.pivot.set(pivotX, pivotY); } else { console.warn("alignPivot: displayObject \u043D\u0435 \u043F\u043E\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 getLocalBounds."); } } static isEqualRects(rect1, rect2) { if (rect1 && rect2) { return rect1.x === rect2.x && rect1.y === rect2.y && rect1.width === rect2.width && rect1.height === rect2.height; } return false; } static putOnTop(view) { if (view && view.parent) { view.parent.setChildIndex(view, view.parent.children.length - 1); } } static fitToWidth(fitDisplayObject, fitWidth, fitIfBigger = true, fitIfSmaller = true) { if (fitDisplayObject && fitWidth > 0) { let fitDisplayObjectWidth = fitDisplayObject.width; if (fitDisplayObjectWidth != fitWidth) { if (!fitIfBigger && fitDisplayObjectWidth > fitWidth) { return; } if (!fitIfSmaller && fitDisplayObjectWidth < fitWidth) { return; } fitDisplayObject.scale.set(fitWidth / fitDisplayObjectWidth * fitDisplayObject.scale.x); } } } static fitToHeight(fitDisplayObject, fitHeight, fitIfBigger = true, fitIfSmaller = true) { if (fitDisplayObject && fitHeight > 0) { let fitDisplayObjectHeight = fitDisplayObject.height; if (fitDisplayObjectHeight != fitHeight) { if (!fitIfBigger && fitDisplayObjectHeight > fitHeight) { return; } if (!fitIfSmaller && fitDisplayObjectHeight < fitHeight) { return; } fitDisplayObject.scale.set(fitHeight / fitDisplayObjectHeight * fitDisplayObject.scale.x); } } } static createRoundedRect(width = 1, height = 1, color, cornerRadius, lineWidth = 0, lineColor) { let bg = new import_pixi.Graphics(); if (lineWidth) { bg.lineStyle(lineWidth, lineColor); } bg.beginFill(color); bg.drawRoundedRect(0, 0, width, height, cornerRadius); bg.endFill(); return bg; } static createRect(width = 1, height = 1, color = "0x000000") { let bg = new import_pixi.Graphics(); bg.beginFill(color); bg.drawRect(0, 0, width, height); bg.endFill(); return bg; } }; // src/pixi/base/GameWaiter.ts var GameWaiter = class extends GameView { constructor(root, container) { super(); this._isShowed = false; this.root = root; this._container = container; } destroy() { super.destroy(); } createSpinner() { return this.root.uiLib.create("spinner"); } show() { if (this._isShowed || this.destroyed) { return; } this._isShowed = true; this._blackImage = ViewUtils.createRect(this.root.fixedStageWidth, this.root.fixedStageHeight, "0x000000"); this._container.addChild(this._blackImage); this._spinner = this.createSpinner(); this._spinner.interactive = false; ViewUtils.alignPivot(this._spinner); this._spinner.x = this.root.fixedStageWidth / 2; this._spinner.y = this.root.fixedStageHeight / 2; this._spinner.alpha = 0.01; this._spinner.scale.set(0.01); this._spinner.playLoop(); this._container.addChild(this._spinner); this._spinnerTween = this.root.juggler.tween(this._spinner, 0.4, { alpha: 1, scale: { x: 1, y: 1 } }).delay(0.2).start(); this._blackTween = this.root.juggler.tween(this._blackImage, 0.4, { alpha: 0.4 }).start(); } hide() { if (this._isShowed) { this._spinnerTween?.destroy(); this._blackTween?.destroy(); GameObject.destroy(this._spinner); GameObject.destroy(this._blackImage); this._isShowed = false; } } }; // src/pixi/base/GameDialog.ts var import_tween2 = require("@tweenjs/tween.js"); // src/managers/SoundManager.ts var import_howler = require("howler"); // src/utils/DateUtils.ts var _DateUtils = class _DateUtils { static get currentUTCDate() { const localDate = /* @__PURE__ */ new Date(); return new Date(localDate.getTime() + localDate.getTimezoneOffset() * 6e4); } static get currentDateFormatted() { const date = /* @__PURE__ */ new Date(); const dtf = new Intl.DateTimeFormat("en-US", { year: "numeric", month: "2-digit", day: "2-digit" }); return dtf.format(date); } static get currentTime() { return _DateUtils.dateTime + (performance.now() - _DateUtils.dateTimestamp); } static msToSeconds(ms) { return ms / 1e3; } static msToMinutes(ms) { return _DateUtils.msToSeconds(ms) / 60; } static msToHours(ms) { return ms / 1e3 / 60 / 60; } static secondsToDays(sec) { return _DateUtils.msToHours(_DateUtils.secondsToMs(sec)) / 24; } static hoursToSeconds(hours) { return _DateUtils.minutesToSeconds(_DateUtils.hoursToMinutes(hours)); } static hoursToMinutes(hours) { return hours * 60; } static daysToMs(days) { return _DateUtils.hoursToMS(24 * days); } static daysToMinutes(days) { return _DateUtils.hoursToMinutes(24 * days); } static minutesToSeconds(min) { return min * 60; } static hoursToMS(hours) { return _DateUtils.minutesToMs(hours * 60); } static minutesToMs(min) { return _DateUtils.secondsToMs(min * 60); } static secondsToMs(sec) { return sec * 1e3; } static getDaysBetween(d1, d2) { const MS_PER_DAY = 864e5; const date1 = new Date(d1.getFullYear(), d1.getMonth(), d1.getDate()); const date2 = new Date(d2.getFullYear(), d2.getMonth(), d2.getDate()); return Math.round((date2.getTime() - date1.getTime()) / MS_PER_DAY); } static getTimeString(index, fps) { let sec = Math.round(index / fps); const min = Math.floor(sec / 60); sec = sec % 60; const mStr = min < 10 ? "0" + min : min.toString(); const sStr = sec < 10 ? "0" + sec : sec.toString(); return mStr + ":" + sStr; } static getTimeStringFromSeconds(seconds) { const min = Math.floor(seconds / 60); seconds = seconds % 60; const mStr = min < 10 ? "0" + min : min.toString(); const sStr = seconds < 10 ? "0" + seconds : seconds.toString(); return mStr + ":" + sStr; } static getNowTimeString() { const today = /* @__PURE__ */ new Date(); const minutes = today.getMinutes(); const hours = today.getHours(); const seconds = today.getSeconds(); return `${hours}:${minutes}:${seconds}`; } static getTimeBetween(d1, d2) { const date1 = new Date(d1.getFullYear(), d1.getMonth(), d1.getDate(), d1.getHours(), d1.getMinutes(), d1.getSeconds()); const date2 = new Date(d2.getFullYear(), d2.getMonth(), d2.getDate(), d2.getHours(), d2.getMinutes(), d2.getSeconds()); return date2.getTime() - date1.getTime(); } static isNextDay(d1, d2) { const d1Year = d1.getFullYear(); const d2Year = d2.getFullYear(); const d1Month = d1.getMonth(); const d2Month = d2.getMonth(); const d1Day = d1.getDate(); const d2Day = d2.getDate(); return d2Year > d1Year || d2Month > d1Month || d2Day > d1Day; } static isTheSameDays(d1, d2) { const d1Year = d1.getFullYear(); const d2Year = d2.getFullYear(); const d1Month = d1.getMonth(); const d2Month = d2.getMonth(); const d1Day = d1.getDate(); const d2Day = d2.getDate(); return d2Year === d1Year && d2Month === d1Month && d2Day === d1Day; } static parseDateStringToDate(utcParseString) { if (!utcParseString) { return null; } const matches = utcParseString.match(/(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})\.(\d{3})Z/); if (!matches) { return null; } const d = /* @__PURE__ */ new Date(); d.setFullYear(Number(matches[1])); d.setMonth(Number(matches[2]) - 1); d.setDate(Number(matches[3])); d.setHours(Number(matches[4])); d.setMinutes(Number(matches[5])); d.setSeconds(Number(matches[6])); d.setMilliseconds(Number(matches[7])); return d; } static parseObjectToDate(o) { if (o && o.__type === "Date" && o.iso) { return _DateUtils.parseDateStringToDate(o.iso); } return null; } static formatTimeMs(ms, dayLng, hourLng, minLng, secLng) { let out = ""; let days = 0; let hours = 0; let minutes = 0; let seconds = _DateUtils.msToSeconds(ms); minutes = Math.floor(seconds / 60); seconds -= minutes * 60; hours = Math.floor(minutes / 60); minutes -= hours * 60; days = Math.floor(hours / 24); hours -= days * 24; if (days > 0) { out = `${days}${dayLng}${hours > 0 ? ` ${hours}${hourLng}` : ""}`; } else if (hours > 0) { out = `${hours}${hourLng}${minutes > 0 ? ` ${minutes}${minLng}` : ""}`; } else { out = `${minutes > 0 ? `${minutes}${minLng} ` : ""}${seconds > 0 ? `${seconds}${secLng}` : ""}`; } return out; } }; _DateUtils.MINUTE = 60 * 1e3; _DateUtils.HOUR = 60 * _DateUtils.MINUTE; _DateUtils.DAY = 24 * _DateUtils.HOUR; _DateUtils.dateTime = (/* @__PURE__ */ new Date()).getTime(); _DateUtils.dateTimestamp = performance.now(); var DateUtils = _DateUtils; // src/managers/AbstractPreferencesManager.ts var import_preferences = require("@capacitor/preferences"); var AbstractPreferencesManager = class { async setBoolValue(key, value) { await import_preferences.Preferences.set({ key, value: JSON.stringify(value || false) }); } async getBoolValue(key) { const { value } = await import_preferences.Preferences.get({ key }); return Boolean(JSON.parse(value || "false")); } async setValue(key, value) { await import_preferences.Preferences.set({ key, value }); } async getValue(key) { const { value } = await import_preferences.Preferences.get({ key }); return value; } async removeValue(key) { await import_preferences.Preferences.remove({ key }); } }; // src/managers/SoundManager.ts var _SoundManager = class _SoundManager extends AbstractPreferencesManager { constructor(app, needPersistence) { super(); this.howlerSoundPool = /* @__PURE__ */ new Map(); this.howlMusic = null; this.musicName = ""; this.soundLastPlayed = /* @__PURE__ */ new Map(); this._soundMuted = false; this._musicMuted = false; this.app = app; this._needPersistence = needPersistence; } async init() { if (this._needPersistence) { this._soundMuted = await this.getBoolValue(_SoundManager.SOUND_MUTED_KEY); this._musicMuted = await this.getBoolValue(_SoundManager.MUSIC_MUTED_KEY); } } async playSound(soundName, timeGapBetweenNextSameSound = 100) { if (this.soundMuted) { return; } const lastPlayedTime = this.soundLastPlayed.get(soundName) || 0; const currentTime = DateUtils.currentTime; if (currentTime - lastPlayedTime >= timeGapBetweenNextSameSound) { if (!this.howlerSoundPool.has(soundName)) { const sound = new import_howler.Howl({ src: [`assets/sounds/${soundName}.mp3`], volume: _SoundManager.SOUND_VOLUME, html5: false }); this.howlerSoundPool.set(soundName, sound); } this.howlerSoundPool.get(soundName)?.play(); this.soundLastPlayed.set(soundName, currentTime); } } async onActivate() { this.playMusic(this.musicName); } async onDeActivate() { this.unloadSounds(); this.unloadMusic(); Howler.stop(); Howler.unload(); } playMusic(musicName) { if (!musicName) { return; } if (this._musicMuted) { this.musicName = musicName; return; } if (this.musicName === musicName && this.howlMusic) { return; } this.unloadMusic(); this.musicName = musicName; try { this.howlMusic = new import_howler.Howl({ src: [`assets/music/${musicName}.mp3`], volume: _SoundManager.MUSIC_VOLUME, loop: true, html5: false }); this.howlMusic.play(); this.howlMusic.loop(); } catch (error) { this.app.error.handleCaughtError(error, "SoundService:playMusic: " + musicName); } } unloadMusic() { try { if (this.howlMusic) { this.howlMusic.stop(); this.howlMusic.unload(); this.howlMusic = null; } } catch (error) { this.app.error.handleCaughtError(error, "SoundService:unloadMusic"); } } unloadSounds() { try { this.howlerSoundPool.forEach((sound) => { sound.stop(); sound.unload(); }); this.howlerSoundPool.clear(); } catch (error) { this.app.error.handleCaughtError(error, "SoundService:unloadSounds"); } } get soundMuted() { return this._soundMuted; } set soundMuted(value) { if (this._soundMuted != value) { this._soundMuted = value; if (this._needPersistence) { void this.setBoolValue(_SoundManager.SOUND_MUTED_KEY, value); } if (this._soundMuted) { this.unloadSounds(); } } } async unmute() { if (this._musicMuted) { this._musicMuted = false; if (this._needPersistence) { void this.setBoolValue(_SoundManager.MUSIC_MUTED_KEY, false); } if (this.musicName) { this.playMusic(this.musicName); } } } async mute() { if (!this._musicMuted) { this._musicMuted = true; if (this._needPersistence) { void this.setBoolValue(_SoundManager.MUSIC_MUTED_KEY, true); } this.unloadMusic(); } } }; _SoundManager.SOUND_VOLUME = 0.8; _SoundManager.MUSIC_VOLUME = 0.6; _SoundManager.Click = "Click"; _SoundManager.DialogOpen = "DialogOpen"; _SoundManager.DialogClose = "DialogClose"; _SoundManager.SOUND_MUTED_KEY = "SOUND_MUTED_KEY"; _SoundManager.MUSIC_MUTED_KEY = "MUSIC_MUTED_KEY"; var SoundManager = _SoundManager; // src/pixi/base/GameDialog.ts var _GameDialog = class _GameDialog extends GameView { constructor() { super(...arguments); this.assetsLoader = null; this._waiter = null; this._dialog = null; this._blackBack = null; this._dialogContent = null; this._isInHideProcess = false; } // internal, used in App, don't assign explicitly get btnClose() { return this._dialogContent?.getButtonByLabel("btn_close"); } get title() { return null; } get dialogContentMoldName() { return ""; } get dialogScale() { let multiplier = 1; if (this.root.app.device.isTablet || this.root.app.device.isDesktop) { multiplier = this.tabletMultiplier; } if (this.root.app.device.isIOS) { return 1.3 * multiplier; } if (this.root.app.device.isAndroid) { return 1.2 * multiplier; } return multiplier; } get tabletMultiplier() { return 0.8; } get backgroundAlpha() { return 0.5; } get createDialogLib() { return this.root.uiLib; } playShowSound() { void this.root.app.sound.playSound(SoundManager.DialogOpen); } async loadAssets(onLoaded) { if (onLoaded) { onLoaded(); } } onAdded() { this.createBlackBack(); this.createBackgroundEffect(); } destroy() { this._dialog = GameObject.destroy(this._dialog); this._blackBack = GameObject.destroy(this._blackBack); this.assetsLoader = GameObject.destroy(this.assetsLoader); this.hideWaiter(); this._dialogContent = GameObject.destroy(this._dialogContent); this._shouldDisposeCallback = null; super.destroy(); } showWaiter() { this.hideWaiter(); this._waiter = this.root.uiLib.create("loading_anim"); ViewUtils.fitToHeight(this._waiter, this.root.adapt(150), true, true); ViewUtils.alignPivot(this._waiter); this._waiter.x = this.root.fixedStageWidth / 2; this._waiter.y = this.root.fixedStageHeight / 2; this._waiter.playLoop(); this.addChildAt(this._waiter, this.children?.length); } hideWaiter() { if (this._waiter) { this._waiter = GameObject.destroy(this._waiter); } } createDialog() { this._dialog = new GameView(); this.addChild(this._dialog); this._dialogContent = this.createDialogLib.create(this.dialogContentMoldName); this._dialog.addChild(this._dialogContent); if (this.btnClose) { this.btnClose.clickCallback = this.onButtonClose.bind(this); } this.createTitle(); } show() { this.playShowSound(); if (this._dialog) { this._dialog.interactive = false; this._dialog.scale = this.dialogScale; ViewUtils.fitToHeight(this._dialog, this.root.fixedStageSafeHeight - this.root.adapt(100), true, false); ViewUtils.alignPivot(this._dialog); this._dialog.x = this.getCenterX(); this._dialog.y = -this._dialog.height; this.root.juggler.tween(this._dialog, _GameDialog.SHOW_TIME, { y: this.getCenterY() }).easing(import_tween2.Easing.Back.Out).onComplete(this.onDialogShowEnd.bind(this)).start(); } } hide() { if (this._isInHideProcess) { return; } this._isInHideProcess = true; this.interactive = false; this.playCloseSound(); this.hideBlackBack(); this.hideDialog(); } onButtonClose() { this.interactive = false; void this.root.app.sound.playSound(SoundManager.Click); this.hide(); } createBlackBack() {