@energy8platform/game-engine 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 (80) hide show
  1. package/README.md +1134 -0
  2. package/dist/animation.cjs.js +505 -0
  3. package/dist/animation.cjs.js.map +1 -0
  4. package/dist/animation.d.ts +235 -0
  5. package/dist/animation.esm.js +500 -0
  6. package/dist/animation.esm.js.map +1 -0
  7. package/dist/assets.cjs.js +148 -0
  8. package/dist/assets.cjs.js.map +1 -0
  9. package/dist/assets.d.ts +97 -0
  10. package/dist/assets.esm.js +146 -0
  11. package/dist/assets.esm.js.map +1 -0
  12. package/dist/audio.cjs.js +345 -0
  13. package/dist/audio.cjs.js.map +1 -0
  14. package/dist/audio.d.ts +135 -0
  15. package/dist/audio.esm.js +343 -0
  16. package/dist/audio.esm.js.map +1 -0
  17. package/dist/core.cjs.js +1832 -0
  18. package/dist/core.cjs.js.map +1 -0
  19. package/dist/core.d.ts +633 -0
  20. package/dist/core.esm.js +1827 -0
  21. package/dist/core.esm.js.map +1 -0
  22. package/dist/debug.cjs.js +298 -0
  23. package/dist/debug.cjs.js.map +1 -0
  24. package/dist/debug.d.ts +114 -0
  25. package/dist/debug.esm.js +295 -0
  26. package/dist/debug.esm.js.map +1 -0
  27. package/dist/index.cjs.js +3623 -0
  28. package/dist/index.cjs.js.map +1 -0
  29. package/dist/index.d.ts +1607 -0
  30. package/dist/index.esm.js +3598 -0
  31. package/dist/index.esm.js.map +1 -0
  32. package/dist/ui.cjs.js +1081 -0
  33. package/dist/ui.cjs.js.map +1 -0
  34. package/dist/ui.d.ts +387 -0
  35. package/dist/ui.esm.js +1072 -0
  36. package/dist/ui.esm.js.map +1 -0
  37. package/dist/vite.cjs.js +125 -0
  38. package/dist/vite.cjs.js.map +1 -0
  39. package/dist/vite.d.ts +42 -0
  40. package/dist/vite.esm.js +122 -0
  41. package/dist/vite.esm.js.map +1 -0
  42. package/package.json +107 -0
  43. package/src/animation/Easing.ts +116 -0
  44. package/src/animation/SpineHelper.ts +162 -0
  45. package/src/animation/Timeline.ts +138 -0
  46. package/src/animation/Tween.ts +225 -0
  47. package/src/animation/index.ts +4 -0
  48. package/src/assets/AssetManager.ts +174 -0
  49. package/src/assets/index.ts +2 -0
  50. package/src/audio/AudioManager.ts +366 -0
  51. package/src/audio/index.ts +1 -0
  52. package/src/core/EventEmitter.ts +47 -0
  53. package/src/core/GameApplication.ts +306 -0
  54. package/src/core/Scene.ts +48 -0
  55. package/src/core/SceneManager.ts +258 -0
  56. package/src/core/index.ts +4 -0
  57. package/src/debug/DevBridge.ts +259 -0
  58. package/src/debug/FPSOverlay.ts +102 -0
  59. package/src/debug/index.ts +3 -0
  60. package/src/index.ts +71 -0
  61. package/src/input/InputManager.ts +171 -0
  62. package/src/input/index.ts +1 -0
  63. package/src/loading/CSSPreloader.ts +155 -0
  64. package/src/loading/LoadingScene.ts +356 -0
  65. package/src/loading/index.ts +2 -0
  66. package/src/state/StateMachine.ts +228 -0
  67. package/src/state/index.ts +1 -0
  68. package/src/types.ts +218 -0
  69. package/src/ui/BalanceDisplay.ts +155 -0
  70. package/src/ui/Button.ts +199 -0
  71. package/src/ui/Label.ts +111 -0
  72. package/src/ui/Modal.ts +134 -0
  73. package/src/ui/Panel.ts +125 -0
  74. package/src/ui/ProgressBar.ts +121 -0
  75. package/src/ui/Toast.ts +124 -0
  76. package/src/ui/WinDisplay.ts +133 -0
  77. package/src/ui/index.ts +16 -0
  78. package/src/viewport/ViewportManager.ts +241 -0
  79. package/src/viewport/index.ts +1 -0
  80. package/src/vite/index.ts +153 -0
