@energy8platform/game-engine 0.2.1 → 0.3.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.
- package/README.md +298 -28
- package/dist/animation.cjs.js +191 -1
- package/dist/animation.cjs.js.map +1 -1
- package/dist/animation.d.ts +117 -1
- package/dist/animation.esm.js +192 -3
- package/dist/animation.esm.js.map +1 -1
- package/dist/audio.cjs.js +66 -16
- package/dist/audio.cjs.js.map +1 -1
- package/dist/audio.d.ts +4 -0
- package/dist/audio.esm.js +66 -16
- package/dist/audio.esm.js.map +1 -1
- package/dist/core.cjs.js +306 -85
- package/dist/core.cjs.js.map +1 -1
- package/dist/core.d.ts +60 -1
- package/dist/core.esm.js +307 -86
- package/dist/core.esm.js.map +1 -1
- package/dist/debug.cjs.js +36 -68
- package/dist/debug.cjs.js.map +1 -1
- package/dist/debug.d.ts +4 -6
- package/dist/debug.esm.js +36 -68
- package/dist/debug.esm.js.map +1 -1
- package/dist/index.cjs.js +1247 -253
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.d.ts +386 -41
- package/dist/index.esm.js +1247 -256
- package/dist/index.esm.js.map +1 -1
- package/dist/ui.cjs.js +757 -1
- package/dist/ui.cjs.js.map +1 -1
- package/dist/ui.d.ts +208 -2
- package/dist/ui.esm.js +756 -2
- package/dist/ui.esm.js.map +1 -1
- package/dist/vite.cjs.js +65 -68
- package/dist/vite.cjs.js.map +1 -1
- package/dist/vite.d.ts +17 -23
- package/dist/vite.esm.js +66 -68
- package/dist/vite.esm.js.map +1 -1
- package/package.json +4 -5
- package/src/animation/SpriteAnimation.ts +210 -0
- package/src/animation/Tween.ts +27 -1
- package/src/animation/index.ts +2 -0
- package/src/audio/AudioManager.ts +64 -15
- package/src/core/EventEmitter.ts +7 -1
- package/src/core/GameApplication.ts +18 -7
- package/src/core/SceneManager.ts +3 -1
- package/src/debug/DevBridge.ts +49 -80
- package/src/index.ts +6 -0
- package/src/input/InputManager.ts +26 -0
- package/src/loading/CSSPreloader.ts +7 -33
- package/src/loading/LoadingScene.ts +17 -41
- package/src/loading/index.ts +1 -0
- package/src/loading/logo.ts +95 -0
- package/src/types.ts +4 -0
- package/src/ui/BalanceDisplay.ts +14 -0
- package/src/ui/Button.ts +1 -1
- package/src/ui/Layout.ts +364 -0
- package/src/ui/ScrollContainer.ts +557 -0
- package/src/ui/index.ts +4 -0
- package/src/viewport/ViewportManager.ts +2 -0
- package/src/vite/index.ts +83 -83
package/README.md
CHANGED
|
@@ -17,7 +17,21 @@ A universal casino game engine built on [PixiJS v8](https://pixijs.com/) and [@e
|
|
|
17
17
|
- [Viewport & Scaling](#viewport--scaling)
|
|
18
18
|
- [State Machine](#state-machine)
|
|
19
19
|
- [Animation](#animation)
|
|
20
|
+
- [Tween](#tween)
|
|
21
|
+
- [Timeline](#timeline)
|
|
22
|
+
- [SpriteAnimation](#spriteanimation)
|
|
23
|
+
- [Spine Animations](#spine-animations)
|
|
20
24
|
- [UI Components](#ui-components)
|
|
25
|
+
- [Layout](#layout)
|
|
26
|
+
- [ScrollContainer](#scrollcontainer)
|
|
27
|
+
- [Button](#button)
|
|
28
|
+
- [Label](#label)
|
|
29
|
+
- [BalanceDisplay](#balancedisplay)
|
|
30
|
+
- [WinDisplay](#windisplay)
|
|
31
|
+
- [ProgressBar](#progressbar)
|
|
32
|
+
- [Panel](#panel)
|
|
33
|
+
- [Modal](#modal)
|
|
34
|
+
- [Toast](#toast)
|
|
21
35
|
- [Input](#input)
|
|
22
36
|
- [Vite Configuration](#vite-configuration)
|
|
23
37
|
- [DevBridge](#devbridge)
|
|
@@ -83,7 +97,7 @@ async function bootstrap() {
|
|
|
83
97
|
debug: true,
|
|
84
98
|
});
|
|
85
99
|
|
|
86
|
-
game.scenes.register('game', GameScene
|
|
100
|
+
game.scenes.register('game', GameScene);
|
|
87
101
|
|
|
88
102
|
game.on('initialized', () => console.log('Engine initialized'));
|
|
89
103
|
game.on('loaded', () => console.log('Assets loaded'));
|
|
@@ -105,7 +119,7 @@ bootstrap();
|
|
|
105
119
|
| Package | Version | Required |
|
|
106
120
|
| --- | --- | --- |
|
|
107
121
|
| `pixi.js` | `^8.16.0` | Yes |
|
|
108
|
-
| `@energy8platform/game-sdk` | `^2.
|
|
122
|
+
| `@energy8platform/game-sdk` | `^2.6.0` | Yes |
|
|
109
123
|
| `@pixi/sound` | `^6.0.0` | Optional — for audio |
|
|
110
124
|
| `@esotericsoftware/spine-pixi-v8` | `~4.2.0` | Optional — for Spine animations |
|
|
111
125
|
|
|
@@ -118,8 +132,8 @@ import { GameApplication } from '@energy8platform/game-engine'; // full b
|
|
|
118
132
|
import { Scene, SceneManager } from '@energy8platform/game-engine/core';
|
|
119
133
|
import { AssetManager } from '@energy8platform/game-engine/assets';
|
|
120
134
|
import { AudioManager } from '@energy8platform/game-engine/audio';
|
|
121
|
-
import { Button, Label, Modal } from '@energy8platform/game-engine/ui';
|
|
122
|
-
import { Tween, Timeline, Easing } from '@energy8platform/game-engine/animation';
|
|
135
|
+
import { Button, Label, Modal, Layout, ScrollContainer } from '@energy8platform/game-engine/ui';
|
|
136
|
+
import { Tween, Timeline, Easing, SpriteAnimation } from '@energy8platform/game-engine/animation';
|
|
123
137
|
import { DevBridge, FPSOverlay } from '@energy8platform/game-engine/debug';
|
|
124
138
|
import { defineGameConfig } from '@energy8platform/game-engine/vite';
|
|
125
139
|
```
|
|
@@ -146,7 +160,7 @@ import { defineGameConfig } from '@energy8platform/game-engine/vite';
|
|
|
146
160
|
|
|
147
161
|
1. **CSS Preloader** — an instant HTML/CSS overlay shown while PixiJS initializes (inline SVG logo with a shimmer animation and "Loading..." text).
|
|
148
162
|
2. **PixiJS initialization** — creates `Application`, initializes `ResizeObserver`.
|
|
149
|
-
3. **SDK handshake** — connects to the casino host (or DevBridge in dev mode).
|
|
163
|
+
3. **SDK handshake** — connects to the casino host (or DevBridge in dev mode via shared `MemoryChannel`).
|
|
150
164
|
4. **Canvas Loading Screen** — `LoadingScene` displays the SVG logo with an animated progress bar, `preload` bundle is loaded first.
|
|
151
165
|
5. **Asset loading** — remaining bundles are loaded; the progress bar fills in real time.
|
|
152
166
|
6. **Tap-to-start** — optional screen shown after loading (required on mobile for audio unlock).
|
|
@@ -169,6 +183,10 @@ import { defineGameConfig } from '@energy8platform/game-engine/vite';
|
|
|
169
183
|
| `manifest` | `AssetManifest` | — | Asset manifest |
|
|
170
184
|
| `audio` | `AudioConfig` | — | Audio configuration |
|
|
171
185
|
| `sdk` | `object \| false` | — | SDK options; `false` to disable |
|
|
186
|
+
| `sdk.devMode` | `boolean` | `false` | Use in-memory channel instead of `postMessage` (no iframe needed) |
|
|
187
|
+
| `sdk.parentOrigin` | `string` | — | Expected parent origin for `postMessage` validation |
|
|
188
|
+
| `sdk.timeout` | `number` | — | SDK handshake timeout in ms |
|
|
189
|
+
| `sdk.debug` | `boolean` | — | Enable SDK debug logging |
|
|
172
190
|
| `pixi` | `Partial<ApplicationOptions>` | — | PixiJS pass-through options |
|
|
173
191
|
| `debug` | `boolean` | `false` | Enable FPS overlay |
|
|
174
192
|
|
|
@@ -261,9 +279,9 @@ export class GameScene extends Scene {
|
|
|
261
279
|
const scenes = game.scenes;
|
|
262
280
|
|
|
263
281
|
// Register scenes
|
|
264
|
-
scenes.register('menu', MenuScene
|
|
265
|
-
scenes.register('game', GameScene
|
|
266
|
-
scenes.register('bonus', BonusScene
|
|
282
|
+
scenes.register('menu', MenuScene);
|
|
283
|
+
scenes.register('game', GameScene);
|
|
284
|
+
scenes.register('bonus', BonusScene);
|
|
267
285
|
|
|
268
286
|
// Navigate (replaces entire stack)
|
|
269
287
|
await scenes.goto('game');
|
|
@@ -400,7 +418,7 @@ const audio = game.audio;
|
|
|
400
418
|
audio.play('click', 'ui');
|
|
401
419
|
audio.play('coin-drop', 'sfx', { volume: 0.8 });
|
|
402
420
|
|
|
403
|
-
// Music with crossfade
|
|
421
|
+
// Music with crossfade (smooth volume transition between tracks)
|
|
404
422
|
audio.playMusic('main-theme', 1000); // 1s crossfade
|
|
405
423
|
audio.stopMusic();
|
|
406
424
|
|
|
@@ -542,13 +560,17 @@ await Tween.from(sprite, { scale: 0 }, 300, Easing.easeOutBack);
|
|
|
542
560
|
// Animate between two sets of values
|
|
543
561
|
await Tween.fromTo(sprite, { x: -100 }, { x: 500 }, 1000, Easing.easeInOutQuad);
|
|
544
562
|
|
|
545
|
-
// Wait (
|
|
563
|
+
// Wait (uses PixiJS Ticker for consistent timing)
|
|
546
564
|
await Tween.delay(1000);
|
|
547
565
|
|
|
548
566
|
// Cancel tweens
|
|
549
567
|
Tween.killTweensOf(sprite);
|
|
550
568
|
Tween.killAll();
|
|
551
569
|
|
|
570
|
+
// Full reset — kill all tweens and remove ticker listener
|
|
571
|
+
// Useful for cleanup between game instances, tests, or hot-reload
|
|
572
|
+
Tween.reset();
|
|
573
|
+
|
|
552
574
|
// Supports nested properties
|
|
553
575
|
await Tween.to(sprite, { 'scale.x': 2, 'position.y': 300 }, 500);
|
|
554
576
|
```
|
|
@@ -592,6 +614,59 @@ All 24 easing functions:
|
|
|
592
614
|
| | | | `easeOutElastic` |
|
|
593
615
|
| | | | `easeInElastic` |
|
|
594
616
|
|
|
617
|
+
### SpriteAnimation
|
|
618
|
+
|
|
619
|
+
Frame-based animation helper wrapping PixiJS `AnimatedSprite`. Cheaper than Spine for simple frame sequences — perfect for coin showers, symbol animations, sparkle trails, and win celebrations.
|
|
620
|
+
|
|
621
|
+
```typescript
|
|
622
|
+
import { SpriteAnimation } from '@energy8platform/game-engine';
|
|
623
|
+
import { Assets } from 'pixi.js';
|
|
624
|
+
|
|
625
|
+
// From an array of textures
|
|
626
|
+
const coinAnim = SpriteAnimation.create(coinTextures, {
|
|
627
|
+
fps: 30,
|
|
628
|
+
loop: true,
|
|
629
|
+
});
|
|
630
|
+
scene.container.addChild(coinAnim);
|
|
631
|
+
|
|
632
|
+
// From a spritesheet using a name prefix
|
|
633
|
+
const sheet = Assets.get('effects');
|
|
634
|
+
const sparkle = SpriteAnimation.fromSpritesheet(sheet, 'sparkle_', {
|
|
635
|
+
fps: 24,
|
|
636
|
+
loop: true,
|
|
637
|
+
});
|
|
638
|
+
|
|
639
|
+
// From a numbered range (e.g., 'explosion_00' to 'explosion_24')
|
|
640
|
+
const explosion = SpriteAnimation.fromRange(sheet, 'explosion_{i}', 0, 24, {
|
|
641
|
+
fps: 60,
|
|
642
|
+
loop: false,
|
|
643
|
+
onComplete: () => explosion.destroy(),
|
|
644
|
+
});
|
|
645
|
+
|
|
646
|
+
// From pre-loaded texture aliases
|
|
647
|
+
const anim = SpriteAnimation.fromAliases(
|
|
648
|
+
['frame_0', 'frame_1', 'frame_2', 'frame_3'],
|
|
649
|
+
{ fps: 12 },
|
|
650
|
+
);
|
|
651
|
+
|
|
652
|
+
// Fire-and-forget: play once and auto-destroy
|
|
653
|
+
const { sprite, finished } = SpriteAnimation.playOnce(coinTextures, {
|
|
654
|
+
fps: 30,
|
|
655
|
+
});
|
|
656
|
+
scene.container.addChild(sprite);
|
|
657
|
+
await finished; // resolves when animation completes
|
|
658
|
+
```
|
|
659
|
+
|
|
660
|
+
#### SpriteAnimationConfig
|
|
661
|
+
|
|
662
|
+
| Property | Type | Default | Description |
|
|
663
|
+
| --- | --- | --- | --- |
|
|
664
|
+
| `fps` | `number` | `24` | Frames per second |
|
|
665
|
+
| `loop` | `boolean` | `true` | Whether to loop |
|
|
666
|
+
| `autoPlay` | `boolean` | `true` | Start playing immediately |
|
|
667
|
+
| `onComplete` | `() => void` | — | Callback when animation completes (non-looping) |
|
|
668
|
+
| `anchor` | `number \| { x, y }` | `0.5` | Anchor point |
|
|
669
|
+
|
|
595
670
|
### Spine Animations
|
|
596
671
|
|
|
597
672
|
If `@esotericsoftware/spine-pixi-v8` is installed:
|
|
@@ -621,6 +696,136 @@ console.log(SpineHelper.getAnimationNames(spine));
|
|
|
621
696
|
|
|
622
697
|
## UI Components
|
|
623
698
|
|
|
699
|
+
### Layout
|
|
700
|
+
|
|
701
|
+
Responsive layout container that automatically arranges children. Supports horizontal, vertical, grid, and wrap modes with alignment, padding, gap, anchor positioning, and viewport breakpoints.
|
|
702
|
+
|
|
703
|
+
```typescript
|
|
704
|
+
import { Layout } from '@energy8platform/game-engine';
|
|
705
|
+
|
|
706
|
+
// Horizontal toolbar anchored to bottom-center
|
|
707
|
+
const toolbar = new Layout({
|
|
708
|
+
direction: 'horizontal',
|
|
709
|
+
gap: 20,
|
|
710
|
+
alignment: 'center',
|
|
711
|
+
anchor: 'bottom-center',
|
|
712
|
+
padding: 16,
|
|
713
|
+
breakpoints: {
|
|
714
|
+
768: { direction: 'vertical', gap: 10 },
|
|
715
|
+
},
|
|
716
|
+
});
|
|
717
|
+
|
|
718
|
+
toolbar.addItem(spinButton);
|
|
719
|
+
toolbar.addItem(betLabel);
|
|
720
|
+
toolbar.addItem(balanceDisplay);
|
|
721
|
+
scene.container.addChild(toolbar);
|
|
722
|
+
|
|
723
|
+
// Update position on resize
|
|
724
|
+
toolbar.updateViewport(width, height);
|
|
725
|
+
```
|
|
726
|
+
|
|
727
|
+
```typescript
|
|
728
|
+
// Grid layout for a symbol paytable
|
|
729
|
+
const grid = new Layout({
|
|
730
|
+
direction: 'grid',
|
|
731
|
+
columns: 3,
|
|
732
|
+
gap: 16,
|
|
733
|
+
alignment: 'center',
|
|
734
|
+
anchor: 'center',
|
|
735
|
+
padding: [20, 40, 20, 40],
|
|
736
|
+
});
|
|
737
|
+
|
|
738
|
+
symbols.forEach((sym) => grid.addItem(sym));
|
|
739
|
+
grid.updateViewport(viewWidth, viewHeight);
|
|
740
|
+
```
|
|
741
|
+
|
|
742
|
+
```typescript
|
|
743
|
+
// Wrap layout — items flow and wrap to next line
|
|
744
|
+
const tags = new Layout({
|
|
745
|
+
direction: 'wrap',
|
|
746
|
+
gap: 8,
|
|
747
|
+
maxWidth: 600,
|
|
748
|
+
});
|
|
749
|
+
```
|
|
750
|
+
|
|
751
|
+
#### LayoutConfig
|
|
752
|
+
|
|
753
|
+
| Property | Type | Default | Description |
|
|
754
|
+
| --- | --- | --- | --- |
|
|
755
|
+
| `direction` | `'horizontal' \| 'vertical' \| 'grid' \| 'wrap'` | `'vertical'` | Layout direction |
|
|
756
|
+
| `gap` | `number` | `0` | Gap between children (px) |
|
|
757
|
+
| `padding` | `number \| [top, right, bottom, left]` | `0` | Inner padding |
|
|
758
|
+
| `alignment` | `'start' \| 'center' \| 'end' \| 'stretch'` | `'start'` | Cross-axis alignment |
|
|
759
|
+
| `anchor` | `LayoutAnchor` | `'top-left'` | Position relative to viewport |
|
|
760
|
+
| `columns` | `number` | `2` | Column count (grid mode only) |
|
|
761
|
+
| `maxWidth` | `number` | `Infinity` | Max width before wrapping (wrap mode) |
|
|
762
|
+
| `autoLayout` | `boolean` | `true` | Auto-recalculate on add/remove |
|
|
763
|
+
| `breakpoints` | `Record<number, Partial<LayoutConfig>>` | — | Override config per viewport width |
|
|
764
|
+
|
|
765
|
+
**Anchor values:** `top-left`, `top-center`, `top-right`, `center-left`, `center`, `center-right`, `bottom-left`, `bottom-center`, `bottom-right`
|
|
766
|
+
|
|
767
|
+
### ScrollContainer
|
|
768
|
+
|
|
769
|
+
Scrollable container with touch/drag, mouse wheel, inertia deceleration, elastic overscroll bounce, snap-to-item, and auto-hiding scrollbars. Ideal for paytables, settings, bet history, and any content that doesn't fit on screen.
|
|
770
|
+
|
|
771
|
+
```typescript
|
|
772
|
+
import { ScrollContainer } from '@energy8platform/game-engine';
|
|
773
|
+
|
|
774
|
+
const scroll = new ScrollContainer({
|
|
775
|
+
width: 600,
|
|
776
|
+
height: 400,
|
|
777
|
+
direction: 'vertical',
|
|
778
|
+
showScrollbar: true,
|
|
779
|
+
elasticity: 0.3,
|
|
780
|
+
inertia: 0.92,
|
|
781
|
+
borderRadius: 12,
|
|
782
|
+
backgroundColor: 0x1a1a2e,
|
|
783
|
+
backgroundAlpha: 0.8,
|
|
784
|
+
});
|
|
785
|
+
|
|
786
|
+
// Build scrollable content
|
|
787
|
+
const list = new Container();
|
|
788
|
+
for (let i = 0; i < 50; i++) {
|
|
789
|
+
const row = createRow(i);
|
|
790
|
+
row.y = i * 40;
|
|
791
|
+
list.addChild(row);
|
|
792
|
+
}
|
|
793
|
+
scroll.setContent(list);
|
|
794
|
+
|
|
795
|
+
scene.container.addChild(scroll);
|
|
796
|
+
```
|
|
797
|
+
|
|
798
|
+
```typescript
|
|
799
|
+
// Programmatic scrolling
|
|
800
|
+
scroll.scrollTo(0, 200); // scroll to y=200 with animation
|
|
801
|
+
scroll.scrollTo(0, 200, false); // instant jump
|
|
802
|
+
scroll.scrollToItem(5); // snap to item index (when snapSize is set)
|
|
803
|
+
|
|
804
|
+
// Current position
|
|
805
|
+
const { x, y } = scroll.scrollPosition;
|
|
806
|
+
|
|
807
|
+
// Resize viewport
|
|
808
|
+
scroll.resize(newWidth, newHeight);
|
|
809
|
+
```
|
|
810
|
+
|
|
811
|
+
#### ScrollContainerConfig
|
|
812
|
+
|
|
813
|
+
| Property | Type | Default | Description |
|
|
814
|
+
| --- | --- | --- | --- |
|
|
815
|
+
| `width` | `number` | — | Visible viewport width |
|
|
816
|
+
| `height` | `number` | — | Visible viewport height |
|
|
817
|
+
| `direction` | `'vertical' \| 'horizontal' \| 'both'` | `'vertical'` | Scroll direction |
|
|
818
|
+
| `showScrollbar` | `boolean` | `true` | Show scrollbar(s) |
|
|
819
|
+
| `scrollbarWidth` | `number` | `6` | Scrollbar width (px) |
|
|
820
|
+
| `scrollbarColor` | `number` | `0xffffff` | Scrollbar color |
|
|
821
|
+
| `scrollbarAlpha` | `number` | `0.4` | Scrollbar opacity |
|
|
822
|
+
| `elasticity` | `number` | `0.3` | Overscroll bounce (0 = none) |
|
|
823
|
+
| `inertia` | `number` | `0.92` | Deceleration factor (0 = instant stop) |
|
|
824
|
+
| `snapSize` | `number` | `0` | Snap to fixed increments (0 = disabled) |
|
|
825
|
+
| `backgroundColor` | `number` | — | Background color (transparent if omitted) |
|
|
826
|
+
| `backgroundAlpha` | `number` | `1` | Background opacity |
|
|
827
|
+
| `borderRadius` | `number` | `0` | Mask border radius |
|
|
828
|
+
|
|
624
829
|
### Button
|
|
625
830
|
|
|
626
831
|
```typescript
|
|
@@ -799,10 +1004,17 @@ if (input.isKeyDown('ArrowLeft')) {
|
|
|
799
1004
|
input.lock();
|
|
800
1005
|
// ... animation plays ...
|
|
801
1006
|
input.unlock();
|
|
1007
|
+
|
|
1008
|
+
// Convert DOM canvas position to game-world coordinates
|
|
1009
|
+
// (accounts for viewport scaling and offset)
|
|
1010
|
+
const worldPos = input.getWorldPosition(canvasX, canvasY);
|
|
1011
|
+
console.log(worldPos.x, worldPos.y);
|
|
802
1012
|
```
|
|
803
1013
|
|
|
804
1014
|
**Events:** `tap`, `press`, `release`, `move`, `swipe`, `keydown`, `keyup`
|
|
805
1015
|
|
|
1016
|
+
> **Note:** The viewport transform for coordinate mapping is wired up automatically by `GameApplication`. Call `getWorldPosition()` when you need to convert raw DOM coordinates to game-world space.
|
|
1017
|
+
|
|
806
1018
|
---
|
|
807
1019
|
|
|
808
1020
|
## Vite Configuration
|
|
@@ -815,28 +1027,31 @@ import { defineGameConfig } from '@energy8platform/game-engine/vite';
|
|
|
815
1027
|
|
|
816
1028
|
export default defineGameConfig({
|
|
817
1029
|
base: '/games/my-slot/',
|
|
818
|
-
outDir: 'dist',
|
|
819
1030
|
devBridge: true, // Auto-inject DevBridge in dev mode
|
|
820
|
-
|
|
821
|
-
'png', 'jpg', 'webp', 'avif',
|
|
822
|
-
'mp3', 'ogg', 'wav',
|
|
823
|
-
'json', 'atlas', 'skel',
|
|
824
|
-
'fnt', 'ttf', 'woff2',
|
|
825
|
-
],
|
|
1031
|
+
devBridgeConfig: './dev.config', // Custom config path (optional)
|
|
826
1032
|
vite: {
|
|
827
1033
|
// Additional Vite config overrides
|
|
828
1034
|
},
|
|
829
1035
|
});
|
|
830
1036
|
```
|
|
831
1037
|
|
|
1038
|
+
### `GameConfig`
|
|
1039
|
+
|
|
1040
|
+
| Property | Type | Default | Description |
|
|
1041
|
+
| --- | --- | --- | --- |
|
|
1042
|
+
| `base` | `string` | `'/'` | Vite `base` path for deployment |
|
|
1043
|
+
| `devBridge` | `boolean` | `false` | Auto-inject DevBridge in dev mode |
|
|
1044
|
+
| `devBridgeConfig` | `string` | `'./dev.config'` | Path to DevBridge config file |
|
|
1045
|
+
| `vite` | `UserConfig` | — | Additional Vite config to merge |
|
|
1046
|
+
|
|
832
1047
|
### What `defineGameConfig` Provides
|
|
833
1048
|
|
|
834
|
-
- **
|
|
1049
|
+
- **Build target: ES2020+** — modern output for all supported casino platforms
|
|
1050
|
+
- **Asset inlining** — files under 8KB are auto-inlined
|
|
1051
|
+
- **PixiJS chunk splitting** — `pixi.js` is extracted into a separate chunk for caching
|
|
835
1052
|
- **DevBridge injection** — automatically available in dev mode via virtual module
|
|
836
|
-
- **
|
|
837
|
-
- **
|
|
838
|
-
- **Gzip-friendly output** — chunking strategy optimized for compression
|
|
839
|
-
- **Base path** — configurable for deployment subpaths
|
|
1053
|
+
- **Dev server** — port 3000, auto-open browser
|
|
1054
|
+
- **Dependency optimization** — `pixi.js` pre-bundled for faster dev starts
|
|
840
1055
|
|
|
841
1056
|
### Custom DevBridge Configuration
|
|
842
1057
|
|
|
@@ -858,13 +1073,15 @@ export default {
|
|
|
858
1073
|
} satisfies DevBridgeConfig;
|
|
859
1074
|
```
|
|
860
1075
|
|
|
861
|
-
This file is auto-imported by the Vite plugin when `devBridge: true`.
|
|
1076
|
+
This file is auto-imported by the Vite plugin when `devBridge: true`. The plugin injects a virtual module (`/@dev-bridge-entry.js`) that starts DevBridge **before** importing your app entry point, ensuring the `MemoryChannel` is ready when the SDK calls `ready()`.
|
|
862
1077
|
|
|
863
1078
|
---
|
|
864
1079
|
|
|
865
1080
|
## DevBridge
|
|
866
1081
|
|
|
867
|
-
`DevBridge` simulates a casino host for local development. It
|
|
1082
|
+
`DevBridge` simulates a casino host for local development. It uses the SDK's `Bridge` class in `devMode`, communicating with `CasinoGameSDK` through a shared in-memory `MemoryChannel` — no `postMessage` or iframe required.
|
|
1083
|
+
|
|
1084
|
+
> **Requires `@energy8platform/game-sdk` >= 2.6.0**
|
|
868
1085
|
|
|
869
1086
|
```typescript
|
|
870
1087
|
import { DevBridge } from '@energy8platform/game-engine/debug';
|
|
@@ -876,7 +1093,10 @@ const bridge = new DevBridge({
|
|
|
876
1093
|
networkDelay: 200,
|
|
877
1094
|
debug: true,
|
|
878
1095
|
gameConfig: {
|
|
1096
|
+
id: 'my-slot',
|
|
1097
|
+
type: 'slot',
|
|
879
1098
|
viewport: { width: 1920, height: 1080 },
|
|
1099
|
+
betLevels: [0.1, 0.2, 0.5, 1, 2, 5, 10],
|
|
880
1100
|
},
|
|
881
1101
|
onPlay: ({ action, bet, roundId }) => {
|
|
882
1102
|
// Return custom play result
|
|
@@ -885,7 +1105,7 @@ const bridge = new DevBridge({
|
|
|
885
1105
|
},
|
|
886
1106
|
});
|
|
887
1107
|
|
|
888
|
-
bridge.start();
|
|
1108
|
+
bridge.start(); // Creates SDK Bridge({ devMode: true }) + registers handlers
|
|
889
1109
|
|
|
890
1110
|
// Update balance programmatically
|
|
891
1111
|
bridge.setBalance(5000);
|
|
@@ -894,6 +1114,8 @@ bridge.setBalance(5000);
|
|
|
894
1114
|
bridge.destroy();
|
|
895
1115
|
```
|
|
896
1116
|
|
|
1117
|
+
When using the Vite plugin with `devBridge: true`, the SDK is automatically configured with `devMode: true` so both sides use the same `MemoryChannel`.
|
|
1118
|
+
|
|
897
1119
|
### Handled Messages
|
|
898
1120
|
|
|
899
1121
|
| Message | Description |
|
|
@@ -920,7 +1142,7 @@ fps.toggle();
|
|
|
920
1142
|
fps.hide();
|
|
921
1143
|
```
|
|
922
1144
|
|
|
923
|
-
When `debug: true` is set in `GameApplicationConfig`, the FPS overlay is
|
|
1145
|
+
When `debug: true` is set in `GameApplicationConfig`, the FPS overlay is created and shown automatically — no manual setup needed.
|
|
924
1146
|
|
|
925
1147
|
The overlay displays:
|
|
926
1148
|
- Average FPS
|
|
@@ -1077,9 +1299,10 @@ class Tween {
|
|
|
1077
1299
|
static to(target: any, props: Record<string, number>, duration: number, easing?: EasingFunction, onUpdate?: (p: number) => void): Promise<void>;
|
|
1078
1300
|
static from(target: any, props: Record<string, number>, duration: number, easing?, onUpdate?): Promise<void>;
|
|
1079
1301
|
static fromTo(target: any, fromProps: Record<string, number>, toProps: Record<string, number>, duration: number, easing?, onUpdate?): Promise<void>;
|
|
1080
|
-
static delay(ms: number): Promise<void>;
|
|
1302
|
+
static delay(ms: number): Promise<void>; // Uses PixiJS Ticker
|
|
1081
1303
|
static killTweensOf(target: any): void;
|
|
1082
1304
|
static killAll(): void;
|
|
1305
|
+
static reset(): void; // Kill all + remove ticker listener
|
|
1083
1306
|
}
|
|
1084
1307
|
```
|
|
1085
1308
|
|
|
@@ -1110,10 +1333,56 @@ class InputManager extends EventEmitter<InputEvents> {
|
|
|
1110
1333
|
lock(): void;
|
|
1111
1334
|
unlock(): void;
|
|
1112
1335
|
isKeyDown(key: string): boolean;
|
|
1336
|
+
setViewportTransform(scale: number, offsetX: number, offsetY: number): void;
|
|
1337
|
+
getWorldPosition(canvasX: number, canvasY: number): { x: number; y: number };
|
|
1338
|
+
destroy(): void;
|
|
1339
|
+
}
|
|
1340
|
+
```
|
|
1341
|
+
|
|
1342
|
+
### Layout
|
|
1343
|
+
|
|
1344
|
+
```typescript
|
|
1345
|
+
class Layout extends Container {
|
|
1346
|
+
get items(): readonly Container[];
|
|
1347
|
+
|
|
1348
|
+
constructor(config?: LayoutConfig);
|
|
1349
|
+
addItem(child: Container): this;
|
|
1350
|
+
removeItem(child: Container): this;
|
|
1351
|
+
clearItems(): this;
|
|
1352
|
+
updateViewport(width: number, height: number): void;
|
|
1353
|
+
layout(): void;
|
|
1354
|
+
}
|
|
1355
|
+
```
|
|
1356
|
+
|
|
1357
|
+
### ScrollContainer
|
|
1358
|
+
|
|
1359
|
+
```typescript
|
|
1360
|
+
class ScrollContainer extends Container {
|
|
1361
|
+
get content(): Container | null;
|
|
1362
|
+
get scrollPosition(): { x: number; y: number };
|
|
1363
|
+
|
|
1364
|
+
constructor(config: ScrollContainerConfig);
|
|
1365
|
+
setContent(content: Container): void;
|
|
1366
|
+
scrollTo(x: number, y: number, animate?: boolean): void;
|
|
1367
|
+
scrollToItem(index: number): void;
|
|
1368
|
+
resize(width: number, height: number): void;
|
|
1113
1369
|
destroy(): void;
|
|
1114
1370
|
}
|
|
1115
1371
|
```
|
|
1116
1372
|
|
|
1373
|
+
### SpriteAnimation
|
|
1374
|
+
|
|
1375
|
+
```typescript
|
|
1376
|
+
class SpriteAnimation {
|
|
1377
|
+
static create(textures: Texture[], config?: SpriteAnimationConfig): AnimatedSprite;
|
|
1378
|
+
static fromSpritesheet(sheet: Spritesheet, prefix: string, config?: SpriteAnimationConfig): AnimatedSprite;
|
|
1379
|
+
static fromRange(sheet: Spritesheet, pattern: string, start: number, end: number, config?: SpriteAnimationConfig): AnimatedSprite;
|
|
1380
|
+
static fromAliases(aliases: string[], config?: SpriteAnimationConfig): AnimatedSprite;
|
|
1381
|
+
static playOnce(textures: Texture[], config?: SpriteAnimationConfig): { sprite: AnimatedSprite; finished: Promise<void> };
|
|
1382
|
+
static getTexturesByPrefix(sheet: Spritesheet, prefix: string): Texture[];
|
|
1383
|
+
}
|
|
1384
|
+
```
|
|
1385
|
+
|
|
1117
1386
|
### EventEmitter
|
|
1118
1387
|
|
|
1119
1388
|
```typescript
|
|
@@ -1121,7 +1390,8 @@ class EventEmitter<TEvents extends {}> {
|
|
|
1121
1390
|
on<K>(event: K, handler: (data: TEvents[K]) => void): this;
|
|
1122
1391
|
once<K>(event: K, handler: (data: TEvents[K]) => void): this;
|
|
1123
1392
|
off<K>(event: K, handler: (data: TEvents[K]) => void): this;
|
|
1124
|
-
|
|
1393
|
+
// Void events can be emitted without a data argument
|
|
1394
|
+
emit<K>(event: K, ...args): void;
|
|
1125
1395
|
removeAllListeners(event?: keyof TEvents): this;
|
|
1126
1396
|
}
|
|
1127
1397
|
```
|