@playus.club/games-sdk 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. package/LICENSE.md +35 -0
  2. package/README.md +129 -0
  3. package/dist/sdk/babylon/canvas.d.ts +30 -0
  4. package/dist/sdk/babylon/canvas.d.ts.map +1 -0
  5. package/dist/sdk/babylon/index.d.ts +3 -0
  6. package/dist/sdk/babylon/index.d.ts.map +1 -0
  7. package/dist/sdk/babylon.js +52 -0
  8. package/dist/sdk/bridge.d.ts +2 -0
  9. package/dist/sdk/bridge.d.ts.map +1 -0
  10. package/dist/sdk/chunks/background-DLy8kjVf.js +47 -0
  11. package/dist/sdk/chunks/debug-BKXPXMKn.js +92 -0
  12. package/dist/sdk/chunks/touch-hint-BZBB3COY.js +148 -0
  13. package/dist/sdk/helpers/timeFormat.d.ts +3 -0
  14. package/dist/sdk/helpers/timeFormat.d.ts.map +1 -0
  15. package/dist/sdk/i18n.d.ts +55 -0
  16. package/dist/sdk/i18n.d.ts.map +1 -0
  17. package/dist/sdk/index.d.ts +19 -0
  18. package/dist/sdk/index.d.ts.map +1 -0
  19. package/dist/sdk/index.js +366 -0
  20. package/dist/sdk/mobile-interaction.d.ts +4 -0
  21. package/dist/sdk/mobile-interaction.d.ts.map +1 -0
  22. package/dist/sdk/native-bridge.d.ts +45 -0
  23. package/dist/sdk/native-bridge.d.ts.map +1 -0
  24. package/dist/sdk/overlay/debug.d.ts +31 -0
  25. package/dist/sdk/overlay/debug.d.ts.map +1 -0
  26. package/dist/sdk/overlay/index.d.ts +5 -0
  27. package/dist/sdk/overlay/index.d.ts.map +1 -0
  28. package/dist/sdk/overlay/touch-hint.d.ts +12 -0
  29. package/dist/sdk/overlay/touch-hint.d.ts.map +1 -0
  30. package/dist/sdk/overlay.js +3 -0
  31. package/dist/sdk/phaser/container.d.ts +25 -0
  32. package/dist/sdk/phaser/container.d.ts.map +1 -0
  33. package/dist/sdk/phaser/index.d.ts +3 -0
  34. package/dist/sdk/phaser/index.d.ts.map +1 -0
  35. package/dist/sdk/phaser.js +72 -0
  36. package/dist/sdk/random.d.ts +5 -0
  37. package/dist/sdk/random.d.ts.map +1 -0
  38. package/dist/sdk/sound.d.ts +36 -0
  39. package/dist/sdk/sound.d.ts.map +1 -0
  40. package/dist/sdk/tap-to-start.d.ts +19 -0
  41. package/dist/sdk/tap-to-start.d.ts.map +1 -0
  42. package/dist/sdk/three/canvas.d.ts +13 -0
  43. package/dist/sdk/three/canvas.d.ts.map +1 -0
  44. package/dist/sdk/three/index.d.ts +3 -0
  45. package/dist/sdk/three/index.d.ts.map +1 -0
  46. package/dist/sdk/three.js +36 -0
  47. package/dist/sdk/timing.d.ts +4 -0
  48. package/dist/sdk/timing.d.ts.map +1 -0
  49. package/dist/sdk/types/background.d.ts +33 -0
  50. package/dist/sdk/types/background.d.ts.map +1 -0
  51. package/dist/sdk/url-params.d.ts +5 -0
  52. package/dist/sdk/url-params.d.ts.map +1 -0
  53. package/package.json +77 -0
  54. package/src/playus/fonts.css +29 -0
  55. package/src/playus/global.css +14 -0
  56. package/src/playus/styles.css +61 -0