@@ -0,0 +1,306 @@
1
+ import { Application, Assets, Ticker } from 'pixi.js';
2
+ import { CasinoGameSDK } from '@energy8platform/game-sdk';
3
+ import type { InitData, GameConfigData, SessionData } from '@energy8platform/game-sdk';
4
+ import type { GameApplicationConfig, GameEngineEvents, AssetManifest } from '../types';
5
+ import { ScaleMode, Orientation, TransitionType } from '../types';
6
+ import { EventEmitter } from './EventEmitter';
7
+ import { SceneManager } from './SceneManager';
8
+ import { AssetManager } from '../assets/AssetManager';
9
+ import { AudioManager } from '../audio/AudioManager';
10
+ import { ViewportManager } from '../viewport/ViewportManager';
11
+ import { LoadingScene } from '../loading/LoadingScene';
12
+ import { createCSSPreloader, removeCSSPreloader } from '../loading/CSSPreloader';
13
+
14
+ /**
15
+ * The main entry point for a game built on @energy8platform/game-engine.
16
+ *
17
+ * Orchestrates the full lifecycle:
18
+ * 1. Create PixiJS Application
19
+ * 2. Initialize SDK (or run offline)
20
+ * 3. Show CSS preloader → Canvas loading screen with progress bar
21
+ * 4. Load asset manifest
22
+ * 5. Transition to the first game scene
23
+ *
24
+ * @example
25
+ * ```ts
26
+ * import { GameApplication, ScaleMode } from '@energy8platform/game-engine';
27
+ * import { GameScene } from './scenes/GameScene';
28
+ *
29
+ * const game = new GameApplication({
30
+ * container: '#game',
31
+ * designWidth: 1920,
32
+ * designHeight: 1080,
33
+ * scaleMode: ScaleMode.FIT,
34
+ * manifest: { bundles: [
35
+ * { name: 'preload', assets: [{ alias: 'logo', src: 'logo.png' }] },
36
+ * { name: 'game', assets: [{ alias: 'bg', src: 'background.png' }] },
37
+ * ]},
38
+ * loading: { tapToStart: true },
39
+ * });
40
+ *
41
+ * game.scenes.register('game', GameScene);
42
+ * await game.start('game');
43
+ * ```
44
+ */
45
+ export class GameApplication extends EventEmitter<GameEngineEvents> {
46
+ // ─── Public references ──────────────────────────────────
47
+
48
+ /** PixiJS Application instance */
49
+ public app!: Application;
50
+
51
+ /** Scene manager */
52
+ public scenes!: SceneManager;
53
+
54
+ /** Asset manager */
55
+ public assets!: AssetManager;
56
+
57
+ /** Audio manager */
58
+ public audio!: AudioManager;
59
+
60
+ /** Viewport manager */
61
+ public viewport!: ViewportManager;
62
+
63
+ /** SDK instance (null in offline mode) */
64
+ public sdk: CasinoGameSDK | null = null;
65
+
66
+ /** Data received from SDK initialization */
67
+ public initData: InitData | null = null;
68
+
69
+ /** Configuration */
70
+ public readonly config: GameApplicationConfig;
71
+
72
+ // ─── Private state ──────────────────────────────────────
73
+
74
+ private _running = false;
75
+ private _destroyed = false;
76
+ private _container: HTMLElement | null = null;
77
+
78
+ constructor(config: GameApplicationConfig = {}) {
79
+ super();
80
+ this.config = {
81
+ designWidth: 1920,
82
+ designHeight: 1080,
83
+ scaleMode: ScaleMode.FIT,
84
+ orientation: Orientation.ANY,
85
+ debug: false,
86
+ ...config,
87
+ };
88
+
89
+ // Create SceneManager early so scenes can be registered before start()
90
+ this.scenes = new SceneManager();
91
+ }
92
+
93
+ // ─── Public getters ─────────────────────────────────────
94
+
95
+ /** Current game config from SDK (or null in offline mode) */
96
+ get gameConfig(): GameConfigData | null {
97
+ return this.initData?.config ?? null;
98
+ }
99
+
100
+ /** Current session data */
101
+ get session(): SessionData | null {
102
+ return this.initData?.session ?? null;
103
+ }
104
+
105
+ /** Current balance */
106
+ get balance(): number {
107
+ return this.sdk?.balance ?? 0;
108
+ }
109
+
110
+ /** Current currency */
111
+ get currency(): string {
112
+ return this.sdk?.currency ?? 'USD';
113
+ }
114
+
115
+ /** Whether the engine is running */
116
+ get isRunning(): boolean {
117
+ return this._running;
118
+ }
119
+
120
+ // ─── Lifecycle ──────────────────────────────────────────
121
+
122
+ /**
123
+ * Start the game engine. This is the main entry point.
124
+ *
125
+ * @param firstScene - Key of the first scene to show after loading (must be registered)
126
+ * @param sceneData - Optional data to pass to the first scene's onEnter
127
+ */
128
+ async start(firstScene: string, sceneData?: unknown): Promise<void> {
129
+ if (this._running) {
130
+ console.warn('[GameEngine] Already running');
131
+ return;
132
+ }
133
+
134
+ try {
135
+ // 1. Resolve container element
136
+ this._container = this.resolveContainer();
137
+
138
+ // 2. Show CSS preloader immediately (before PixiJS)
139
+ createCSSPreloader(this._container, this.config.loading);
140
+
141
+ // 3. Initialize PixiJS
142
+ await this.initPixi();
143
+
144
+ // 4. Initialize SDK (if enabled)
145
+ await this.initSDK();
146
+
147
+ // 5. Merge design dimensions from SDK config
148
+ this.applySDKConfig();
149
+
150
+ // 6. Initialize sub-systems
151
+ this.initSubSystems();
152
+
153
+ this.emit('initialized', undefined as any);
154
+
155
+ // 7. Remove CSS preloader, show Canvas loading screen
156
+ removeCSSPreloader(this._container);
157
+
158
+ // 8. Load assets with loading screen
159
+ await this.loadAssets(firstScene, sceneData);
160
+
161
+ // 9. Start the game loop
162
+ this._running = true;
163
+ this.emit('started', undefined as any);
164
+ } catch (err) {
165
+ console.error('[GameEngine] Failed to start:', err);
166
+ this.emit('error', err instanceof Error ? err : new Error(String(err)));
167
+ throw err;
168
+ }
169
+ }
170
+
171
+ /**
172
+ * Destroy the engine and free all resources.
173
+ */
174
+ destroy(): void {
175
+ if (this._destroyed) return;
176
+ this._destroyed = true;
177
+ this._running = false;
178
+
179
+ this.scenes?.destroy();
180
+ this.audio?.destroy();
181
+ this.viewport?.destroy();
182
+ this.sdk?.destroy();
183
+ this.app?.destroy(true, { children: true, texture: true });
184
+ this.removeAllListeners();
185
+
186
+ this.emit('destroyed', undefined as any);
187
+ }
188
+
189
+ // ─── Private initialization steps ──────────────────────
190
+
191
+ private resolveContainer(): HTMLElement {
192
+ if (typeof this.config.container === 'string') {
193
+ const el = document.querySelector<HTMLElement>(this.config.container);
194
+ if (!el) throw new Error(`[GameEngine] Container "${this.config.container}" not found`);
195
+ return el;
196
+ }
197
+ return this.config.container ?? document.body;
198
+ }
199
+
200
+ private async initPixi(): Promise<void> {
201
+ this.app = new Application();
202
+
203
+ const pixiOpts = {
204
+ background: typeof this.config.loading?.backgroundColor === 'number'
205
+ ? this.config.loading.backgroundColor
206
+ : 0x000000,
207
+ antialias: true,
208
+ resolution: Math.min(window.devicePixelRatio, 2),
209
+ autoDensity: true,
210
+ ...this.config.pixi,
211
+ };
212
+
213
+ await this.app.init(pixiOpts);
214
+
215
+ // Append canvas to container
216
+ this._container!.appendChild(this.app.canvas);
217
+
218
+ // Set canvas style
219
+ this.app.canvas.style.display = 'block';
220
+ this.app.canvas.style.width = '100%';
221
+ this.app.canvas.style.height = '100%';
222
+ }
223
+
224
+ private async initSDK(): Promise<void> {
225
+ if (this.config.sdk === false) {
226
+ // Offline / development mode — no SDK
227
+ this.initData = null;
228
+ return;
229
+ }
230
+
231
+ const sdkOpts = typeof this.config.sdk === 'object' ? this.config.sdk : {};
232
+ this.sdk = new CasinoGameSDK(sdkOpts);
233
+
234
+ // Perform the handshake
235
+ this.initData = await this.sdk.ready();
236
+
237
+ // Forward SDK events
238
+ this.sdk.on('error', (err: Error) => {
239
+ this.emit('error', err);
240
+ });
241
+ }
242
+
243
+ private applySDKConfig(): void {
244
+ // If SDK provides viewport dimensions, use them as design reference
245
+ if (this.initData?.config?.viewport) {
246
+ const vp = this.initData.config.viewport;
247
+ if (!this.config.designWidth) this.config.designWidth = vp.width;
248
+ if (!this.config.designHeight) this.config.designHeight = vp.height;
249
+ }
250
+ }
251
+
252
+ private initSubSystems(): void {
253
+ // Asset Manager
254
+ const basePath = this.initData?.assetsUrl ?? '';
255
+ this.assets = new AssetManager(basePath, this.config.manifest);
256
+
257
+ // Audio Manager
258
+ this.audio = new AudioManager(this.config.audio);
259
+
260
+ // Viewport Manager
261
+ this.viewport = new ViewportManager(
262
+ this.app,
263
+ this._container!,
264
+ {
265
+ designWidth: this.config.designWidth!,
266
+ designHeight: this.config.designHeight!,
267
+ scaleMode: this.config.scaleMode!,
268
+ orientation: this.config.orientation!,
269
+ },
270
+ );
271
+
272
+ // Wire SceneManager to the PixiJS stage
273
+ this.scenes.setRoot(this.app.stage);
274
+
275
+ // Wire viewport resize → scene manager
276
+ this.viewport.on('resize', ({ width, height }) => {
277
+ this.scenes.resize(width, height);
278
+ this.emit('resize', { width, height });
279
+ });
280
+
281
+ this.viewport.on('orientationChange', (orientation) => {
282
+ this.emit('orientationChange', orientation);
283
+ });
284
+
285
+ // Connect ticker → scene updates
286
+ this.app.ticker.add((ticker) => {
287
+ // Always update scenes (loading screen needs onUpdate before _running=true)
288
+ this.scenes.update(ticker.deltaTime / 60); // convert to seconds
289
+ });
290
+
291
+ // Trigger initial resize
292
+ this.viewport.refresh();
293
+ }
294
+
295
+ private async loadAssets(firstScene: string, sceneData?: unknown): Promise<void> {
296
+ // Register built-in loading scene
297
+ this.scenes.register('__loading__', LoadingScene as any);
298
+
299
+ // Enter loading scene
300
+ await this.scenes.goto('__loading__', {
301
+ engine: this,
302
+ targetScene: firstScene,
303
+ targetData: sceneData,
304
+ });
305
+ }
306
+ }
@@ -0,0 +1,48 @@
1
+ import { Container } from 'pixi.js';
2
+ import type { IScene } from '../types';
3
+
4
+ /**
5
+ * Base class for all scenes.
6
+ * Provides a root PixiJS Container and lifecycle hooks.
7
+ *
8
+ * @example
9
+ * ```ts
10
+ * class MenuScene extends Scene {
11
+ * async onEnter() {
12
+ * const bg = Sprite.from('menu-bg');
13
+ * this.container.addChild(bg);
14
+ * }
15
+ *
16
+ * onUpdate(dt: number) {
17
+ * // per-frame logic
18
+ * }
19
+ *
20
+ * onResize(width: number, height: number) {
21
+ * // reposition UI
22
+ * }
23
+ * }
24
+ * ```
25
+ */
26
+ export abstract class Scene implements IScene {
27
+ public readonly container: Container;
28
+
29
+ constructor() {
30
+ this.container = new Container();
31
+ this.container.label = this.constructor.name;
32
+ }
33
+
34
+ /** Called when this scene becomes active. Override in subclass. */
35
+ onEnter?(data?: unknown): Promise<void> | void;
36
+
37
+ /** Called when this scene is deactivated. Override in subclass. */
38
+ onExit?(): Promise<void> | void;
39
+
40
+ /** Called every frame with delta time (in seconds). Override in subclass. */
41
+ onUpdate?(dt: number): void;
42
+
43
+ /** Called when the viewport resizes. Override in subclass. */
44
+ onResize?(width: number, height: number): void;
45
+
46
+ /** Cleanup — called when the scene is permanently removed. */
47
+ onDestroy?(): void;
48
+ }
@@ -0,0 +1,258 @@
1
+ import { Container } from 'pixi.js';
2
+ import type { IScene, SceneConstructor, TransitionConfig, TransitionType } from '../types';
3
+ import { TransitionType as TT } from '../types';
4
+ import { Tween } from '../animation/Tween';
5
+ import { EventEmitter } from './EventEmitter';
6
+
7
+ interface SceneEntry {
8
+ scene: IScene;
9
+ key: string;
10
+ }
11
+
12
+ interface SceneManagerEvents {
13
+ change: { from: string | null; to: string };
14
+ }
15
+
16
+ /**
17
+ * Manages the scene stack and transitions between scenes.
18
+ *
19
+ * @example
20
+ * ```ts
21
+ * const scenes = new SceneManager(app.stage);
22
+ * scenes.register('loading', LoadingScene);
23
+ * scenes.register('game', GameScene);
24
+ * await scenes.goto('loading');
25
+ * ```
26
+ */
27
+ export class SceneManager extends EventEmitter<SceneManagerEvents> {
28
+ /** Root container that scenes are added to */
29
+ public root!: Container;
30
+
31
+ private registry = new Map<string, SceneConstructor>();
32
+ private stack: SceneEntry[] = [];
33
+ private _transitioning = false;
34
+
35
+ /** Current viewport dimensions — set by ViewportManager */
36
+ private _width = 0;
37
+ private _height = 0;
38
+
39
+ constructor(root?: Container) {
40
+ super();
41
+ if (root) this.root = root;
42
+ }
43
+
44
+ /** @internal Set the root container (called by GameApplication after PixiJS init) */
45
+ setRoot(root: Container): void {
46
+ this.root = root;
47
+ }
48
+
49
+ /** Register a scene class by key */
50
+ register(key: string, ctor: SceneConstructor): this {
51
+ this.registry.set(key, ctor);
52
+ return this;
53
+ }
54
+
55
+ /** Get the current (topmost) scene entry */
56
+ get current(): SceneEntry | null {
57
+ return this.stack.length > 0 ? this.stack[this.stack.length - 1] : null;
58
+ }
59
+
60
+ /** Get the current scene key */
61
+ get currentKey(): string | null {
62
+ return this.current?.key ?? null;
63
+ }
64
+
65
+ /** Whether a scene transition is in progress */
66
+ get isTransitioning(): boolean {
67
+ return this._transitioning;
68
+ }
69
+
70
+ /**
71
+ * Navigate to a scene, replacing the entire stack.
72
+ */
73
+ async goto(
74
+ key: string,
75
+ data?: unknown,
76
+ transition?: TransitionConfig,
77
+ ): Promise<void> {
78
+ const prevKey = this.currentKey;
79
+
80
+ // Exit all current scenes
81
+ while (this.stack.length > 0) {
82
+ await this.popInternal(false);
83
+ }
84
+
85
+ // Enter new scene
86
+ await this.pushInternal(key, data, transition);
87
+ this.emit('change', { from: prevKey, to: key });
88
+ }
89
+
90
+ /**
91
+ * Push a scene onto the stack (the previous scene stays underneath).
92
+ * Useful for overlays, modals, pause screens.
93
+ */
94
+ async push(
95
+ key: string,
96
+ data?: unknown,
97
+ transition?: TransitionConfig,
98
+ ): Promise<void> {
99
+ const prevKey = this.currentKey;
100
+ await this.pushInternal(key, data, transition);
101
+ this.emit('change', { from: prevKey, to: key });
102
+ }
103
+
104
+ /**
105
+ * Pop the top scene from the stack.
106
+ */
107
+ async pop(transition?: TransitionConfig): Promise<void> {
108
+ if (this.stack.length <= 1) {
109
+ console.warn('[SceneManager] Cannot pop the last scene');
110
+ return;
111
+ }
112
+ const prevKey = this.currentKey;
113
+ await this.popInternal(true, transition);
114
+ this.emit('change', { from: prevKey, to: this.currentKey! });
115
+ }
116
+
117
+ /**
118
+ * Replace the top scene with a new one.
119
+ */
120
+ async replace(
121
+ key: string,
122
+ data?: unknown,
123
+ transition?: TransitionConfig,
124
+ ): Promise<void> {
125
+ const prevKey = this.currentKey;
126
+ await this.popInternal(false);
127
+ await this.pushInternal(key, data, transition);
128
+ this.emit('change', { from: prevKey, to: key });
129
+ }
130
+
131
+ /**
132
+ * Called every frame by GameApplication.
133
+ */
134
+ update(dt: number): void {
135
+ // Update only the top scene
136
+ this.current?.scene.onUpdate?.(dt);
137
+ }
138
+
139
+ /**
140
+ * Called on viewport resize.
141
+ */
142
+ resize(width: number, height: number): void {
143
+ this._width = width;
144
+ this._height = height;
145
+
146
+ // Notify all scenes in the stack
147
+ for (const entry of this.stack) {
148
+ entry.scene.onResize?.(width, height);
149
+ }
150
+ }
151
+
152
+ /**
153
+ * Destroy all scenes and clear the manager.
154
+ */
155
+ destroy(): void {
156
+ for (const entry of this.stack) {
157
+ entry.scene.onDestroy?.();
158
+ entry.scene.container.destroy({ children: true });
159
+ }
160
+ this.stack.length = 0;
161
+ this.registry.clear();
162
+ this.removeAllListeners();
163
+ }
164
+
165
+ // ─── Internal ──────────────────────────────────────────
166
+
167
+ private createScene(key: string): IScene {
168
+ const Ctor = this.registry.get(key);
169
+ if (!Ctor) {
170
+ throw new Error(`[SceneManager] Scene "${key}" is not registered`);
171
+ }
172
+ return new Ctor();
173
+ }
174
+
175
+ private async pushInternal(
176
+ key: string,
177
+ data?: unknown,
178
+ transition?: TransitionConfig,
179
+ ): Promise<void> {
180
+ this._transitioning = true;
181
+
182
+ const scene = this.createScene(key);
183
+ this.root.addChild(scene.container);
184
+
185
+ // Set initial size
186
+ if (this._width && this._height) {
187
+ scene.onResize?.(this._width, this._height);
188
+ }
189
+
190
+ // Transition in
191
+ await this.transitionIn(scene.container, transition);
192
+
193
+ await scene.onEnter?.(data);
194
+
195
+ this.stack.push({ scene, key });
196
+ this._transitioning = false;
197
+ }
198
+
199
+ private async popInternal(
200
+ showTransition: boolean,
201
+ transition?: TransitionConfig,
202
+ ): Promise<void> {
203
+ const entry = this.stack.pop();
204
+ if (!entry) return;
205
+
206
+ this._transitioning = true;
207
+
208
+ await entry.scene.onExit?.();
209
+
210
+ if (showTransition) {
211
+ await this.transitionOut(entry.scene.container, transition);
212
+ }
213
+
214
+ entry.scene.onDestroy?.();
215
+ entry.scene.container.destroy({ children: true });
216
+
217
+ this._transitioning = false;
218
+ }
219
+
220
+ private async transitionIn(
221
+ container: Container,
222
+ config?: TransitionConfig,
223
+ ): Promise<void> {
224
+ const type = config?.type ?? TT.NONE;
225
+ const duration = config?.duration ?? 300;
226
+
227
+ if (type === TT.NONE || duration <= 0) return;
228
+
229
+ if (type === TT.FADE) {
230
+ container.alpha = 0;
231
+ await Tween.to(container, { alpha: 1 }, duration, config?.easing);
232
+ } else if (type === TT.SLIDE_LEFT) {
233
+ container.x = this._width;
234
+ await Tween.to(container, { x: 0 }, duration, config?.easing);
235
+ } else if (type === TT.SLIDE_RIGHT) {
236
+ container.x = -this._width;
237
+ await Tween.to(container, { x: 0 }, duration, config?.easing);
238
+ }
239
+ }
240
+
241
+ private async transitionOut(
242
+ container: Container,
243
+ config?: TransitionConfig,
244
+ ): Promise<void> {
245
+ const type = config?.type ?? TT.FADE;
246
+ const duration = config?.duration ?? 300;
247
+
248
+ if (type === TT.NONE || duration <= 0) return;
249
+
250
+ if (type === TT.FADE) {
251
+ await Tween.to(container, { alpha: 0 }, duration, config?.easing);
252
+ } else if (type === TT.SLIDE_LEFT) {
253
+ await Tween.to(container, { x: -this._width }, duration, config?.easing);
254
+ } else if (type === TT.SLIDE_RIGHT) {
255
+ await Tween.to(container, { x: this._width }, duration, config?.easing);
256
+ }
257
+ }
258
+ }
@@ -0,0 +1,4 @@
1
+ export { GameApplication } from './GameApplication';
2
+ export { SceneManager } from './SceneManager';
3
+ export { Scene } from './Scene';
4
+ export { EventEmitter } from './EventEmitter';