@energy8platform/game-engine 0.5.0 → 0.6.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 +220 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -36,6 +36,8 @@ A universal casino game engine built on [PixiJS v8](https://pixijs.com/) and [@e
|
|
|
36
36
|
- [Vite Configuration](#vite-configuration)
|
|
37
37
|
- [DevBridge](#devbridge)
|
|
38
38
|
- [Debug](#debug)
|
|
39
|
+
- [Flexbox-First Layout](#flexbox-first-layout)
|
|
40
|
+
- [Using with React (`@pixi/react`)](#using-with-react-pixireact)
|
|
39
41
|
- [API Reference](#api-reference)
|
|
40
42
|
- [License](#license)
|
|
41
43
|
|
|
@@ -54,6 +56,9 @@ npm install pixi.js @energy8platform/game-sdk @energy8platform/game-engine
|
|
|
54
56
|
# Install UI layout dependencies (optional — needed for Layout, Panel, ScrollContainer)
|
|
55
57
|
npm install @pixi/ui @pixi/layout yoga-layout
|
|
56
58
|
|
|
59
|
+
# (Optional) React integration
|
|
60
|
+
npm install @pixi/react react react-dom
|
|
61
|
+
|
|
57
62
|
# (Optional) install spine and audio support
|
|
58
63
|
npm install @pixi/sound @esotericsoftware/spine-pixi-v8
|
|
59
64
|
```
|
|
@@ -128,6 +133,7 @@ bootstrap();
|
|
|
128
133
|
| `yoga-layout` | `^3.0.0` | Optional — peer dep of `@pixi/layout` |
|
|
129
134
|
| `@pixi/sound` | `^6.0.0` | Optional — for audio |
|
|
130
135
|
| `@esotericsoftware/spine-pixi-v8` | `~4.2.0` | Optional — for Spine animations |
|
|
136
|
+
| `@pixi/react` | `^8.0.0` | Optional — for React integration (see [Using with React](#using-with-react-pixireact)) |
|
|
131
137
|
|
|
132
138
|
### Sub-path Exports
|
|
133
139
|
|
|
@@ -1067,6 +1073,220 @@ row.addChild(volumeSlider, muteCheck);
|
|
|
1067
1073
|
|
|
1068
1074
|
---
|
|
1069
1075
|
|
|
1076
|
+
## Flexbox-First Layout
|
|
1077
|
+
|
|
1078
|
+
> **Best practice:** Use `@pixi/layout` flexbox instead of manual pixel positioning. Flexbox adapts to screen sizes, handles RTL, and eliminates fragile `x = width / 2 - 100` math.
|
|
1079
|
+
|
|
1080
|
+
### ❌ Avoid: Manual Pixel Positioning
|
|
1081
|
+
|
|
1082
|
+
```typescript
|
|
1083
|
+
// Fragile — breaks when screen size, text length, or element sizes change
|
|
1084
|
+
onResize(width: number, height: number) {
|
|
1085
|
+
this.title.x = width / 2;
|
|
1086
|
+
this.title.y = 80;
|
|
1087
|
+
this.balance.x = width / 2;
|
|
1088
|
+
this.balance.y = 220;
|
|
1089
|
+
this.spinButton.x = width / 2;
|
|
1090
|
+
this.spinButton.y = height - 120;
|
|
1091
|
+
}
|
|
1092
|
+
```
|
|
1093
|
+
|
|
1094
|
+
### ✅ Prefer: Flexbox Layout
|
|
1095
|
+
|
|
1096
|
+
```typescript
|
|
1097
|
+
import { Layout } from '@energy8platform/game-engine/ui';
|
|
1098
|
+
import { LayoutContainer } from '@pixi/layout/components';
|
|
1099
|
+
import type { LayoutStyles } from '@pixi/layout';
|
|
1100
|
+
|
|
1101
|
+
// Root layout — fills the screen, stacks children vertically
|
|
1102
|
+
const root = new LayoutContainer();
|
|
1103
|
+
root.layout = {
|
|
1104
|
+
width: '100%',
|
|
1105
|
+
height: '100%',
|
|
1106
|
+
flexDirection: 'column',
|
|
1107
|
+
alignItems: 'center',
|
|
1108
|
+
justifyContent: 'space-between',
|
|
1109
|
+
padding: 40,
|
|
1110
|
+
} satisfies LayoutStyles;
|
|
1111
|
+
|
|
1112
|
+
// Header area
|
|
1113
|
+
const header = new LayoutContainer();
|
|
1114
|
+
header.layout = {
|
|
1115
|
+
flexDirection: 'column',
|
|
1116
|
+
alignItems: 'center',
|
|
1117
|
+
gap: 12,
|
|
1118
|
+
};
|
|
1119
|
+
header.addChild(title, subtitle, balance);
|
|
1120
|
+
|
|
1121
|
+
// Center area — expands to fill available space
|
|
1122
|
+
const center = new LayoutContainer();
|
|
1123
|
+
center.layout = {
|
|
1124
|
+
flexGrow: 1,
|
|
1125
|
+
alignItems: 'center',
|
|
1126
|
+
justifyContent: 'center',
|
|
1127
|
+
};
|
|
1128
|
+
center.addChild(winDisplay);
|
|
1129
|
+
|
|
1130
|
+
// Footer toolbar
|
|
1131
|
+
const footer = new Layout({
|
|
1132
|
+
direction: 'horizontal',
|
|
1133
|
+
gap: 20,
|
|
1134
|
+
alignment: 'center',
|
|
1135
|
+
});
|
|
1136
|
+
footer.addItem(betLabel);
|
|
1137
|
+
footer.addItem(spinButton);
|
|
1138
|
+
|
|
1139
|
+
root.addChild(header, center, footer);
|
|
1140
|
+
scene.container.addChild(root);
|
|
1141
|
+
```
|
|
1142
|
+
|
|
1143
|
+
### When to Use Each Approach
|
|
1144
|
+
|
|
1145
|
+
| Approach | Use When |
|
|
1146
|
+
|---|---|
|
|
1147
|
+
| Engine `Layout` | Toolbar-style rows/columns with anchor positioning and breakpoints |
|
|
1148
|
+
| `LayoutContainer` (raw) | Full flexbox control — `flexGrow`, `justifyContent`, percentage sizes |
|
|
1149
|
+
| `container.layout = { ... }` (mixin) | Adding flex styles to any existing PixiJS container |
|
|
1150
|
+
| Manual pixel positioning | Exact artistic placement (e.g. particle emitters, spine anchors) |
|
|
1151
|
+
|
|
1152
|
+
### Nested Flexbox Example
|
|
1153
|
+
|
|
1154
|
+
```typescript
|
|
1155
|
+
// settings-panel.ts — responsive settings UI
|
|
1156
|
+
import { LayoutContainer } from '@pixi/layout/components';
|
|
1157
|
+
import { Slider, CheckBox } from '@pixi/ui';
|
|
1158
|
+
import { Panel, Label } from '@energy8platform/game-engine/ui';
|
|
1159
|
+
|
|
1160
|
+
const panel = new Panel({
|
|
1161
|
+
width: 500,
|
|
1162
|
+
height: 400,
|
|
1163
|
+
backgroundColor: 0x1a1a2e,
|
|
1164
|
+
borderRadius: 16,
|
|
1165
|
+
padding: 24,
|
|
1166
|
+
});
|
|
1167
|
+
|
|
1168
|
+
// Each row: label on left, control on right
|
|
1169
|
+
function settingsRow(labelText: string, control: Container): LayoutContainer {
|
|
1170
|
+
const row = new LayoutContainer();
|
|
1171
|
+
row.layout = {
|
|
1172
|
+
flexDirection: 'row',
|
|
1173
|
+
justifyContent: 'space-between',
|
|
1174
|
+
alignItems: 'center',
|
|
1175
|
+
width: '100%',
|
|
1176
|
+
height: 48,
|
|
1177
|
+
};
|
|
1178
|
+
row.addChild(new Label({ text: labelText }), control);
|
|
1179
|
+
return row;
|
|
1180
|
+
}
|
|
1181
|
+
|
|
1182
|
+
panel.content.addChild(
|
|
1183
|
+
settingsRow('Music Volume', musicSlider),
|
|
1184
|
+
settingsRow('SFX Volume', sfxSlider),
|
|
1185
|
+
settingsRow('Mute', muteCheckbox),
|
|
1186
|
+
);
|
|
1187
|
+
```
|
|
1188
|
+
|
|
1189
|
+
---
|
|
1190
|
+
|
|
1191
|
+
## Using with React (`@pixi/react`)
|
|
1192
|
+
|
|
1193
|
+
For React-based projects, [`@pixi/react`](https://github.com/pixijs/pixi-react) provides declarative JSX components for PixiJS. The engine is framework-agnostic — `@pixi/react` is **not** a dependency, but works seamlessly alongside it.
|
|
1194
|
+
|
|
1195
|
+
### Installation
|
|
1196
|
+
|
|
1197
|
+
```bash
|
|
1198
|
+
npm install @pixi/react react react-dom
|
|
1199
|
+
```
|
|
1200
|
+
|
|
1201
|
+
### Wrapping the Engine in React
|
|
1202
|
+
|
|
1203
|
+
```tsx
|
|
1204
|
+
import { Application, extend } from '@pixi/react';
|
|
1205
|
+
import { Container, Graphics, Text } from 'pixi.js';
|
|
1206
|
+
import { GameApplication, Scene } from '@energy8platform/game-engine';
|
|
1207
|
+
|
|
1208
|
+
// Register PixiJS components for JSX
|
|
1209
|
+
extend({ Container, Graphics, Text });
|
|
1210
|
+
|
|
1211
|
+
function GameWrapper() {
|
|
1212
|
+
return (
|
|
1213
|
+
<Application
|
|
1214
|
+
width={1920}
|
|
1215
|
+
height={1080}
|
|
1216
|
+
background={0x0f0f23}
|
|
1217
|
+
>
|
|
1218
|
+
<GameContent />
|
|
1219
|
+
</Application>
|
|
1220
|
+
);
|
|
1221
|
+
}
|
|
1222
|
+
```
|
|
1223
|
+
|
|
1224
|
+
### Using Engine Components in JSX
|
|
1225
|
+
|
|
1226
|
+
Engine components (`Button`, `Panel`, `Layout`, etc.) are PixiJS `Container` subclasses — use them with `@pixi/react`'s `extend`:
|
|
1227
|
+
|
|
1228
|
+
```tsx
|
|
1229
|
+
import { extend, useTick } from '@pixi/react';
|
|
1230
|
+
import { Button, Label, Panel, ProgressBar } from '@energy8platform/game-engine/ui';
|
|
1231
|
+
|
|
1232
|
+
// Register engine components for JSX
|
|
1233
|
+
extend({ Button, Label, Panel, ProgressBar });
|
|
1234
|
+
|
|
1235
|
+
function GameHUD({ balance, bet }: { balance: number; bet: number }) {
|
|
1236
|
+
return (
|
|
1237
|
+
<container>
|
|
1238
|
+
<panel
|
|
1239
|
+
width={400}
|
|
1240
|
+
height={80}
|
|
1241
|
+
backgroundColor={0x1a1a2e}
|
|
1242
|
+
borderRadius={12}
|
|
1243
|
+
padding={16}
|
|
1244
|
+
>
|
|
1245
|
+
<label text={`Balance: $${balance.toFixed(2)}`} />
|
|
1246
|
+
<label text={`Bet: $${bet.toFixed(2)}`} />
|
|
1247
|
+
</panel>
|
|
1248
|
+
</container>
|
|
1249
|
+
);
|
|
1250
|
+
}
|
|
1251
|
+
```
|
|
1252
|
+
|
|
1253
|
+
### Combining Flexbox with React
|
|
1254
|
+
|
|
1255
|
+
```tsx
|
|
1256
|
+
import { extend } from '@pixi/react';
|
|
1257
|
+
import { LayoutContainer } from '@pixi/layout/components';
|
|
1258
|
+
|
|
1259
|
+
extend({ LayoutContainer });
|
|
1260
|
+
|
|
1261
|
+
function FlexRow({ children }: { children: React.ReactNode }) {
|
|
1262
|
+
return (
|
|
1263
|
+
<layoutContainer
|
|
1264
|
+
layout={{
|
|
1265
|
+
flexDirection: 'row',
|
|
1266
|
+
gap: 16,
|
|
1267
|
+
alignItems: 'center',
|
|
1268
|
+
justifyContent: 'center',
|
|
1269
|
+
}}
|
|
1270
|
+
>
|
|
1271
|
+
{children}
|
|
1272
|
+
</layoutContainer>
|
|
1273
|
+
);
|
|
1274
|
+
}
|
|
1275
|
+
|
|
1276
|
+
function Toolbar() {
|
|
1277
|
+
return (
|
|
1278
|
+
<FlexRow>
|
|
1279
|
+
<button text="SPIN" width={180} height={60} />
|
|
1280
|
+
<label text="BET: $1.00" />
|
|
1281
|
+
</FlexRow>
|
|
1282
|
+
);
|
|
1283
|
+
}
|
|
1284
|
+
```
|
|
1285
|
+
|
|
1286
|
+
> **Note:** `@pixi/react` is entirely optional. The engine works without React. Choose whichever approach fits your team and project.
|
|
1287
|
+
|
|
1288
|
+
---
|
|
1289
|
+
|
|
1070
1290
|
## Input
|
|
1071
1291
|
|
|
1072
1292
|
`InputManager` provides unified touch/mouse/keyboard handling with gesture detection:
|