@@ -0,0 +1,366 @@
1
+ import { a as e, i as t, n, o as r, r as i, t as a } from "./chunks/background-DLy8kjVf.js";
2
+ import { a as o, i as s, n as c, r as l, t as u } from "./chunks/debug-BKXPXMKn.js";
3
+ import { t as d } from "./chunks/touch-hint-BZBB3COY.js";
4
+ //#region src/playus/sound.ts
5
+ var f = "https://pub-f2838cca4376431f9c696446d4a3e503.r2.dev";
6
+ function p(e) {
7
+ let t = `${e}.mp3`;
8
+ return [
9
+ `native://sounds/${t}`,
10
+ `/__native__/sounds/${t}`,
11
+ `${f}/sounds/${t}`
12
+ ];
13
+ }
14
+ var m = new class {
15
+ audioContext = null;
16
+ buffers = /* @__PURE__ */ new Map();
17
+ loading = /* @__PURE__ */ new Map();
18
+ enabled = !0;
19
+ enabledListeners = [];
20
+ async preload(e) {
21
+ let t = Array.isArray(e) ? e : [e];
22
+ await Promise.all(t.map((e) => this.load(e, p(e))));
23
+ }
24
+ async preloadUrl(e) {
25
+ let t = Array.isArray(e) ? e : [e];
26
+ await Promise.all(t.map((e) => this.load(String(e), [String(e)])));
27
+ }
28
+ play(e, t = {}) {
29
+ this.playFrom(e, p(e), t);
30
+ }
31
+ playUrl(e, t = {}) {
32
+ this.playFrom(String(e), [String(e)], t);
33
+ }
34
+ setEnabled(e) {
35
+ if (e !== this.enabled) {
36
+ this.enabled = e;
37
+ for (let t of this.enabledListeners) t(e);
38
+ }
39
+ }
40
+ isEnabled() {
41
+ return this.enabled;
42
+ }
43
+ onEnabledChange(e) {
44
+ return this.enabledListeners.push(e), e(this.enabled), () => {
45
+ this.enabledListeners = this.enabledListeners.filter((t) => t !== e);
46
+ };
47
+ }
48
+ dispose() {
49
+ this.audioContext &&= (this.audioContext.close().catch(() => {}), null), this.buffers.clear(), this.loading.clear(), this.enabledListeners = [];
50
+ }
51
+ playFrom(e, t, n) {
52
+ this.enabled && this.getContext() && this.load(e, t).then((t) => {
53
+ if (!(!t || !this.audioContext)) try {
54
+ let e = this.audioContext.createBufferSource();
55
+ if (e.buffer = t, n.volume !== void 0 && n.volume !== 1) {
56
+ let t = this.audioContext.createGain();
57
+ t.gain.value = Math.max(0, Math.min(1, n.volume)), e.connect(t), t.connect(this.audioContext.destination);
58
+ } else e.connect(this.audioContext.destination);
59
+ e.start(0);
60
+ } catch (t) {
61
+ console.warn(`SoundManager: Failed to play ${e}:`, t);
62
+ }
63
+ });
64
+ }
65
+ getContext() {
66
+ if (!this.audioContext) try {
67
+ let e = window.AudioContext || window.webkitAudioContext;
68
+ this.audioContext = new e();
69
+ } catch {
70
+ return console.warn("SoundManager: Web Audio API not supported"), null;
71
+ }
72
+ return this.audioContext.state === "suspended" && this.audioContext.resume().catch(() => {}), this.audioContext;
73
+ }
74
+ async load(e, t) {
75
+ if (this.buffers.has(e)) return this.buffers.get(e);
76
+ if (this.loading.has(e)) return this.loading.get(e);
77
+ let n = this.getContext();
78
+ if (!n) return null;
79
+ let r = this.fetchAndDecode(n, e, t);
80
+ return this.loading.set(e, r), r.finally(() => this.loading.delete(e));
81
+ }
82
+ async fetchAndDecode(e, t, n) {
83
+ for (let r of n) try {
84
+ let n = await fetch(r);
85
+ if (!n.ok) continue;
86
+ let i = await n.arrayBuffer(), a = await e.decodeAudioData(i);
87
+ return this.buffers.set(t, a), a;
88
+ } catch {
89
+ continue;
90
+ }
91
+ return console.warn(`SoundManager: Could not load ${t}`), null;
92
+ }
93
+ }(), h = "gameEvent", g = 3;
94
+ function _(e) {
95
+ return JSON.stringify(e);
96
+ }
97
+ function v() {
98
+ let e = window.crypto;
99
+ if (typeof e?.randomUUID == "function") return e.randomUUID();
100
+ if (typeof e?.getRandomValues == "function") {
101
+ let t = e.getRandomValues(/* @__PURE__ */ new Uint32Array(2)), n = Array.from(t, (e) => e.toString(36)).join("");
102
+ return `${Date.now().toString(36)}-${n}`;
103
+ }
104
+ return `${Date.now().toString(36)}-${Math.random().toString(36).slice(2)}`;
105
+ }
106
+ var y = {
107
+ READY: "ready",
108
+ GAME_STARTED: "gameStarted",
109
+ GAME_FINISHED: "gameFinished",
110
+ SCORE_UPDATE: "scoreUpdate",
111
+ ERROR: "error",
112
+ HAPTIC: "haptic",
113
+ COLOR_CONFIG: "colorConfig",
114
+ MESSAGE: "message",
115
+ DEBUG_MESSAGE: "debugMessage",
116
+ HOST_READY_ACK: "hostReadyAck"
117
+ };
118
+ function b() {
119
+ return {
120
+ width: window.innerWidth,
121
+ height: window.innerHeight,
122
+ devicePixelRatio: window.devicePixelRatio || 1
123
+ };
124
+ }
125
+ var x = class {
126
+ assetPrimaryColor;
127
+ assetDarkColor;
128
+ backgroundGradientTop;
129
+ backgroundGradientBottom;
130
+ constructor(e = {}) {
131
+ Object.assign(this, e);
132
+ }
133
+ }, S = 200, C = 10 ** 7, w = (2 ** 53 - 1) / C;
134
+ function T(e) {
135
+ if (!Number.isFinite(e) || Math.abs(e) >= w) return e;
136
+ let t = Math.sign(e) * Math.round(Math.abs(e) * C) / C;
137
+ return Object.is(t, -0) ? 0 : t;
138
+ }
139
+ var E = class {
140
+ gameId;
141
+ handshakeId = v();
142
+ pendingScore = null;
143
+ scoreTimer = null;
144
+ configure(e = {}) {
145
+ this.gameId = e.gameId ?? this.gameId;
146
+ }
147
+ postToNative(e) {
148
+ let t = window.webkit?.messageHandlers?.[h], n = window.gameEvent, r = "native_handler_missing";
149
+ try {
150
+ if (t && typeof t.postMessage == "function") return t.postMessage(e), { success: !0 };
151
+ if (n && typeof n.handleMessage == "function") return n.handleMessage(JSON.stringify(e)), { success: !0 };
152
+ } catch (e) {
153
+ console.error("NativeBridge post failed:", e), r = "post_failed";
154
+ }
155
+ console.log("NativeBridge (simulated) →", e);
156
+ try {
157
+ window.parent && window.parent !== window && window.parent.postMessage({
158
+ source: "game-native-bridge",
159
+ ...e
160
+ }, "*");
161
+ } catch {}
162
+ return {
163
+ success: !1,
164
+ error: r
165
+ };
166
+ }
167
+ postDetailed(e, t) {
168
+ try {
169
+ let n = {
170
+ type: e,
171
+ gameId: this.gameId,
172
+ timestamp: Date.now(),
173
+ ...t
174
+ };
175
+ return this.postToNative(n);
176
+ } catch (t) {
177
+ return console.error(`NativeBridge post failed for "${e}"`, t), {
178
+ success: !1,
179
+ error: "post_failed"
180
+ };
181
+ }
182
+ }
183
+ post(e, t) {
184
+ return this.postDetailed(e, t).success;
185
+ }
186
+ installGameAPI() {
187
+ let e = this;
188
+ window.gameAPI = {
189
+ hostReady(t) {
190
+ if (t?.handshakeId !== e.handshakeId) return console.warn("NativeBridge hostReady ignored:", t), _({
191
+ success: !1,
192
+ error: "handshake_mismatch"
193
+ });
194
+ console.info("NativeBridge hostReady:", t);
195
+ let n = e.postDetailed(y.HOST_READY_ACK, {
196
+ handshakeId: e.handshakeId,
197
+ bridgeVersion: g
198
+ });
199
+ return n.success || console.warn("NativeBridge hostReadyAck post failed:", n.error), _({ success: !0 });
200
+ },
201
+ setMuted(e) {
202
+ m.setEnabled(!e);
203
+ }
204
+ };
205
+ }
206
+ flushScore() {
207
+ this.scoreTimer &&= (clearTimeout(this.scoreTimer), null), this.pendingScore !== null && (this.post(y.SCORE_UPDATE, { score: T(this.pendingScore) }), this.pendingScore = null);
208
+ }
209
+ attach() {
210
+ this.installGameAPI();
211
+ }
212
+ game = {
213
+ ready: (e) => {
214
+ e?.gameId && (this.gameId = e.gameId), this.post(y.READY, {
215
+ userAgent: navigator.userAgent,
216
+ viewport: b(),
217
+ ...e,
218
+ bridgeVersion: g,
219
+ handshakeId: this.handshakeId
220
+ });
221
+ },
222
+ started: () => {
223
+ this.post(y.GAME_STARTED);
224
+ },
225
+ finished: (e) => {
226
+ this.flushScore(), this.post(y.GAME_FINISHED, { score: T(e) });
227
+ },
228
+ score: (e) => {
229
+ this.pendingScore = e, this.scoreTimer ||= setTimeout(() => this.flushScore(), S);
230
+ },
231
+ error: (e) => {
232
+ let t = typeof e == "string" ? {
233
+ code: "UNKNOWN",
234
+ message: e
235
+ } : {
236
+ code: e.code,
237
+ message: e.message
238
+ };
239
+ this.post(y.ERROR, t);
240
+ },
241
+ setColorConfig: (e) => {
242
+ this.post(y.COLOR_CONFIG, { colorConfig: e });
243
+ },
244
+ message: (e, t) => {
245
+ this.post(y.MESSAGE, {
246
+ text: e,
247
+ ...t !== void 0 && { duration: t }
248
+ });
249
+ },
250
+ debugMessage: (e) => {
251
+ this.post(y.DEBUG_MESSAGE, { text: e });
252
+ }
253
+ };
254
+ device = { haptic: (e) => {
255
+ this.post(y.HAPTIC, { pattern: e });
256
+ } };
257
+ }, D = new E();
258
+ e(), D.attach();
259
+ //#endregion
260
+ //#region src/playus/random.ts
261
+ function O(e) {
262
+ let t = 5381;
263
+ for (let n = 0; n < e.length; n += 1) t = (t << 5) + t + e.charCodeAt(n) | 0;
264
+ return t >>> 0;
265
+ }
266
+ function k(e) {
267
+ let t = e | 0;
268
+ return () => {
269
+ t = t + 1831565813 | 0;
270
+ let e = Math.imul(t ^ t >>> 15, 1 | t);
271
+ return e = e + Math.imul(e ^ e >>> 7, 61 | e) ^ e, ((e ^ e >>> 14) >>> 0) / 4294967296;
272
+ };
273
+ }
274
+ function A(e) {
275
+ return e === void 0 || e === "" ? () => Math.random() : k(O(e));
276
+ }
277
+ function j(e, t, n) {
278
+ return t + Math.floor(e() * (n - t + 1));
279
+ }
280
+ function M(e, t, n) {
281
+ return t + e() * (n - t);
282
+ }
283
+ function N(e, t) {
284
+ for (let n = t.length - 1; n > 0; --n) {
285
+ let r = Math.floor(e() * (n + 1)), i = t[n];
286
+ t[n] = t[r], t[r] = i;
287
+ }
288
+ return t;
289
+ }
290
+ function P(e) {
291
+ return !Number.isFinite(e) || e <= 0 ? 0 : Math.min(e, 150);
292
+ }
293
+ function F(e) {
294
+ return !Number.isFinite(e) || e <= 0 ? 0 : Math.min(e, 150 / 1e3);
295
+ }
296
+ //#endregion
297
+ //#region src/playus/i18n.ts
298
+ var I = [
299
+ "en",
300
+ "de",
301
+ "fr",
302
+ "es",
303
+ "it"
304
+ ];
305
+ function L() {
306
+ let e = o("lang");
307
+ return e && I.includes(e) ? e : "en";
308
+ }
309
+ function R(e) {
310
+ let t = L();
311
+ return ((n, r) => {
312
+ let i = e[n], a = i?.[t] || i?.en || String(n);
313
+ return r && Object.entries(r).forEach(([e, t]) => {
314
+ a = a.replace(RegExp(`\\{${e}\\}`, "g"), String(t));
315
+ }), a;
316
+ });
317
+ }
318
+ //#endregion
319
+ //#region src/playus/tap-to-start.ts
320
+ function z(e) {
321
+ let t = e.parent ?? document.body, n = e.mode ?? "dismiss-only", r = document.createElement("div"), i = document.createElement("div"), a = null;
322
+ r.className = "playus-tap-start", r.style.pointerEvents = n === "dismiss-only" ? "auto" : "none", i.className = "playus-tap-start__label", i.textContent = B(e.text ?? {
323
+ en: "Tap to start",
324
+ de: "Tippen zum Starten",
325
+ fr: "Touchez pour commencer",
326
+ es: "Toca para empezar",
327
+ it: "Tocca per iniziare"
328
+ }), i.style.pointerEvents = n === "dismiss-only" ? "auto" : "none", r.appendChild(i), t.appendChild(r), e.touchHint !== !1 && (a = d(e.touchHint ?? "tap", r, "#ffffff", {
329
+ top: "64%",
330
+ width: "24%"
331
+ }));
332
+ function o(t) {
333
+ c(), e.onStart(t);
334
+ }
335
+ function s() {
336
+ r.hidden = !1, a?.show();
337
+ }
338
+ function c() {
339
+ r.hidden = !0, a?.hide(), t.removeEventListener("pointerdown", o, !0), r.removeEventListener("pointerdown", o);
340
+ }
341
+ function l() {
342
+ c(), r.remove();
343
+ }
344
+ return n === "dismiss-only" ? r.addEventListener("pointerdown", o) : t.addEventListener("pointerdown", o, !0), {
345
+ show: s,
346
+ hide: c,
347
+ destroy: l
348
+ };
349
+ }
350
+ function B(e) {
351
+ return typeof e == "string" ? e : e[L()] ?? e.en ?? Object.values(e)[0] ?? "";
352
+ }
353
+ //#endregion
354
+ //#region src/playus/helpers/timeFormat.ts
355
+ function V(e) {
356
+ let t = e;
357
+ (!Number.isFinite(t) || t < 0) && (t = 0);
358
+ let n = Math.floor(t), r = Math.floor(n / 60), i = n % 60;
359
+ return `${String(r).padStart(2, "0")}:${String(i).padStart(2, "0")}`;
360
+ }
361
+ function H(e) {
362
+ let t = e;
363
+ return (!Number.isFinite(t) || t < 0) && (t = 0), V(Math.floor(t / 1e3));
364
+ }
365
+ //#endregion
366
+ export { x as ColorConfig, a as DEFAULT_BACKGROUND, E as NativeBridge, t as applyMobileSurfaceStyle, P as clampGameplayDeltaMs, F as clampGameplayDeltaSeconds, u as createDebugOverlay, A as createSeededRandom, z as createTapToStartOverlay, d as createTouchHint, R as createTranslator, H as formatMillisecondsAsClock, V as formatSecondsAsClock, n as getBackgroundColor, L as getCurrentLanguage, s as getGameSeed, c as getRendererInfo, o as getUrlParam, e as installMobileSelectionPolicy, r as installTouchDefaultGuard, l as isDebugMode, i as isTransparent, D as nativeBridge, T as roundScoreForBridge, j as seededBetween, M as seededFloatBetween, N as seededShuffle, m as sound };
@@ -0,0 +1,4 @@
1
+ export declare function installMobileSelectionPolicy(): void;
2
+ export declare function applyMobileSurfaceStyle<T extends HTMLElement>(element: T): T;
3
+ export declare function installTouchDefaultGuard<T extends HTMLElement>(element: T): T;
4
+ //# sourceMappingURL=mobile-interaction.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mobile-interaction.d.ts","sourceRoot":"","sources":["../../src/playus/mobile-interaction.ts"],"names":[],"mappings":"AAyBA,wBAAgB,4BAA4B,SAiB3C;AAED,wBAAgB,uBAAuB,CAAC,CAAC,SAAS,WAAW,EAAE,OAAO,EAAE,CAAC,GAAG,CAAC,CAM5E;AAED,wBAAgB,wBAAwB,CAAC,CAAC,SAAS,WAAW,EAAE,OAAO,EAAE,CAAC,GAAG,CAAC,CAQ7E"}
@@ -0,0 +1,45 @@
1
+ export declare class ColorConfig {
2
+ assetPrimaryColor?: string;
3
+ assetDarkColor?: string;
4
+ backgroundGradientTop?: string;
5
+ backgroundGradientBottom?: string;
6
+ constructor(init?: Partial<ColorConfig>);
7
+ }
8
+ export declare function roundScoreForBridge(score: number): number;
9
+ export declare class NativeBridge {
10
+ private gameId?;
11
+ private readonly handshakeId;
12
+ private pendingScore;
13
+ private scoreTimer;
14
+ configure(options?: {
15
+ gameId?: string;
16
+ }): void;
17
+ private postToNative;
18
+ private postDetailed;
19
+ private post;
20
+ private installGameAPI;
21
+ private flushScore;
22
+ attach(): void;
23
+ readonly game: {
24
+ ready: (details?: {
25
+ gameId?: string;
26
+ version?: string;
27
+ timestamp?: number;
28
+ }) => void;
29
+ started: () => void;
30
+ finished: (score: number) => void;
31
+ score: (score: number) => void;
32
+ error: (error: {
33
+ code: string;
34
+ message: string;
35
+ } | string) => void;
36
+ setColorConfig: (config: ColorConfig) => void;
37
+ message: (text: string, duration?: number) => void;
38
+ debugMessage: (text: string) => void;
39
+ };
40
+ readonly device: {
41
+ haptic: (pattern: "tap" | "release" | "soft" | "startLoading" | "success" | "failed" | "confetti") => void;
42
+ };
43
+ }
44
+ export declare const nativeBridge: NativeBridge;
45
+ //# sourceMappingURL=native-bridge.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"native-bridge.d.ts","sourceRoot":"","sources":["../../src/playus/native-bridge.ts"],"names":[],"mappings":"AAsEA,qBAAa,WAAW;IACtB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,cAAc,CAAC,EAAE,MAAM,CAAC;IAExB,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,wBAAwB,CAAC,EAAE,MAAM,CAAC;gBACtB,IAAI,GAAE,OAAO,CAAC,WAAW,CAAM;CAG5C;AAOD,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAQzD;AAED,qBAAa,YAAY;IACvB,OAAO,CAAC,MAAM,CAAC,CAAS;IACxB,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAuB;IACnD,OAAO,CAAC,YAAY,CAAuB;IAC3C,OAAO,CAAC,UAAU,CAA8C;IAEhE,SAAS,CAAC,OAAO,GAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAA;KAAO;IAI3C,OAAO,CAAC,YAAY;IAuCpB,OAAO,CAAC,YAAY;IAiBpB,OAAO,CAAC,IAAI;IAIZ,OAAO,CAAC,cAAc;IAmCtB,OAAO,CAAC,UAAU;IAWlB,MAAM;IAMN,QAAQ,CAAC,IAAI;0BACO;YAAE,MAAM,CAAC,EAAE,MAAM,CAAC;YAAC,OAAO,CAAC,EAAE,MAAM,CAAC;YAAC,SAAS,CAAC,EAAE,MAAM,CAAA;SAAE;;0BAazD,MAAM;uBAIT,MAAM;uBAMN;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,OAAO,EAAE,MAAM,CAAA;SAAE,GAAG,MAAM;iCAOhC,WAAW;wBAGpB,MAAM,aAAa,MAAM;6BAGpB,MAAM;MAG3B;IAGF,QAAQ,CAAC,MAAM;0BAGF,KAAK,GAAG,SAAS,GAAG,MAAM,GAAG,cAAc,GAAG,SAAS,GAAG,QAAQ,GAAG,UAAU;MAI1F;CAEH;AAED,eAAO,MAAM,YAAY,cAAqB,CAAC"}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Shared debug overlay utility for performance monitoring
3
+ * Shows FPS and can be extended for other debug info (memory, draw calls, etc.)
4
+ * Only visible when URL contains ?d=1
5
+ */
6
+ export type DebugOverlay = {
7
+ setFps: (fps: number) => void;
8
+ setRenderer: (renderer: string) => void;
9
+ show: () => void;
10
+ hide: () => void;
11
+ destroy: () => void;
12
+ };
13
+ /**
14
+ * Detect WebGL support and GPU renderer info
15
+ */
16
+ export declare function getRendererInfo(): {
17
+ supported: boolean;
18
+ renderer: string;
19
+ vendor: string;
20
+ };
21
+ /**
22
+ * Check if debug mode is enabled via URL parameter
23
+ * @returns true if ?d=1 is present in URL
24
+ */
25
+ export declare function isDebugMode(): boolean;
26
+ /**
27
+ * Create a debug overlay element with FPS counter
28
+ * Position: top-center, small badge with dark background
29
+ */
30
+ export declare function createDebugOverlay(parentElement: HTMLElement): DebugOverlay;
31
+ //# sourceMappingURL=debug.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"debug.d.ts","sourceRoot":"","sources":["../../../src/playus/overlay/debug.ts"],"names":[],"mappings":"AAEA;;;;GAIG;AAEH,MAAM,MAAM,YAAY,GAAG;IACzB,MAAM,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IAC9B,WAAW,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;IACxC,IAAI,EAAE,MAAM,IAAI,CAAC;IACjB,IAAI,EAAE,MAAM,IAAI,CAAC;IACjB,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB,CAAC;AAEF;;GAEG;AACH,wBAAgB,eAAe,IAAI;IAAE,SAAS,EAAE,OAAO,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAmB1F;AAED;;;GAGG;AACH,wBAAgB,WAAW,IAAI,OAAO,CAErC;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,aAAa,EAAE,WAAW,GAAG,YAAY,CA0D3E"}
@@ -0,0 +1,5 @@
1
+ export { createDebugOverlay, getRendererInfo, isDebugMode } from './debug';
2
+ export { createTouchHint } from './touch-hint';
3
+ export type { DebugOverlay } from './debug';
4
+ export type { TouchHint, TouchHintType } from './touch-hint';
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/playus/overlay/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAC3E,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAC/C,YAAY,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAC5C,YAAY,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC"}
@@ -0,0 +1,12 @@
1
+ /** Supported touch-hint animation types */
2
+ export type TouchHintType = 'tap' | 'drag-horizontal' | 'tap-sides' | 'tap-timed' | 'drag-free' | 'swipe-4dir' | 'swipe-horizontal' | 'swipe-down' | 'tap-rapid';
3
+ export type TouchHint = {
4
+ show: () => void;
5
+ hide: () => void;
6
+ destroy: () => void;
7
+ };
8
+ export declare function createTouchHint(type: TouchHintType, parent: HTMLElement, color?: string, options?: {
9
+ top?: string;
10
+ width?: string;
11
+ }): TouchHint;
12
+ //# sourceMappingURL=touch-hint.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"touch-hint.d.ts","sourceRoot":"","sources":["../../../src/playus/overlay/touch-hint.ts"],"names":[],"mappings":"AAAA,2CAA2C;AAC3C,MAAM,MAAM,aAAa,GACrB,KAAK,GACL,iBAAiB,GACjB,WAAW,GACX,WAAW,GACX,WAAW,GACX,YAAY,GACZ,kBAAkB,GAClB,YAAY,GACZ,WAAW,CAAC;AAEhB,MAAM,MAAM,SAAS,GAAG;IACtB,IAAI,EAAE,MAAM,IAAI,CAAC;IACjB,IAAI,EAAE,MAAM,IAAI,CAAC;IACjB,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB,CAAC;AA2OF,wBAAgB,eAAe,CAAC,IAAI,EAAE,aAAa,EAAE,MAAM,EAAE,WAAW,EAAE,KAAK,SAAY,EAAE,OAAO,CAAC,EAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,CAwBlJ"}
@@ -0,0 +1,3 @@
1
+ import { n as e, r as t, t as n } from "./chunks/debug-BKXPXMKn.js";
2
+ import { t as r } from "./chunks/touch-hint-BZBB3COY.js";
3
+ export { n as createDebugOverlay, r as createTouchHint, e as getRendererInfo, t as isDebugMode };
@@ -0,0 +1,25 @@
1
+ import Phaser from 'phaser';
2
+ import { type BackgroundConfig } from '../types/background';
3
+ export declare const BASE_VIEWPORT_WIDTH = 1200;
4
+ export declare const BASE_VIEWPORT_HEIGHT = 1920;
5
+ export type PhaserParentOptions = {
6
+ aspectRatio?: number;
7
+ background?: BackgroundConfig;
8
+ };
9
+ /**
10
+ * Get Phaser game config for background settings.
11
+ * Merge this with BASE_PHASER_CONFIG when creating Phaser.Game.
12
+ *
13
+ * @example
14
+ * const game = new Phaser.Game({
15
+ * ...BASE_PHASER_CONFIG,
16
+ * ...getPhaserBackgroundConfig({ transparent: false, color: '#1a1a2e' }),
17
+ * scene: [MainScene],
18
+ * scale: { ...BASE_PHASER_CONFIG.scale!, parent },
19
+ * });
20
+ */
21
+ export declare function getPhaserBackgroundConfig(background?: BackgroundConfig): Partial<Phaser.Types.Core.GameConfig>;
22
+ export declare const BASE_PHASER_CONFIG: Phaser.Types.Core.GameConfig;
23
+ export declare function createPhaserParent(options?: PhaserParentOptions): HTMLElement;
24
+ export declare function isOutOfBounds(entity: Phaser.GameObjects.GameObject & Phaser.GameObjects.Components.GetBounds): boolean;
25
+ //# sourceMappingURL=container.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"container.d.ts","sourceRoot":"","sources":["../../../src/playus/phaser/container.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,QAAQ,CAAC;AAG5B,OAAO,EAAE,KAAK,gBAAgB,EAAqC,MAAM,qBAAqB,CAAC;AAE/F,eAAO,MAAM,mBAAmB,OAAO,CAAC;AACxC,eAAO,MAAM,oBAAoB,OAAO,CAAC;AAEzC,MAAM,MAAM,mBAAmB,GAAG;IAChC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,gBAAgB,CAAC;CAC/B,CAAC;AAEF;;;;;;;;;;;GAWG;AACH,wBAAgB,yBAAyB,CAAC,UAAU,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,CAW9G;AAED,eAAO,MAAM,kBAAkB,EAAE,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,UAqBlD,CAAC;AAEF,wBAAgB,kBAAkB,CAAC,OAAO,CAAC,EAAE,mBAAmB,GAAG,WAAW,CA8C7E;AAED,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,CAAC,WAAW,CAAC,UAAU,GAAG,MAAM,CAAC,WAAW,CAAC,UAAU,CAAC,SAAS,WAI5G"}
@@ -0,0 +1,3 @@
1
+ export { BASE_PHASER_CONFIG, BASE_VIEWPORT_HEIGHT, BASE_VIEWPORT_WIDTH, createPhaserParent, getPhaserBackgroundConfig, isOutOfBounds, } from './container';
2
+ export type { PhaserParentOptions } from './container';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/playus/phaser/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,kBAAkB,EAClB,oBAAoB,EACpB,mBAAmB,EACnB,kBAAkB,EAClB,yBAAyB,EACzB,aAAa,GACd,MAAM,aAAa,CAAC;AACrB,YAAY,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC"}
@@ -0,0 +1,72 @@
1
+ import { i as e, n as t, r as n } from "./chunks/background-DLy8kjVf.js";
2
+ import { r } from "./chunks/debug-BKXPXMKn.js";
3
+ import i from "phaser";
4
+ //#region src/playus/phaser/container.ts
5
+ var a = 1200, o = 1920;
6
+ function s(e) {
7
+ return n(e) ? { transparent: !0 } : {
8
+ transparent: !1,
9
+ backgroundColor: t(e)
10
+ };
11
+ }
12
+ var c = {
13
+ type: i.AUTO,
14
+ transparent: !0,
15
+ fps: {
16
+ target: 60,
17
+ min: 30,
18
+ smoothStep: !1,
19
+ deltaHistory: 1
20
+ },
21
+ scale: {
22
+ mode: i.Scale.FIT,
23
+ autoCenter: i.Scale.CENTER_BOTH,
24
+ parent: void 0,
25
+ width: a,
26
+ height: o
27
+ },
28
+ banner: !1,
29
+ render: {
30
+ antialias: !0,
31
+ antialiasGL: !0,
32
+ pixelArt: !1,
33
+ roundPixels: !0,
34
+ clearBeforeRender: !0,
35
+ powerPreference: "high-performance",
36
+ desynchronized: !0
37
+ }
38
+ };
39
+ function l(n) {
40
+ let i = n?.aspectRatio ?? 1.6, a = t(n?.background), o = document.createElement("div");
41
+ o.id = "game-root", Object.assign(o.style, {
42
+ position: "fixed",
43
+ inset: "0",
44
+ display: "grid",
45
+ placeItems: "center",
46
+ background: a ?? "transparent"
47
+ }), e(o), document.body.appendChild(o);
48
+ let s = document.createElement("div");
49
+ if (s.id = "phaser-parent", Object.assign(s.style, {
50
+ width: `min(100vw, calc(100vh / ${i}))`,
51
+ aspectRatio: `${1 / i}`,
52
+ background: a ?? "transparent",
53
+ position: "relative",
54
+ overflow: "hidden"
55
+ }), e(s), o.appendChild(s), r()) {
56
+ let e = document.createElement("div");
57
+ e.id = "debug-background", Object.assign(e.style, {
58
+ position: "absolute",
59
+ inset: "0",
60
+ background: "rgba(0, 0, 0, 0.1)",
61
+ pointerEvents: "none",
62
+ zIndex: "-1"
63
+ }), s.appendChild(e);
64
+ }
65
+ return s;
66
+ }
67
+ function u(e) {
68
+ let { width: t, height: n } = e.scene.scale, r = e.getBounds();
69
+ return r.right < 0 || r.bottom < 0 || r.left > t || r.top > n;
70
+ }
71
+ //#endregion
72
+ export { c as BASE_PHASER_CONFIG, o as BASE_VIEWPORT_HEIGHT, a as BASE_VIEWPORT_WIDTH, l as createPhaserParent, s as getPhaserBackgroundConfig, u as isOutOfBounds };
@@ -0,0 +1,5 @@
1
+ export declare function createSeededRandom(seed?: string): () => number;
2
+ export declare function seededBetween(random: () => number, min: number, max: number): number;
3
+ export declare function seededFloatBetween(random: () => number, min: number, max: number): number;
4
+ export declare function seededShuffle<T>(random: () => number, values: T[]): T[];
5
+ //# sourceMappingURL=random.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"random.d.ts","sourceRoot":"","sources":["../../src/playus/random.ts"],"names":[],"mappings":"AAkBA,wBAAgB,kBAAkB,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,MAAM,CAG9D;AAED,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAEpF;AAED,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAEzF;AAED,wBAAgB,aAAa,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,MAAM,EAAE,MAAM,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE,CAQvE"}
@@ -0,0 +1,36 @@
1
+ export type SoundId = 'ball-hole' | 'game-info' | 'game-warning' | 'hit-analog' | 'jump' | 'knife-throw' | 'level-complete' | 'level-up' | 'negative-input' | 'piano1' | 'piano2' | 'piano3' | 'piano4' | 'pop-bubble' | 'pop-happy' | 'pop-sharp' | 'pop-multi-up' | 'pop-multi-down' | 'positive-input' | 'ring-down' | 'ring-up' | 'wall-hit-2' | 'wall-hit';
2
+ export type SoundPlayOptions = {
3
+ volume?: number;
4
+ };
5
+ declare class SoundManager {
6
+ private audioContext;
7
+ private buffers;
8
+ private loading;
9
+ private enabled;
10
+ private enabledListeners;
11
+ preload(ids: SoundId | SoundId[]): Promise<void>;
12
+ /** Preload custom sound files bundled with the game. */
13
+ preloadUrl(sources: string | URL | Array<string | URL>): Promise<void>;
14
+ play(id: SoundId, options?: SoundPlayOptions): void;
15
+ /**
16
+ * Play a custom sound file bundled with the game. Goes through the same
17
+ * manager as shared sounds, so the host mute state applies automatically.
18
+ */
19
+ playUrl(source: string | URL, options?: SoundPlayOptions): void;
20
+ setEnabled(enabled: boolean): void;
21
+ isEnabled(): boolean;
22
+ /**
23
+ * Subscribe to the host mute state, e.g. to mute your own audio engine.
24
+ * Calls the listener immediately with the current state and again on every
25
+ * change. Returns an unsubscribe function.
26
+ */
27
+ onEnabledChange(listener: (enabled: boolean) => void): () => void;
28
+ dispose(): void;
29
+ private playFrom;
30
+ private getContext;
31
+ private load;
32
+ private fetchAndDecode;
33
+ }
34
+ export declare const sound: SoundManager;
35
+ export {};
36
+ //# sourceMappingURL=sound.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sound.d.ts","sourceRoot":"","sources":["../../src/playus/sound.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,OAAO,GACf,WAAW,GACX,WAAW,GACX,cAAc,GACd,YAAY,GACZ,MAAM,GACN,aAAa,GACb,gBAAgB,GAChB,UAAU,GACV,gBAAgB,GAChB,QAAQ,GACR,QAAQ,GACR,QAAQ,GACR,QAAQ,GACR,YAAY,GACZ,WAAW,GACX,WAAW,GACX,cAAc,GACd,gBAAgB,GAChB,gBAAgB,GAChB,WAAW,GACX,SAAS,GACT,YAAY,GACZ,UAAU,CAAC;AAEf,MAAM,MAAM,gBAAgB,GAAG;IAC7B,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAaF,cAAM,YAAY;IAChB,OAAO,CAAC,YAAY,CAA6B;IACjD,OAAO,CAAC,OAAO,CAAuC;IACtD,OAAO,CAAC,OAAO,CAAuD;IACtE,OAAO,CAAC,OAAO,CAAQ;IACvB,OAAO,CAAC,gBAAgB,CAAyC;IAE3D,OAAO,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAKtD,wDAAwD;IAClD,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,GAAG,GAAG,KAAK,CAAC,MAAM,GAAG,GAAG,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAK5E,IAAI,CAAC,EAAE,EAAE,OAAO,EAAE,OAAO,GAAE,gBAAqB,GAAG,IAAI;IAIvD;;;OAGG;IACH,OAAO,CAAC,MAAM,EAAE,MAAM,GAAG,GAAG,EAAE,OAAO,GAAE,gBAAqB,GAAG,IAAI;IAInE,UAAU,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;IAOlC,SAAS,IAAI,OAAO;IAIpB;;;;OAIG;IACH,eAAe,CAAC,QAAQ,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,GAAG,MAAM,IAAI;IASjE,OAAO,IAAI,IAAI;IAWf,OAAO,CAAC,QAAQ;IA6BhB,OAAO,CAAC,UAAU;YAkBJ,IAAI;YAaJ,cAAc;CAkB7B;AAED,eAAO,MAAM,KAAK,cAAqB,CAAC"}