@energy8platform/game-engine 0.20.0 → 0.22.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 +121 -0
- package/dist/animation.cjs.js +18 -3
- package/dist/animation.cjs.js.map +1 -1
- package/dist/animation.esm.js +18 -3
- package/dist/animation.esm.js.map +1 -1
- package/dist/core.cjs.js +18 -3
- package/dist/core.cjs.js.map +1 -1
- package/dist/core.esm.js +18 -3
- package/dist/core.esm.js.map +1 -1
- package/dist/host.cjs.js +18 -3
- package/dist/host.cjs.js.map +1 -1
- package/dist/host.d.ts +3 -5
- package/dist/host.esm.js +18 -3
- package/dist/host.esm.js.map +1 -1
- package/dist/index.cjs.js +18 -2535
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.d.ts +3 -1020
- package/dist/index.esm.js +20 -2525
- package/dist/index.esm.js.map +1 -1
- package/dist/slot.cjs.js +1872 -61
- package/dist/slot.cjs.js.map +1 -1
- package/dist/slot.d.ts +555 -28
- package/dist/slot.esm.js +1857 -62
- package/dist/slot.esm.js.map +1 -1
- package/dist/vite.cjs.js +0 -5
- package/dist/vite.cjs.js.map +1 -1
- package/dist/vite.esm.js +0 -5
- package/dist/vite.esm.js.map +1 -1
- package/package.json +2 -35
- package/src/animation/Tween.ts +14 -3
- package/src/host/index.ts +0 -1
- package/src/host/types.ts +0 -3
- package/src/index.ts +0 -28
- package/src/slot/anim/easing-map.ts +16 -2
- package/src/slot/cascade/TumbleController.ts +230 -0
- package/src/slot/config/ReelSystemConfig.ts +559 -0
- package/src/slot/config/presets.ts +222 -0
- package/src/slot/features/extra.ts +189 -0
- package/src/slot/features/index.ts +44 -0
- package/src/slot/features/symbols.ts +183 -0
- package/src/slot/features/types.ts +136 -0
- package/src/slot/features/wilds.ts +151 -0
- package/src/slot/grid/ReelGrid.ts +93 -24
- package/src/slot/grid/SymbolCell.ts +45 -11
- package/src/slot/index.ts +61 -2
- package/src/slot/motion/AnticipationController.ts +96 -0
- package/src/slot/motion/SpinEngine.ts +384 -0
- package/src/slot/system/ReelSystem.ts +295 -0
- package/src/vite/index.ts +0 -5
- package/dist/react-jsx.cjs.js +0 -3
- package/dist/react-jsx.cjs.js.map +0 -1
- package/dist/react-jsx.d.ts +0 -602
- package/dist/react-jsx.esm.js +0 -2
- package/dist/react-jsx.esm.js.map +0 -1
- package/dist/react.cjs.js +0 -3787
- package/dist/react.cjs.js.map +0 -1
- package/dist/react.d.ts +0 -1467
- package/dist/react.esm.js +0 -3771
- package/dist/react.esm.js.map +0 -1
- package/dist/ui.cjs.js +0 -2999
- package/dist/ui.cjs.js.map +0 -1
- package/dist/ui.d.ts +0 -1116
- package/dist/ui.esm.js +0 -2983
- package/dist/ui.esm.js.map +0 -1
- package/src/react/EngineContext.ts +0 -26
- package/src/react/ReactScene.ts +0 -88
- package/src/react/applyProps.ts +0 -271
- package/src/react/catalogue.ts +0 -17
- package/src/react/createPixiRoot.ts +0 -31
- package/src/react/extendAll.ts +0 -74
- package/src/react/hooks.ts +0 -46
- package/src/react/index.ts +0 -29
- package/src/react/jsx-runtime.ts +0 -346
- package/src/react/reconciler.ts +0 -338
- package/src/slot/freeSpins/FreeSpinsSession.ts +0 -40
- package/src/state/StateMachine.ts +0 -231
- package/src/state/index.ts +0 -1
- package/src/ui/BalanceDisplay.ts +0 -159
- package/src/ui/Button.ts +0 -304
- package/src/ui/FlexContainer.ts +0 -775
- package/src/ui/Label.ts +0 -124
- package/src/ui/LabelValue.ts +0 -122
- package/src/ui/Layout.ts +0 -291
- package/src/ui/Modal.ts +0 -170
- package/src/ui/Panel.ts +0 -204
- package/src/ui/ProgressBar.ts +0 -170
- package/src/ui/ScrollContainer.ts +0 -478
- package/src/ui/Slider.ts +0 -241
- package/src/ui/Toast.ts +0 -150
- package/src/ui/Toggle.ts +0 -201
- package/src/ui/WinDisplay.ts +0 -145
- package/src/ui/index.ts +0 -33
- package/src/ui/view.ts +0 -28
package/src/ui/Toast.ts
DELETED
|
@@ -1,150 +0,0 @@
|
|
|
1
|
-
import { Container, Graphics, Text } from 'pixi.js';
|
|
2
|
-
import { Tween } from '../animation/Tween';
|
|
3
|
-
import { Easing } from '../animation/Easing';
|
|
4
|
-
import { resolveView } from './view';
|
|
5
|
-
import type { ViewInput } from './view';
|
|
6
|
-
|
|
7
|
-
export type ToastType = 'info' | 'success' | 'warning' | 'error';
|
|
8
|
-
|
|
9
|
-
export interface ToastConfig {
|
|
10
|
-
/** Auto-dismiss after this many ms (0 = manual dismiss only) */
|
|
11
|
-
duration?: number;
|
|
12
|
-
/** Toast position from bottom */
|
|
13
|
-
bottomOffset?: number;
|
|
14
|
-
/** Custom background view (string texture name, Texture, or Container). Sized to fit text. */
|
|
15
|
-
backgroundView?: ViewInput;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
const TOAST_COLORS: Record<ToastType, number> = {
|
|
19
|
-
info: 0x3498db,
|
|
20
|
-
success: 0x27ae60,
|
|
21
|
-
warning: 0xf39c12,
|
|
22
|
-
error: 0xe74c3c,
|
|
23
|
-
};
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* Toast notification component for displaying transient messages.
|
|
27
|
-
*
|
|
28
|
-
* @example
|
|
29
|
-
* ```ts
|
|
30
|
-
* const toast = new Toast();
|
|
31
|
-
* scene.container.addChild(toast);
|
|
32
|
-
* await toast.show('Connection lost', 'error', 1920, 1080);
|
|
33
|
-
* ```
|
|
34
|
-
*/
|
|
35
|
-
export class Toast extends Container {
|
|
36
|
-
readonly __uiComponent = true as const;
|
|
37
|
-
|
|
38
|
-
private _bg: Container;
|
|
39
|
-
private _customBg: boolean;
|
|
40
|
-
private _text: Text;
|
|
41
|
-
private _config: Required<Pick<ToastConfig, 'duration' | 'bottomOffset'>>;
|
|
42
|
-
private _dismissPending = false;
|
|
43
|
-
|
|
44
|
-
constructor(config: ToastConfig = {}) {
|
|
45
|
-
super();
|
|
46
|
-
|
|
47
|
-
this._config = {
|
|
48
|
-
duration: config.duration ?? 3000,
|
|
49
|
-
bottomOffset: config.bottomOffset ?? 60,
|
|
50
|
-
};
|
|
51
|
-
|
|
52
|
-
const customBg = resolveView(config.backgroundView);
|
|
53
|
-
this._customBg = !!customBg;
|
|
54
|
-
this._bg = customBg ?? new Graphics();
|
|
55
|
-
this.addChild(this._bg);
|
|
56
|
-
|
|
57
|
-
this._text = new Text({
|
|
58
|
-
text: '',
|
|
59
|
-
style: {
|
|
60
|
-
fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif',
|
|
61
|
-
fontSize: 16,
|
|
62
|
-
fill: 0xffffff,
|
|
63
|
-
},
|
|
64
|
-
});
|
|
65
|
-
this._text.anchor.set(0.5);
|
|
66
|
-
this.addChild(this._text);
|
|
67
|
-
|
|
68
|
-
this.visible = false;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
/**
|
|
72
|
-
* Show a toast message.
|
|
73
|
-
*/
|
|
74
|
-
async show(
|
|
75
|
-
message: string,
|
|
76
|
-
type: ToastType = 'info',
|
|
77
|
-
viewWidth?: number,
|
|
78
|
-
viewHeight?: number,
|
|
79
|
-
): Promise<void> {
|
|
80
|
-
// Cancel any pending dismiss
|
|
81
|
-
Tween.killTweensOf(this);
|
|
82
|
-
this._dismissPending = false;
|
|
83
|
-
|
|
84
|
-
this._text.text = message;
|
|
85
|
-
|
|
86
|
-
const padding = 20;
|
|
87
|
-
const width = Math.max(200, this._text.width + padding * 2);
|
|
88
|
-
const height = 44;
|
|
89
|
-
const radius = 8;
|
|
90
|
-
|
|
91
|
-
// Draw the background
|
|
92
|
-
if (this._customBg) {
|
|
93
|
-
this._bg.width = width;
|
|
94
|
-
this._bg.height = height;
|
|
95
|
-
this._bg.x = -width / 2;
|
|
96
|
-
this._bg.y = -height / 2;
|
|
97
|
-
} else {
|
|
98
|
-
const g = this._bg as Graphics;
|
|
99
|
-
g.clear();
|
|
100
|
-
g.roundRect(-width / 2, -height / 2, width, height, radius);
|
|
101
|
-
g.fill(TOAST_COLORS[type]);
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
// Position
|
|
105
|
-
if (viewWidth && viewHeight) {
|
|
106
|
-
this.x = viewWidth / 2;
|
|
107
|
-
this.y = viewHeight - this._config.bottomOffset;
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
this.visible = true;
|
|
111
|
-
this.alpha = 0;
|
|
112
|
-
this.y += 20;
|
|
113
|
-
|
|
114
|
-
await Tween.to(this, { alpha: 1, y: this.y - 20 }, 300, Easing.easeOutCubic);
|
|
115
|
-
|
|
116
|
-
if (this._config.duration > 0) {
|
|
117
|
-
this._dismissPending = true;
|
|
118
|
-
await Tween.delay(this._config.duration);
|
|
119
|
-
if (this._dismissPending) {
|
|
120
|
-
this._dismissPending = false;
|
|
121
|
-
await this.dismiss();
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
/**
|
|
127
|
-
* Dismiss the toast.
|
|
128
|
-
*/
|
|
129
|
-
async dismiss(): Promise<void> {
|
|
130
|
-
if (!this.visible) return;
|
|
131
|
-
|
|
132
|
-
this._dismissPending = false;
|
|
133
|
-
Tween.killTweensOf(this);
|
|
134
|
-
|
|
135
|
-
await Tween.to(this, { alpha: 0, y: this.y + 20 }, 200, Easing.easeInCubic);
|
|
136
|
-
this.visible = false;
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
/** React reconciler update hook */
|
|
140
|
-
updateConfig(changed: Record<string, any>): void {
|
|
141
|
-
if ('duration' in changed) this._config.duration = changed.duration;
|
|
142
|
-
if ('bottomOffset' in changed) this._config.bottomOffset = changed.bottomOffset;
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
override destroy(options?: boolean | { children?: boolean; texture?: boolean; textureSource?: boolean }): void {
|
|
146
|
-
this._dismissPending = false;
|
|
147
|
-
Tween.killTweensOf(this);
|
|
148
|
-
super.destroy(options);
|
|
149
|
-
}
|
|
150
|
-
}
|
package/src/ui/Toggle.ts
DELETED
|
@@ -1,201 +0,0 @@
|
|
|
1
|
-
import { Container, Graphics } from 'pixi.js';
|
|
2
|
-
import { Tween } from '../animation/Tween';
|
|
3
|
-
import { resolveView } from './view';
|
|
4
|
-
import type { ViewInput } from './view';
|
|
5
|
-
|
|
6
|
-
export interface ToggleConfig {
|
|
7
|
-
/** Initial state (default: false) */
|
|
8
|
-
value?: boolean;
|
|
9
|
-
/** Custom view for the ON state */
|
|
10
|
-
onView?: ViewInput;
|
|
11
|
-
/** Custom view for the OFF state */
|
|
12
|
-
offView?: ViewInput;
|
|
13
|
-
/** Width (for Graphics-based toggle, default: 52) */
|
|
14
|
-
width?: number;
|
|
15
|
-
/** Height (for Graphics-based toggle, default: 28) */
|
|
16
|
-
height?: number;
|
|
17
|
-
/** Track color when ON (ignored when custom views provided) */
|
|
18
|
-
onColor?: number;
|
|
19
|
-
/** Track color when OFF (ignored when custom views provided) */
|
|
20
|
-
offColor?: number;
|
|
21
|
-
/** Handle color (for Graphics-based toggle) */
|
|
22
|
-
handleColor?: number;
|
|
23
|
-
/** Handle radius (for Graphics-based toggle, default: auto) */
|
|
24
|
-
handleRadius?: number;
|
|
25
|
-
/** Animation duration in ms (default: 200) */
|
|
26
|
-
animationDuration?: number;
|
|
27
|
-
|
|
28
|
-
/** Called when value changes */
|
|
29
|
-
onChange?: (value: boolean) => void;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* Toggle switch with two states.
|
|
34
|
-
*
|
|
35
|
-
* Supports custom ON/OFF views or auto-generated Graphics-based toggle.
|
|
36
|
-
* Click to toggle, or use `forceSwitch(value)` programmatically.
|
|
37
|
-
*
|
|
38
|
-
* @example
|
|
39
|
-
* ```ts
|
|
40
|
-
* const mute = new Toggle({
|
|
41
|
-
* value: false,
|
|
42
|
-
* onColor: 0x22cc22,
|
|
43
|
-
* onChange: (on) => audioManager.mute(!on),
|
|
44
|
-
* });
|
|
45
|
-
* ```
|
|
46
|
-
*/
|
|
47
|
-
export class Toggle extends Container {
|
|
48
|
-
readonly __uiComponent = true as const;
|
|
49
|
-
|
|
50
|
-
private _value: boolean;
|
|
51
|
-
private _onView: Container | null = null;
|
|
52
|
-
private _offView: Container | null = null;
|
|
53
|
-
private _handle: Container | null = null;
|
|
54
|
-
private _trackGfx: Graphics | null = null;
|
|
55
|
-
private _config: Required<Pick<ToggleConfig, 'width' | 'height' | 'onColor' | 'offColor' | 'handleColor' | 'handleRadius' | 'animationDuration'>>;
|
|
56
|
-
private _useCustomViews: boolean;
|
|
57
|
-
|
|
58
|
-
onChange: ((value: boolean) => void) | null = null;
|
|
59
|
-
|
|
60
|
-
constructor(config: ToggleConfig = {}) {
|
|
61
|
-
super();
|
|
62
|
-
|
|
63
|
-
this._config = {
|
|
64
|
-
width: config.width ?? 52,
|
|
65
|
-
height: config.height ?? 28,
|
|
66
|
-
onColor: config.onColor ?? 0x22cc22,
|
|
67
|
-
offColor: config.offColor ?? 0x666666,
|
|
68
|
-
handleColor: config.handleColor ?? 0xffffff,
|
|
69
|
-
handleRadius: config.handleRadius ?? 0, // 0 = auto
|
|
70
|
-
animationDuration: config.animationDuration ?? 200,
|
|
71
|
-
};
|
|
72
|
-
|
|
73
|
-
this._value = config.value ?? false;
|
|
74
|
-
this.onChange = config.onChange ?? null;
|
|
75
|
-
|
|
76
|
-
const customOn = resolveView(config.onView);
|
|
77
|
-
const customOff = resolveView(config.offView);
|
|
78
|
-
this._useCustomViews = !!(customOn || customOff);
|
|
79
|
-
|
|
80
|
-
if (this._useCustomViews) {
|
|
81
|
-
// Custom view mode: show/hide ON and OFF views
|
|
82
|
-
if (customOn) {
|
|
83
|
-
this._onView = customOn;
|
|
84
|
-
this._onView.visible = this._value;
|
|
85
|
-
this.addChild(this._onView);
|
|
86
|
-
}
|
|
87
|
-
if (customOff) {
|
|
88
|
-
this._offView = customOff;
|
|
89
|
-
this._offView.visible = !this._value;
|
|
90
|
-
this.addChild(this._offView);
|
|
91
|
-
}
|
|
92
|
-
} else {
|
|
93
|
-
// Graphics mode: track + sliding handle
|
|
94
|
-
const { width, height, handleColor } = this._config;
|
|
95
|
-
const handleRadius = this._config.handleRadius || (height / 2 - 3);
|
|
96
|
-
this._config.handleRadius = handleRadius;
|
|
97
|
-
|
|
98
|
-
this._trackGfx = new Graphics();
|
|
99
|
-
this.addChild(this._trackGfx);
|
|
100
|
-
this._drawTrack();
|
|
101
|
-
|
|
102
|
-
const handle = new Graphics();
|
|
103
|
-
handle.circle(0, 0, handleRadius).fill(handleColor);
|
|
104
|
-
handle.y = height / 2;
|
|
105
|
-
handle.x = this._value ? width - handleRadius - 3 : handleRadius + 3;
|
|
106
|
-
this._handle = handle;
|
|
107
|
-
this.addChild(handle);
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
// Interaction
|
|
111
|
-
this.eventMode = 'static';
|
|
112
|
-
this.cursor = 'pointer';
|
|
113
|
-
this.on('pointertap', this._onTap, this);
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
/** Current toggle state */
|
|
117
|
-
get value(): boolean {
|
|
118
|
-
return this._value;
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
set value(v: boolean) {
|
|
122
|
-
if (v === this._value) return;
|
|
123
|
-
this.forceSwitch(v);
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
/** Programmatically switch to a specific state with animation */
|
|
127
|
-
forceSwitch(value: boolean): void {
|
|
128
|
-
this._value = value;
|
|
129
|
-
this._animateToState();
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
/** React reconciler update hook */
|
|
133
|
-
updateConfig(changed: Record<string, any>): void {
|
|
134
|
-
if ('value' in changed) this.value = changed.value;
|
|
135
|
-
if ('onChange' in changed) this.onChange = changed.onChange;
|
|
136
|
-
if ('animationDuration' in changed) this._config.animationDuration = changed.animationDuration;
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
private _onTap(): void {
|
|
140
|
-
this._value = !this._value;
|
|
141
|
-
this._animateToState();
|
|
142
|
-
this.onChange?.(this._value);
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
private _animateToState(): void {
|
|
146
|
-
const duration = this._config.animationDuration;
|
|
147
|
-
|
|
148
|
-
if (this._useCustomViews) {
|
|
149
|
-
// Custom views: crossfade
|
|
150
|
-
if (this._onView) {
|
|
151
|
-
Tween.killTweensOf(this._onView);
|
|
152
|
-
if (this._value) {
|
|
153
|
-
this._onView.visible = true;
|
|
154
|
-
Tween.to(this._onView, { alpha: 1 }, duration);
|
|
155
|
-
} else {
|
|
156
|
-
Tween.to(this._onView, { alpha: 0 }, duration).then(() => {
|
|
157
|
-
if (this._onView) this._onView.visible = false;
|
|
158
|
-
});
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
if (this._offView) {
|
|
162
|
-
Tween.killTweensOf(this._offView);
|
|
163
|
-
if (!this._value) {
|
|
164
|
-
this._offView.visible = true;
|
|
165
|
-
Tween.to(this._offView, { alpha: 1 }, duration);
|
|
166
|
-
} else {
|
|
167
|
-
Tween.to(this._offView, { alpha: 0 }, duration).then(() => {
|
|
168
|
-
if (this._offView) this._offView.visible = false;
|
|
169
|
-
});
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
} else {
|
|
173
|
-
// Graphics mode: slide handle + recolor track
|
|
174
|
-
this._drawTrack();
|
|
175
|
-
if (this._handle) {
|
|
176
|
-
const { width } = this._config;
|
|
177
|
-
const handleRadius = this._config.handleRadius;
|
|
178
|
-
const targetX = this._value ? width - handleRadius - 3 : handleRadius + 3;
|
|
179
|
-
Tween.killTweensOf(this._handle);
|
|
180
|
-
Tween.to(this._handle, { x: targetX }, duration);
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
private _drawTrack(): void {
|
|
186
|
-
if (!this._trackGfx) return;
|
|
187
|
-
const { width, height, onColor, offColor } = this._config;
|
|
188
|
-
const radius = height / 2;
|
|
189
|
-
this._trackGfx.clear();
|
|
190
|
-
this._trackGfx.roundRect(0, 0, width, height, radius).fill(this._value ? onColor : offColor);
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
override destroy(options?: boolean | { children?: boolean; texture?: boolean; textureSource?: boolean }): void {
|
|
194
|
-
this.off('pointertap', this._onTap, this);
|
|
195
|
-
if (this._handle) Tween.killTweensOf(this._handle);
|
|
196
|
-
if (this._onView) Tween.killTweensOf(this._onView);
|
|
197
|
-
if (this._offView) Tween.killTweensOf(this._offView);
|
|
198
|
-
this.onChange = null;
|
|
199
|
-
super.destroy(options);
|
|
200
|
-
}
|
|
201
|
-
}
|
package/src/ui/WinDisplay.ts
DELETED
|
@@ -1,145 +0,0 @@
|
|
|
1
|
-
import { Container } from 'pixi.js';
|
|
2
|
-
import { Label } from './Label';
|
|
3
|
-
import { Tween } from '../animation/Tween';
|
|
4
|
-
import { Easing } from '../animation/Easing';
|
|
5
|
-
|
|
6
|
-
export interface WinDisplayConfig {
|
|
7
|
-
/** Text style overrides */
|
|
8
|
-
style?: Record<string, unknown>;
|
|
9
|
-
/** Currency code */
|
|
10
|
-
currency?: string;
|
|
11
|
-
/** Locale for number formatting */
|
|
12
|
-
locale?: string;
|
|
13
|
-
/** Countup duration in ms */
|
|
14
|
-
countupDuration?: number;
|
|
15
|
-
/** Scale pop animation on win */
|
|
16
|
-
popScale?: number;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* Win amount display with countup animation.
|
|
21
|
-
*
|
|
22
|
-
* Shows a dramatic countup from 0 to the win amount, with optional
|
|
23
|
-
* scale pop effect — typical of slot games. Uses engine Tween system.
|
|
24
|
-
*
|
|
25
|
-
* @example
|
|
26
|
-
* ```ts
|
|
27
|
-
* const winDisplay = new WinDisplay({ currency: 'USD' });
|
|
28
|
-
* scene.container.addChild(winDisplay);
|
|
29
|
-
* await winDisplay.showWin(150.50); // countup animation
|
|
30
|
-
* winDisplay.hide();
|
|
31
|
-
* ```
|
|
32
|
-
*/
|
|
33
|
-
export class WinDisplay extends Container {
|
|
34
|
-
readonly __uiComponent = true as const;
|
|
35
|
-
|
|
36
|
-
private _label: Label;
|
|
37
|
-
private _config: Required<Pick<WinDisplayConfig, 'currency' | 'locale' | 'countupDuration' | 'popScale'>>;
|
|
38
|
-
/** Internal target for Tween countup */
|
|
39
|
-
private _tweenTarget = { value: 0 };
|
|
40
|
-
|
|
41
|
-
constructor(config: WinDisplayConfig = {}) {
|
|
42
|
-
super();
|
|
43
|
-
|
|
44
|
-
this._config = {
|
|
45
|
-
currency: config.currency ?? 'USD',
|
|
46
|
-
locale: config.locale ?? 'en-US',
|
|
47
|
-
countupDuration: config.countupDuration ?? 1500,
|
|
48
|
-
popScale: config.popScale ?? 1.2,
|
|
49
|
-
};
|
|
50
|
-
|
|
51
|
-
this._label = new Label({
|
|
52
|
-
text: '',
|
|
53
|
-
style: {
|
|
54
|
-
fontSize: 48,
|
|
55
|
-
fontWeight: 'bold',
|
|
56
|
-
fill: 0xffd700,
|
|
57
|
-
stroke: { color: 0x000000, width: 3 },
|
|
58
|
-
...(config.style as any),
|
|
59
|
-
},
|
|
60
|
-
});
|
|
61
|
-
this.addChild(this._label);
|
|
62
|
-
|
|
63
|
-
this.visible = false;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
/**
|
|
67
|
-
* Show a win with countup animation.
|
|
68
|
-
*
|
|
69
|
-
* @param amount - Win amount
|
|
70
|
-
* @returns Promise that resolves when the animation completes
|
|
71
|
-
*/
|
|
72
|
-
async showWin(amount: number): Promise<void> {
|
|
73
|
-
this.visible = true;
|
|
74
|
-
this.alpha = 1;
|
|
75
|
-
|
|
76
|
-
// Cancel any running animation
|
|
77
|
-
Tween.killTweensOf(this._tweenTarget);
|
|
78
|
-
Tween.killTweensOf(this);
|
|
79
|
-
|
|
80
|
-
// Setup countup
|
|
81
|
-
this._tweenTarget.value = 0;
|
|
82
|
-
this.scale.set(0.5);
|
|
83
|
-
|
|
84
|
-
// Scale pop animation
|
|
85
|
-
const scalePromise = Tween.to(
|
|
86
|
-
this,
|
|
87
|
-
{ 'scale.x': 1, 'scale.y': 1 },
|
|
88
|
-
300,
|
|
89
|
-
Easing.easeOutBack,
|
|
90
|
-
);
|
|
91
|
-
|
|
92
|
-
// Countup animation
|
|
93
|
-
const countupPromise = Tween.to(
|
|
94
|
-
this._tweenTarget,
|
|
95
|
-
{ value: amount },
|
|
96
|
-
this._config.countupDuration,
|
|
97
|
-
Easing.easeOutCubic,
|
|
98
|
-
() => {
|
|
99
|
-
this.displayAmount(this._tweenTarget.value);
|
|
100
|
-
},
|
|
101
|
-
);
|
|
102
|
-
|
|
103
|
-
await Promise.all([scalePromise, countupPromise]);
|
|
104
|
-
|
|
105
|
-
// Ensure final value is exact
|
|
106
|
-
this.displayAmount(amount);
|
|
107
|
-
this.scale.set(1);
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
/**
|
|
111
|
-
* Skip the countup animation and show the final amount immediately.
|
|
112
|
-
*/
|
|
113
|
-
skipCountup(amount: number): void {
|
|
114
|
-
Tween.killTweensOf(this._tweenTarget);
|
|
115
|
-
Tween.killTweensOf(this);
|
|
116
|
-
this.displayAmount(amount);
|
|
117
|
-
this.scale.set(1);
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
/**
|
|
121
|
-
* Hide the win display.
|
|
122
|
-
*/
|
|
123
|
-
hide(): void {
|
|
124
|
-
Tween.killTweensOf(this._tweenTarget);
|
|
125
|
-
Tween.killTweensOf(this);
|
|
126
|
-
this.visible = false;
|
|
127
|
-
this._label.text = '';
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
private displayAmount(amount: number): void {
|
|
131
|
-
this._label.setCurrency(amount, this._config.currency, this._config.locale);
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
/** React reconciler update hook */
|
|
135
|
-
updateConfig(changed: Record<string, any>): void {
|
|
136
|
-
if ('currency' in changed) this._config.currency = changed.currency;
|
|
137
|
-
if ('locale' in changed) this._config.locale = changed.locale;
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
override destroy(options?: boolean | { children?: boolean; texture?: boolean; textureSource?: boolean }): void {
|
|
141
|
-
Tween.killTweensOf(this._tweenTarget);
|
|
142
|
-
Tween.killTweensOf(this);
|
|
143
|
-
super.destroy(options);
|
|
144
|
-
}
|
|
145
|
-
}
|
package/src/ui/index.ts
DELETED
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
// ─── View helpers ─────────────────────────────────────────
|
|
2
|
-
export { resolveView } from './view';
|
|
3
|
-
export type { ViewInput } from './view';
|
|
4
|
-
|
|
5
|
-
// ─── Engine UI Components ─────────────────────────────────
|
|
6
|
-
export { FlexContainer } from './FlexContainer';
|
|
7
|
-
export type { FlexContainerConfig, FlexDirection, JustifyContent, AlignItems, AlignSelf, AlignContent, FlexItemConfig } from './FlexContainer';
|
|
8
|
-
export { Button } from './Button';
|
|
9
|
-
export type { ButtonConfig, ButtonState } from './Button';
|
|
10
|
-
export { ProgressBar } from './ProgressBar';
|
|
11
|
-
export type { ProgressBarConfig } from './ProgressBar';
|
|
12
|
-
export { Label } from './Label';
|
|
13
|
-
export type { LabelConfig } from './Label';
|
|
14
|
-
export { LabelValue } from './LabelValue';
|
|
15
|
-
export type { LabelValueConfig, LabelValueAlign } from './LabelValue';
|
|
16
|
-
export { Panel } from './Panel';
|
|
17
|
-
export type { PanelConfig } from './Panel';
|
|
18
|
-
export { BalanceDisplay } from './BalanceDisplay';
|
|
19
|
-
export type { BalanceDisplayConfig } from './BalanceDisplay';
|
|
20
|
-
export { WinDisplay } from './WinDisplay';
|
|
21
|
-
export type { WinDisplayConfig } from './WinDisplay';
|
|
22
|
-
export { Modal } from './Modal';
|
|
23
|
-
export type { ModalConfig } from './Modal';
|
|
24
|
-
export { Toast } from './Toast';
|
|
25
|
-
export type { ToastConfig, ToastType } from './Toast';
|
|
26
|
-
export { Layout } from './Layout';
|
|
27
|
-
export type { LayoutConfig, LayoutDirection, LayoutAlignment, LayoutAnchor } from './Layout';
|
|
28
|
-
export { ScrollContainer } from './ScrollContainer';
|
|
29
|
-
export type { ScrollContainerConfig, ScrollDirection } from './ScrollContainer';
|
|
30
|
-
export { Slider } from './Slider';
|
|
31
|
-
export type { SliderConfig } from './Slider';
|
|
32
|
-
export { Toggle } from './Toggle';
|
|
33
|
-
export type { ToggleConfig } from './Toggle';
|
package/src/ui/view.ts
DELETED
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
import { Container, Sprite, Texture } from 'pixi.js';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Universal view input type for UI component visual slots.
|
|
5
|
-
*
|
|
6
|
-
* - `string` — texture name, resolved via `Sprite.from()`
|
|
7
|
-
* - `Texture` — wrapped in a `Sprite`
|
|
8
|
-
* - `Container` — used as-is (Sprite, Graphics, NineSliceSprite, AnimatedSprite, custom...)
|
|
9
|
-
*/
|
|
10
|
-
export type ViewInput = string | Texture | Container;
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* Resolve a ViewInput to a Container instance.
|
|
14
|
-
*
|
|
15
|
-
* @example
|
|
16
|
-
* ```ts
|
|
17
|
-
* resolveView('btn-idle') // → Sprite.from('btn-idle')
|
|
18
|
-
* resolveView(someTexture) // → new Sprite(someTexture)
|
|
19
|
-
* resolveView(myCustomContainer) // → myCustomContainer (as-is)
|
|
20
|
-
* resolveView(undefined) // → null
|
|
21
|
-
* ```
|
|
22
|
-
*/
|
|
23
|
-
export function resolveView(input: ViewInput | undefined | null): Container | null {
|
|
24
|
-
if (input == null) return null;
|
|
25
|
-
if (typeof input === 'string') return Sprite.from(input);
|
|
26
|
-
if (input instanceof Texture) return new Sprite(input);
|
|
27
|
-
return input;
|
|
28
|
-
}
|