@energy8platform/game-engine 0.17.0 → 0.19.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 (80) hide show
  1. package/dist/audio.cjs.js +15 -5
  2. package/dist/audio.cjs.js.map +1 -1
  3. package/dist/audio.d.ts +5 -0
  4. package/dist/audio.esm.js +15 -5
  5. package/dist/audio.esm.js.map +1 -1
  6. package/dist/core.cjs.js +108 -19
  7. package/dist/core.cjs.js.map +1 -1
  8. package/dist/core.d.ts +46 -3
  9. package/dist/core.esm.js +109 -21
  10. package/dist/core.esm.js.map +1 -1
  11. package/dist/game-spec.cjs.js +13 -0
  12. package/dist/game-spec.cjs.js.map +1 -0
  13. package/dist/game-spec.d.ts +1 -0
  14. package/dist/game-spec.esm.js +2 -0
  15. package/dist/game-spec.esm.js.map +1 -0
  16. package/dist/host.cjs.js +3612 -0
  17. package/dist/host.cjs.js.map +1 -0
  18. package/dist/host.d.ts +1000 -0
  19. package/dist/host.esm.js +3603 -0
  20. package/dist/host.esm.js.map +1 -0
  21. package/dist/index.cjs.js +59 -19
  22. package/dist/index.cjs.js.map +1 -1
  23. package/dist/index.d.ts +19 -2
  24. package/dist/index.esm.js +59 -19
  25. package/dist/index.esm.js.map +1 -1
  26. package/dist/react.cjs.js.map +1 -1
  27. package/dist/react.d.ts +19 -2
  28. package/dist/react.esm.js.map +1 -1
  29. package/dist/shell.cjs.js +19 -0
  30. package/dist/shell.cjs.js.map +1 -0
  31. package/dist/shell.d.ts +1 -0
  32. package/dist/shell.esm.js +2 -0
  33. package/dist/shell.esm.js.map +1 -0
  34. package/dist/slot.cjs.js +998 -0
  35. package/dist/slot.cjs.js.map +1 -0
  36. package/dist/slot.d.ts +333 -0
  37. package/dist/slot.esm.js +985 -0
  38. package/dist/slot.esm.js.map +1 -0
  39. package/package.json +28 -2
  40. package/src/audio/AudioManager.ts +17 -5
  41. package/src/core/GameApplication.ts +38 -6
  42. package/src/core/index.ts +2 -0
  43. package/src/game-spec/index.ts +1 -0
  44. package/src/host/autoplay.ts +78 -0
  45. package/src/host/balanceGate.ts +46 -0
  46. package/src/host/buildConfig.ts +28 -0
  47. package/src/host/createSlotGame.ts +543 -0
  48. package/src/host/fatalError.ts +104 -0
  49. package/src/host/freeSpinsCounter.ts +44 -0
  50. package/src/host/index.ts +21 -0
  51. package/src/host/overlayController.ts +81 -0
  52. package/src/host/pauseController.ts +21 -0
  53. package/src/host/playError.ts +64 -0
  54. package/src/host/preboot.ts +25 -0
  55. package/src/host/replay.ts +9 -0
  56. package/src/host/runRound.ts +55 -0
  57. package/src/host/sceneAudio.ts +14 -0
  58. package/src/host/sceneController.ts +96 -0
  59. package/src/host/sceneStart.ts +25 -0
  60. package/src/host/shellConfig.ts +384 -0
  61. package/src/host/skipGesture.ts +24 -0
  62. package/src/host/slotPlay.ts +62 -0
  63. package/src/host/types.ts +74 -0
  64. package/src/scenes/IntroScene.ts +66 -0
  65. package/src/shell/index.ts +20 -0
  66. package/src/slot/anim/CascadeController.ts +102 -0
  67. package/src/slot/anim/ReelSpinController.ts +81 -0
  68. package/src/slot/anim/easing-map.ts +14 -0
  69. package/src/slot/freeSpins/FreeSpinsSession.ts +40 -0
  70. package/src/slot/grid/AnimatedSymbol.ts +68 -0
  71. package/src/slot/grid/ReelGrid.ts +92 -0
  72. package/src/slot/grid/SymbolCell.ts +127 -0
  73. package/src/slot/grid/SymbolView.ts +13 -0
  74. package/src/slot/index.ts +21 -0
  75. package/src/slot/multiplier/MultiplierAccumulator.ts +29 -0
  76. package/src/slot/overlay/BigWinOverlay.ts +89 -0
  77. package/src/slot/overlay/CountUpDisplay.ts +56 -0
  78. package/src/slot/overlay/tiers.ts +29 -0
  79. package/src/types.ts +3 -0
  80. package/src/viewport/ViewportManager.ts +19 -9
@@ -0,0 +1,56 @@
1
+ import { Container, Text, type TextStyle } from 'pixi.js';
2
+ import { Tween, Easing } from '../../animation';
3
+
4
+ export interface CountUpConfig { format: (v: number) => string; style?: Partial<TextStyle>; }
5
+
6
+ /** PURE eased interpolation 0→target over duration (ms). Clamped to [0, target]. */
7
+ export function valueAt(elapsed: number, target: number, duration: number): number {
8
+ if (duration <= 0 || elapsed >= duration) return target;
9
+ if (elapsed <= 0) return 0;
10
+ const p = elapsed / duration;
11
+ const eased = 1 - Math.pow(1 - p, 3); // easeOutCubic
12
+ return target * eased;
13
+ }
14
+
15
+ export class CountUpDisplay extends Container {
16
+ readonly __uiComponent = true as const;
17
+ private _text: Text;
18
+ private _format: (v: number) => string;
19
+ private _value = 0;
20
+
21
+ constructor(config: CountUpConfig) {
22
+ super();
23
+ this._format = config.format;
24
+ this._text = new Text({
25
+ text: this._format(0),
26
+ style: { fontFamily: 'sans-serif', fontSize: 48, fill: 0xffffff, fontWeight: '800', ...config.style },
27
+ });
28
+ this._text.anchor.set(0.5);
29
+ this.addChild(this._text);
30
+ }
31
+
32
+ get text(): string { return this._text.text; }
33
+
34
+ setValue(v: number): void {
35
+ this._value = v;
36
+ this._text.text = this._format(v);
37
+ }
38
+
39
+ /** Swap the value formatter and immediately re-render the current value. */
40
+ setFormat(format: (v: number) => string): void {
41
+ this._format = format;
42
+ this._text.text = this._format(this._value);
43
+ }
44
+
45
+ /** Animate the value to target over duration; fires onTier on each tier-index increase. */
46
+ async countTo(target: number, duration: number, onTier?: (idx: number) => void): Promise<void> {
47
+ const holder = { v: 0 };
48
+ void onTier; // tier tracking is external — onTier is a forward-compat hook
49
+ await Tween.to(holder, { v: target }, duration, Easing.easeOutCubic, () => {
50
+ this.setValue(holder.v);
51
+ });
52
+ this.setValue(target);
53
+ }
54
+
55
+ skip(): void { Tween.killTweensOf(this); }
56
+ }
@@ -0,0 +1,29 @@
1
+ import type { Texture } from 'pixi.js';
2
+
3
+ export interface WinTier {
4
+ id: string;
5
+ minMultiplier: number;
6
+ title: string;
7
+ accentColor: number;
8
+ bannerTexture?: Texture;
9
+ }
10
+
11
+ /** Highest tier whose minMultiplier <= win/bet, or null if below the lowest. */
12
+ export function pickTier(tiers: WinTier[], win: number, bet: number): WinTier | null {
13
+ if (bet <= 0) return null;
14
+ const mult = win / bet;
15
+ let chosen: WinTier | null = null;
16
+ for (const t of tiers) {
17
+ if (mult >= t.minMultiplier && (!chosen || t.minMultiplier >= chosen.minMultiplier)) chosen = t;
18
+ }
19
+ return chosen;
20
+ }
21
+
22
+ /** Index into `tiers` for the running value (or -1 below the lowest tier). */
23
+ export function tierIndexAtValue(tiers: WinTier[], runningValue: number, bet: number): number {
24
+ if (bet <= 0) return -1;
25
+ const mult = runningValue / bet;
26
+ let idx = -1;
27
+ for (let i = 0; i < tiers.length; i++) if (mult >= tiers[i].minMultiplier) idx = i;
28
+ return idx;
29
+ }
package/src/types.ts CHANGED
@@ -111,6 +111,9 @@ export interface GameApplicationConfig {
111
111
 
112
112
  /** Enable debug overlay (FPS, draw calls) */
113
113
  debug?: boolean;
114
+
115
+ /** When set, GameApplication mounts the branded game shell after the SDK handshake. */
116
+ shell?: import('@energy8platform/platform-core/shell').ShellConfig | false;
114
117
  }
115
118
 
116
119
  // ─── Scene Types ───────────────────────────────────────────
@@ -1,4 +1,4 @@
1
- import type { Application } from 'pixi.js';
1
+ import type { Application, Container } from 'pixi.js';
2
2
  import { EventEmitter } from '../core/EventEmitter';
3
3
  import { ScaleMode, Orientation } from '../types';
4
4
 
@@ -45,6 +45,7 @@ export class ViewportManager extends EventEmitter<ViewportEvents> {
45
45
  private _app: Application;
46
46
  private _container: HTMLElement;
47
47
  private _config: ViewportConfig;
48
+ private _target: Container;
48
49
  private _resizeObserver: ResizeObserver | null = null;
49
50
  private _currentOrientation: Orientation = Orientation.LANDSCAPE;
50
51
  private _currentWidth = 0;
@@ -53,11 +54,20 @@ export class ViewportManager extends EventEmitter<ViewportEvents> {
53
54
  private _destroyed = false;
54
55
  private _resizeTimeout: number | null = null;
55
56
 
56
- constructor(app: Application, container: HTMLElement, config: ViewportConfig) {
57
+ constructor(
58
+ app: Application,
59
+ container: HTMLElement,
60
+ config: ViewportConfig,
61
+ target?: Container,
62
+ ) {
57
63
  super();
58
64
  this._app = app;
59
65
  this._container = container;
60
66
  this._config = config;
67
+ // The container this manager scales/offsets. Defaults to app.stage for backward
68
+ // compatibility; the engine passes a dedicated scaled world root so app.stage stays
69
+ // identity (screen space) for unscaled UI layers.
70
+ this._target = target ?? app.stage;
61
71
 
62
72
  this.setupObserver();
63
73
  }
@@ -164,18 +174,18 @@ export class ViewportManager extends EventEmitter<ViewportEvents> {
164
174
  ? Math.min(containerWidth / designWidth, containerHeight / designHeight)
165
175
  : scale;
166
176
 
167
- this._app.stage.scale.set(stageScale);
177
+ this._target.scale.set(stageScale);
168
178
 
169
179
  // Center the stage for FIT mode
170
180
  if (scaleMode === ScaleMode.FIT) {
171
- this._app.stage.x = Math.round((containerWidth - designWidth * stageScale) / 2);
172
- this._app.stage.y = Math.round((containerHeight - designHeight * stageScale) / 2);
181
+ this._target.x = Math.round((containerWidth - designWidth * stageScale) / 2);
182
+ this._target.y = Math.round((containerHeight - designHeight * stageScale) / 2);
173
183
  } else if (scaleMode === ScaleMode.FILL) {
174
- this._app.stage.x = Math.round((containerWidth - gameWidth * stageScale) / 2);
175
- this._app.stage.y = Math.round((containerHeight - gameHeight * stageScale) / 2);
184
+ this._target.x = Math.round((containerWidth - gameWidth * stageScale) / 2);
185
+ this._target.y = Math.round((containerHeight - gameHeight * stageScale) / 2);
176
186
  } else {
177
- this._app.stage.x = 0;
178
- this._app.stage.y = 0;
187
+ this._target.x = 0;
188
+ this._target.y = 0;
179
189
  }
180
190
 
181
191
  this._currentWidth = gameWidth;