@zylem/game-lib 0.6.0 → 0.6.3
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 +9 -16
- package/dist/actions.d.ts +30 -21
- package/dist/actions.js +628 -145
- package/dist/actions.js.map +1 -1
- package/dist/behavior/platformer-3d.d.ts +296 -0
- package/dist/behavior/platformer-3d.js +518 -0
- package/dist/behavior/platformer-3d.js.map +1 -0
- package/dist/behavior/ricochet-2d.d.ts +274 -0
- package/dist/behavior/ricochet-2d.js +394 -0
- package/dist/behavior/ricochet-2d.js.map +1 -0
- package/dist/behavior/screen-wrap.d.ts +86 -0
- package/dist/behavior/screen-wrap.js +195 -0
- package/dist/behavior/screen-wrap.js.map +1 -0
- package/dist/behavior/thruster.d.ts +10 -0
- package/dist/behavior/thruster.js +234 -0
- package/dist/behavior/thruster.js.map +1 -0
- package/dist/behavior/world-boundary-2d.d.ts +141 -0
- package/dist/behavior/world-boundary-2d.js +181 -0
- package/dist/behavior/world-boundary-2d.js.map +1 -0
- package/dist/behavior-descriptor-BWNWmIjv.d.ts +142 -0
- package/dist/{blueprints-BOCc3Wve.d.ts → blueprints-BWGz8fII.d.ts} +2 -2
- package/dist/camera-B5e4c78l.d.ts +468 -0
- package/dist/camera.d.ts +3 -2
- package/dist/camera.js +962 -166
- package/dist/camera.js.map +1 -1
- package/dist/composition-DrzFrbqI.d.ts +218 -0
- package/dist/{core-CZhozNRH.d.ts → core-DAkskq6Y.d.ts} +97 -65
- package/dist/core.d.ts +12 -6
- package/dist/core.js +4449 -1052
- package/dist/core.js.map +1 -1
- package/dist/{entities-BAxfJOkk.d.ts → entities-DC9ce_vx.d.ts} +154 -45
- package/dist/entities.d.ts +5 -2
- package/dist/entities.js +2505 -722
- package/dist/entities.js.map +1 -1
- package/dist/entity-BpbZqg19.d.ts +1100 -0
- package/dist/entity-types-DAu8sGJH.d.ts +26 -0
- package/dist/global-change-Dc8uCKi2.d.ts +25 -0
- package/dist/main.d.ts +472 -29
- package/dist/main.js +11877 -6124
- package/dist/main.js.map +1 -1
- package/dist/{stage-types-CD21XoIU.d.ts → stage-types-BFsm3qsZ.d.ts} +255 -26
- package/dist/stage.d.ts +11 -6
- package/dist/stage.js +3462 -491
- package/dist/stage.js.map +1 -1
- package/dist/thruster-DhRaJnoL.d.ts +172 -0
- package/dist/world-Be5m1XC1.d.ts +31 -0
- package/package.json +21 -4
- package/dist/behaviors.d.ts +0 -106
- package/dist/behaviors.js +0 -398
- package/dist/behaviors.js.map +0 -1
- package/dist/camera-CpbDr4-V.d.ts +0 -116
- package/dist/entity-COvRtFNG.d.ts +0 -395
- package/dist/moveable-B_vyA6cw.d.ts +0 -67
- package/dist/transformable-CUhvyuYO.d.ts +0 -67
|
@@ -0,0 +1,1100 @@
|
|
|
1
|
+
import { Vector3, Vector2, Color, Material, BufferGeometry, Mesh, Group, ShaderMaterial } from 'three';
|
|
2
|
+
import { Vector3 as Vector3$1, RigidBodyDesc, ColliderDesc, RigidBody, Vector, Collider } from '@dimforge/rapier3d-compat';
|
|
3
|
+
import { IComponent } from 'bitecs';
|
|
4
|
+
import * as mitt from 'mitt';
|
|
5
|
+
import { b as BehaviorDescriptor, c as BehaviorHandle, d as BehaviorRef } from './behavior-descriptor-BWNWmIjv.js';
|
|
6
|
+
|
|
7
|
+
/** Input
|
|
8
|
+
*
|
|
9
|
+
* Maximum number of local players is 8.
|
|
10
|
+
* All input can be mapped to a gamepad or keyboard but shares the common
|
|
11
|
+
* interface represented as a gamepad.
|
|
12
|
+
*/
|
|
13
|
+
type InputPlayerNumber = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8;
|
|
14
|
+
type InputPlayer = `p${InputPlayerNumber}`;
|
|
15
|
+
interface ButtonState {
|
|
16
|
+
pressed: boolean;
|
|
17
|
+
released: boolean;
|
|
18
|
+
held: number;
|
|
19
|
+
}
|
|
20
|
+
interface AnalogState {
|
|
21
|
+
value: number;
|
|
22
|
+
held: number;
|
|
23
|
+
}
|
|
24
|
+
interface InputGamepad {
|
|
25
|
+
playerNumber: InputPlayerNumber;
|
|
26
|
+
buttons: {
|
|
27
|
+
A: ButtonState;
|
|
28
|
+
B: ButtonState;
|
|
29
|
+
X: ButtonState;
|
|
30
|
+
Y: ButtonState;
|
|
31
|
+
Start: ButtonState;
|
|
32
|
+
Select: ButtonState;
|
|
33
|
+
L: ButtonState;
|
|
34
|
+
R: ButtonState;
|
|
35
|
+
};
|
|
36
|
+
directions: {
|
|
37
|
+
Up: ButtonState;
|
|
38
|
+
Down: ButtonState;
|
|
39
|
+
Left: ButtonState;
|
|
40
|
+
Right: ButtonState;
|
|
41
|
+
};
|
|
42
|
+
shoulders: {
|
|
43
|
+
LTrigger: ButtonState;
|
|
44
|
+
RTrigger: ButtonState;
|
|
45
|
+
};
|
|
46
|
+
axes: {
|
|
47
|
+
Horizontal: AnalogState;
|
|
48
|
+
Vertical: AnalogState;
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
type Inputs = Record<InputPlayer, InputGamepad>;
|
|
52
|
+
interface InputProvider {
|
|
53
|
+
getInput(delta: number): Partial<InputGamepad>;
|
|
54
|
+
isConnected(): boolean;
|
|
55
|
+
getName(): string;
|
|
56
|
+
dispose?(): void;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
type LoadingEvent = {
|
|
60
|
+
type: 'start' | 'progress' | 'complete';
|
|
61
|
+
message?: string;
|
|
62
|
+
progress?: number;
|
|
63
|
+
total?: number;
|
|
64
|
+
current?: number;
|
|
65
|
+
};
|
|
66
|
+
interface IGame<TGlobals extends Record<string, unknown> = any> {
|
|
67
|
+
start: () => Promise<this>;
|
|
68
|
+
nextStage: () => void;
|
|
69
|
+
previousStage: () => void;
|
|
70
|
+
reset: () => Promise<void>;
|
|
71
|
+
pause: () => Promise<void>;
|
|
72
|
+
resume: () => Promise<void>;
|
|
73
|
+
onLoading: (callback: (event: LoadingEvent) => void) => void;
|
|
74
|
+
loadStageFromId: (stageId: string) => Promise<void>;
|
|
75
|
+
end: () => Promise<void>;
|
|
76
|
+
goToStage: () => void;
|
|
77
|
+
}
|
|
78
|
+
interface IStage {
|
|
79
|
+
onUpdate: (callback: UpdateFunction<IStage>) => void;
|
|
80
|
+
onSetup: (callback: SetupFunction<IStage>) => void;
|
|
81
|
+
onDestroy: (callback: DestroyFunction<IStage>) => void;
|
|
82
|
+
}
|
|
83
|
+
interface ICamera {
|
|
84
|
+
move: (position: Vector3) => void;
|
|
85
|
+
rotate: (pitch: number, yaw: number, roll: number) => void;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
type GlobalRecord = Record<string, unknown>;
|
|
89
|
+
/** Setup */
|
|
90
|
+
interface SetupContext<T, TGlobals extends GlobalRecord = any> {
|
|
91
|
+
me: T;
|
|
92
|
+
globals: TGlobals;
|
|
93
|
+
inputs?: Inputs;
|
|
94
|
+
camera?: ICamera;
|
|
95
|
+
stage?: IStage;
|
|
96
|
+
game?: IGame<TGlobals>;
|
|
97
|
+
}
|
|
98
|
+
interface SetupFunction<T, TGlobals extends GlobalRecord = any> {
|
|
99
|
+
(context: SetupContext<T, TGlobals>): void;
|
|
100
|
+
}
|
|
101
|
+
/** Loaded */
|
|
102
|
+
interface LoadedContext<T, TGlobals extends GlobalRecord = any> {
|
|
103
|
+
me: T;
|
|
104
|
+
globals: TGlobals;
|
|
105
|
+
}
|
|
106
|
+
interface LoadedFunction<T, TGlobals extends GlobalRecord = any> {
|
|
107
|
+
(context: LoadedContext<T, TGlobals>): void;
|
|
108
|
+
}
|
|
109
|
+
/** Update */
|
|
110
|
+
type UpdateContext<T, TGlobals extends GlobalRecord = any> = {
|
|
111
|
+
me: T;
|
|
112
|
+
delta: number;
|
|
113
|
+
inputs: Inputs;
|
|
114
|
+
globals: TGlobals;
|
|
115
|
+
camera: ICamera;
|
|
116
|
+
stage?: IStage;
|
|
117
|
+
game?: IGame<TGlobals>;
|
|
118
|
+
};
|
|
119
|
+
interface UpdateFunction<T, TGlobals extends GlobalRecord = any> {
|
|
120
|
+
(context: UpdateContext<T, TGlobals>): void;
|
|
121
|
+
}
|
|
122
|
+
/** Destroy */
|
|
123
|
+
interface DestroyContext<T, TGlobals extends GlobalRecord = any> {
|
|
124
|
+
me: T;
|
|
125
|
+
globals: TGlobals;
|
|
126
|
+
}
|
|
127
|
+
interface DestroyFunction<T, TGlobals extends GlobalRecord = any> {
|
|
128
|
+
(context: DestroyContext<T, TGlobals>): void;
|
|
129
|
+
}
|
|
130
|
+
/** Cleanup */
|
|
131
|
+
interface CleanupContext<T, TGlobals extends GlobalRecord = any> {
|
|
132
|
+
me: T;
|
|
133
|
+
globals: TGlobals;
|
|
134
|
+
}
|
|
135
|
+
interface CleanupFunction<T, TGlobals extends GlobalRecord = any> {
|
|
136
|
+
(context: CleanupContext<T, TGlobals>): void;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
interface NodeInterface {
|
|
140
|
+
uuid: string;
|
|
141
|
+
name: string;
|
|
142
|
+
markedForRemoval: boolean;
|
|
143
|
+
nodeSetup(params: SetupContext<any>): void;
|
|
144
|
+
nodeUpdate(params: UpdateContext<any>): void;
|
|
145
|
+
nodeDestroy(params: DestroyContext<any>): void;
|
|
146
|
+
setParent(parent: NodeInterface | null): void;
|
|
147
|
+
getParent(): NodeInterface | null;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
type BaseNodeOptions<T = any> = BaseNode | Partial<T>;
|
|
151
|
+
/**
|
|
152
|
+
* Lifecycle callback arrays - each lifecycle event can have multiple callbacks
|
|
153
|
+
* that execute in order.
|
|
154
|
+
*/
|
|
155
|
+
interface LifecycleCallbacks<T> {
|
|
156
|
+
setup: Array<SetupFunction<T>>;
|
|
157
|
+
loaded: Array<LoadedFunction<T>>;
|
|
158
|
+
update: Array<UpdateFunction<T>>;
|
|
159
|
+
destroy: Array<DestroyFunction<T>>;
|
|
160
|
+
cleanup: Array<CleanupFunction<T>>;
|
|
161
|
+
}
|
|
162
|
+
declare abstract class BaseNode<Options = any, T = any> implements NodeInterface {
|
|
163
|
+
protected parent: NodeInterface | null;
|
|
164
|
+
protected children: NodeInterface[];
|
|
165
|
+
options: Options;
|
|
166
|
+
eid: number;
|
|
167
|
+
uuid: string;
|
|
168
|
+
name: string;
|
|
169
|
+
markedForRemoval: boolean;
|
|
170
|
+
/**
|
|
171
|
+
* Lifecycle callback arrays - use onSetup(), onUpdate(), etc. to add callbacks
|
|
172
|
+
* Uses `any` for the type parameter to avoid invariance issues when subclasses
|
|
173
|
+
* are assigned to BaseNode references. Type safety is enforced by the public
|
|
174
|
+
* onSetup/onUpdate/etc. methods which are typed with `this`.
|
|
175
|
+
*/
|
|
176
|
+
protected lifecycleCallbacks: LifecycleCallbacks<any>;
|
|
177
|
+
constructor(args?: BaseNodeOptions[]);
|
|
178
|
+
/**
|
|
179
|
+
* Add setup callbacks to be executed in order during nodeSetup
|
|
180
|
+
*/
|
|
181
|
+
onSetup(...callbacks: Array<SetupFunction<this>>): this;
|
|
182
|
+
/**
|
|
183
|
+
* Add loaded callbacks to be executed in order during nodeLoaded
|
|
184
|
+
*/
|
|
185
|
+
onLoaded(...callbacks: Array<LoadedFunction<this>>): this;
|
|
186
|
+
/**
|
|
187
|
+
* Add update callbacks to be executed in order during nodeUpdate
|
|
188
|
+
*/
|
|
189
|
+
onUpdate(...callbacks: Array<UpdateFunction<this>>): this;
|
|
190
|
+
/**
|
|
191
|
+
* Add destroy callbacks to be executed in order during nodeDestroy
|
|
192
|
+
*/
|
|
193
|
+
onDestroy(...callbacks: Array<DestroyFunction<this>>): this;
|
|
194
|
+
/**
|
|
195
|
+
* Add cleanup callbacks to be executed in order during nodeCleanup
|
|
196
|
+
*/
|
|
197
|
+
onCleanup(...callbacks: Array<CleanupFunction<this>>): this;
|
|
198
|
+
/**
|
|
199
|
+
* Prepend setup callbacks (run before existing ones)
|
|
200
|
+
*/
|
|
201
|
+
prependSetup(...callbacks: Array<SetupFunction<this>>): this;
|
|
202
|
+
/**
|
|
203
|
+
* Prepend update callbacks (run before existing ones)
|
|
204
|
+
*/
|
|
205
|
+
prependUpdate(...callbacks: Array<UpdateFunction<this>>): this;
|
|
206
|
+
setParent(parent: NodeInterface | null): void;
|
|
207
|
+
getParent(): NodeInterface | null;
|
|
208
|
+
add(baseNode: NodeInterface): void;
|
|
209
|
+
remove(baseNode: NodeInterface): void;
|
|
210
|
+
getChildren(): NodeInterface[];
|
|
211
|
+
isComposite(): boolean;
|
|
212
|
+
abstract create(): T;
|
|
213
|
+
protected abstract _setup(params: SetupContext<this>): void;
|
|
214
|
+
protected abstract _loaded(params: LoadedContext<this>): Promise<void>;
|
|
215
|
+
protected abstract _update(params: UpdateContext<this>): void;
|
|
216
|
+
protected abstract _destroy(params: DestroyContext<this>): void;
|
|
217
|
+
protected abstract _cleanup(params: CleanupContext<this>): void;
|
|
218
|
+
nodeSetup(params: SetupContext<this>): void;
|
|
219
|
+
nodeUpdate(params: UpdateContext<this>): void;
|
|
220
|
+
nodeDestroy(params: DestroyContext<this>): void;
|
|
221
|
+
nodeLoaded(params: LoadedContext<this>): Promise<void>;
|
|
222
|
+
nodeCleanup(params: CleanupContext<this>): void;
|
|
223
|
+
getOptions(): Options;
|
|
224
|
+
setOptions(options: Partial<Options>): void;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
type Vec3 = Vector3 | Vector3$1;
|
|
228
|
+
|
|
229
|
+
declare function shortHash(objString: string): string;
|
|
230
|
+
|
|
231
|
+
/**
|
|
232
|
+
* GLSL shader object (traditional approach for WebGL)
|
|
233
|
+
*/
|
|
234
|
+
type ZylemShaderObject = {
|
|
235
|
+
fragment: string;
|
|
236
|
+
vertex: string;
|
|
237
|
+
};
|
|
238
|
+
/**
|
|
239
|
+
* TSL shader type (for WebGPU)
|
|
240
|
+
* colorNode should be a TSL node that returns the fragment color
|
|
241
|
+
*/
|
|
242
|
+
type ZylemTSLShader = {
|
|
243
|
+
colorNode: any;
|
|
244
|
+
transparent?: boolean;
|
|
245
|
+
};
|
|
246
|
+
/**
|
|
247
|
+
* Combined shader type supporting both GLSL and TSL
|
|
248
|
+
*/
|
|
249
|
+
type ZylemShader = ZylemShaderObject | ZylemTSLShader;
|
|
250
|
+
/**
|
|
251
|
+
* Check if a shader is a TSL shader
|
|
252
|
+
*/
|
|
253
|
+
declare function isTSLShader(shader: ZylemShader): shader is ZylemTSLShader;
|
|
254
|
+
/**
|
|
255
|
+
* Check if a shader is a GLSL shader
|
|
256
|
+
*/
|
|
257
|
+
declare function isGLSLShader(shader: ZylemShader): shader is ZylemShaderObject;
|
|
258
|
+
interface MaterialOptions {
|
|
259
|
+
path?: string;
|
|
260
|
+
normalMap?: string;
|
|
261
|
+
repeat?: Vector2;
|
|
262
|
+
shader?: ZylemShader;
|
|
263
|
+
color?: Color;
|
|
264
|
+
/**
|
|
265
|
+
* When true, prefer TSL/NodeMaterial (for WebGPU)
|
|
266
|
+
* When false, prefer GLSL/ShaderMaterial (for WebGL)
|
|
267
|
+
*/
|
|
268
|
+
useTSL?: boolean;
|
|
269
|
+
}
|
|
270
|
+
type BatchGeometryMap = Map<symbol, number>;
|
|
271
|
+
interface BatchMaterialMapObject {
|
|
272
|
+
geometryMap: BatchGeometryMap;
|
|
273
|
+
material: Material;
|
|
274
|
+
}
|
|
275
|
+
type BatchKey = ReturnType<typeof shortHash>;
|
|
276
|
+
type TexturePath = string | null;
|
|
277
|
+
declare class MaterialBuilder {
|
|
278
|
+
static batchMaterialMap: Map<BatchKey, BatchMaterialMapObject>;
|
|
279
|
+
materials: Material[];
|
|
280
|
+
/** Whether to use TSL/NodeMaterial (for WebGPU compatibility) */
|
|
281
|
+
private useTSL;
|
|
282
|
+
constructor(useTSL?: boolean);
|
|
283
|
+
batchMaterial(options: Partial<MaterialOptions>, entityType: symbol): void;
|
|
284
|
+
build(options: Partial<MaterialOptions>, entityType: symbol): void;
|
|
285
|
+
withColor(color: Color, useTSL?: boolean): this;
|
|
286
|
+
withShader(shader: ZylemShaderObject): this;
|
|
287
|
+
withTSLShader(shader: ZylemTSLShader): this;
|
|
288
|
+
/**
|
|
289
|
+
* Set texture - loads in background (deferred).
|
|
290
|
+
* Material is created immediately with null map, texture applies when loaded.
|
|
291
|
+
*/
|
|
292
|
+
setTexture(texturePath?: TexturePath, repeat?: Vector2, useTSL?: boolean): void;
|
|
293
|
+
/**
|
|
294
|
+
* Set normal map for the current material
|
|
295
|
+
*/
|
|
296
|
+
setNormalMap(normalMapPath: string, repeat?: Vector2): void;
|
|
297
|
+
setColor(color: Color, useTSL?: boolean): void;
|
|
298
|
+
/**
|
|
299
|
+
* Set GLSL shader (WebGL only)
|
|
300
|
+
*/
|
|
301
|
+
setShader(customShader: ZylemShaderObject): void;
|
|
302
|
+
/**
|
|
303
|
+
* Set TSL shader (WebGPU compatible)
|
|
304
|
+
*/
|
|
305
|
+
setTSLShader(tslShader: ZylemTSLShader): void;
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
/**
|
|
309
|
+
* Options for configuring entity collision behavior.
|
|
310
|
+
*/
|
|
311
|
+
interface CollisionOptions {
|
|
312
|
+
static?: boolean;
|
|
313
|
+
sensor?: boolean;
|
|
314
|
+
size?: Vector3$1;
|
|
315
|
+
position?: Vector3$1;
|
|
316
|
+
collisionType?: string;
|
|
317
|
+
collisionFilter?: string[];
|
|
318
|
+
}
|
|
319
|
+
declare class CollisionBuilder {
|
|
320
|
+
static: boolean;
|
|
321
|
+
sensor: boolean;
|
|
322
|
+
gravity: Vec3;
|
|
323
|
+
build(options: Partial<CollisionOptions>): [RigidBodyDesc, ColliderDesc];
|
|
324
|
+
withCollision(collisionOptions: Partial<CollisionOptions>): this;
|
|
325
|
+
collider(options: CollisionOptions): ColliderDesc;
|
|
326
|
+
bodyDesc({ isDynamicBody }: {
|
|
327
|
+
isDynamicBody?: boolean | undefined;
|
|
328
|
+
}): RigidBodyDesc;
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
/**
|
|
332
|
+
* TODO: allow for multiple materials requires geometry groups
|
|
333
|
+
* TODO: allow for instanced uniforms
|
|
334
|
+
* TODO: allow for geometry groups
|
|
335
|
+
* TODO: allow for batched meshes
|
|
336
|
+
* import { InstancedUniformsMesh } from 'three-instanced-uniforms-mesh';
|
|
337
|
+
* may not need geometry groups for shaders though
|
|
338
|
+
* setGeometry<T extends BufferGeometry>(geometry: T) {
|
|
339
|
+
* MeshBuilder.bachedMesh = new BatchedMesh(10, 5000, 10000, material);
|
|
340
|
+
* }
|
|
341
|
+
*/
|
|
342
|
+
type MeshBuilderOptions = Partial<Pick<GameEntityOptions, 'batched' | 'material'>>;
|
|
343
|
+
declare class MeshBuilder {
|
|
344
|
+
_build(meshOptions: MeshBuilderOptions, geometry: BufferGeometry, materials: Material[]): Mesh;
|
|
345
|
+
_postBuild(): void;
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
declare abstract class EntityCollisionBuilder extends CollisionBuilder {
|
|
349
|
+
abstract collider(options: GameEntityOptions): ColliderDesc;
|
|
350
|
+
}
|
|
351
|
+
declare abstract class EntityMeshBuilder extends MeshBuilder {
|
|
352
|
+
build(options: GameEntityOptions): BufferGeometry;
|
|
353
|
+
postBuild(): void;
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
interface Behavior {
|
|
357
|
+
component: IComponent;
|
|
358
|
+
values: any;
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
/**
|
|
362
|
+
* Reusable delegate for event emission and subscription.
|
|
363
|
+
* Use via composition in Game, Stage, and Entity classes.
|
|
364
|
+
*
|
|
365
|
+
* @example
|
|
366
|
+
* class Game {
|
|
367
|
+
* private eventDelegate = new EventEmitterDelegate<GameEvents>();
|
|
368
|
+
*
|
|
369
|
+
* dispatch<K extends keyof GameEvents>(event: K, payload: GameEvents[K]) {
|
|
370
|
+
* this.eventDelegate.dispatch(event, payload);
|
|
371
|
+
* }
|
|
372
|
+
* }
|
|
373
|
+
*/
|
|
374
|
+
declare class EventEmitterDelegate<TEvents extends Record<string, unknown>> {
|
|
375
|
+
private emitter;
|
|
376
|
+
private unsubscribes;
|
|
377
|
+
constructor();
|
|
378
|
+
/**
|
|
379
|
+
* Dispatch an event to all listeners.
|
|
380
|
+
*/
|
|
381
|
+
dispatch<K extends keyof TEvents>(event: K, payload: TEvents[K]): void;
|
|
382
|
+
/**
|
|
383
|
+
* Subscribe to an event. Returns an unsubscribe function.
|
|
384
|
+
*/
|
|
385
|
+
listen<K extends keyof TEvents>(event: K, handler: (payload: TEvents[K]) => void): () => void;
|
|
386
|
+
/**
|
|
387
|
+
* Subscribe to all events.
|
|
388
|
+
*/
|
|
389
|
+
listenAll(handler: (type: keyof TEvents, payload: TEvents[keyof TEvents]) => void): () => void;
|
|
390
|
+
/**
|
|
391
|
+
* Clean up all subscriptions.
|
|
392
|
+
*/
|
|
393
|
+
dispose(): void;
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
/**
|
|
397
|
+
* Payload for game loading events with stage context.
|
|
398
|
+
*/
|
|
399
|
+
interface GameLoadingPayload extends LoadingEvent {
|
|
400
|
+
stageName?: string;
|
|
401
|
+
stageIndex?: number;
|
|
402
|
+
}
|
|
403
|
+
/** Payload for stage configuration sent to editor. */
|
|
404
|
+
interface StageConfigPayload {
|
|
405
|
+
id: string;
|
|
406
|
+
backgroundColor: string;
|
|
407
|
+
backgroundImage: string | null;
|
|
408
|
+
gravity: {
|
|
409
|
+
x: number;
|
|
410
|
+
y: number;
|
|
411
|
+
z: number;
|
|
412
|
+
};
|
|
413
|
+
inputs: Record<string, string[]>;
|
|
414
|
+
variables: Record<string, unknown>;
|
|
415
|
+
}
|
|
416
|
+
/** Payload for entity configuration sent to editor. */
|
|
417
|
+
interface EntityConfigPayload {
|
|
418
|
+
uuid: string;
|
|
419
|
+
name: string;
|
|
420
|
+
type: string;
|
|
421
|
+
position: {
|
|
422
|
+
x: number;
|
|
423
|
+
y: number;
|
|
424
|
+
z: number;
|
|
425
|
+
};
|
|
426
|
+
rotation: {
|
|
427
|
+
x: number;
|
|
428
|
+
y: number;
|
|
429
|
+
z: number;
|
|
430
|
+
};
|
|
431
|
+
scale: {
|
|
432
|
+
x: number;
|
|
433
|
+
y: number;
|
|
434
|
+
z: number;
|
|
435
|
+
};
|
|
436
|
+
}
|
|
437
|
+
/** Payload for state dispatch events from game to editor. */
|
|
438
|
+
interface StateDispatchPayload {
|
|
439
|
+
scope: 'game' | 'stage' | 'entity';
|
|
440
|
+
path: string;
|
|
441
|
+
value: unknown;
|
|
442
|
+
previousValue?: unknown;
|
|
443
|
+
config?: {
|
|
444
|
+
id: string;
|
|
445
|
+
aspectRatio: number;
|
|
446
|
+
fullscreen: boolean;
|
|
447
|
+
bodyBackground: string | undefined;
|
|
448
|
+
internalResolution: {
|
|
449
|
+
width: number;
|
|
450
|
+
height: number;
|
|
451
|
+
} | undefined;
|
|
452
|
+
debug: boolean;
|
|
453
|
+
} | null;
|
|
454
|
+
stageConfig?: StageConfigPayload | null;
|
|
455
|
+
entities?: EntityConfigPayload[] | null;
|
|
456
|
+
}
|
|
457
|
+
type GameEvents = {
|
|
458
|
+
'loading:start': GameLoadingPayload;
|
|
459
|
+
'loading:progress': GameLoadingPayload;
|
|
460
|
+
'loading:complete': GameLoadingPayload;
|
|
461
|
+
'paused': {
|
|
462
|
+
paused: boolean;
|
|
463
|
+
};
|
|
464
|
+
'debug': {
|
|
465
|
+
enabled: boolean;
|
|
466
|
+
};
|
|
467
|
+
'state:dispatch': StateDispatchPayload;
|
|
468
|
+
};
|
|
469
|
+
type StageEvents = {
|
|
470
|
+
'stage:loaded': {
|
|
471
|
+
stageId: string;
|
|
472
|
+
};
|
|
473
|
+
'stage:unloaded': {
|
|
474
|
+
stageId: string;
|
|
475
|
+
};
|
|
476
|
+
'stage:variable:changed': {
|
|
477
|
+
key: string;
|
|
478
|
+
value: unknown;
|
|
479
|
+
};
|
|
480
|
+
};
|
|
481
|
+
type EntityEvents = {
|
|
482
|
+
'entity:spawned': {
|
|
483
|
+
entityId: string;
|
|
484
|
+
name: string;
|
|
485
|
+
};
|
|
486
|
+
'entity:destroyed': {
|
|
487
|
+
entityId: string;
|
|
488
|
+
};
|
|
489
|
+
'entity:collision': {
|
|
490
|
+
entityId: string;
|
|
491
|
+
otherId: string;
|
|
492
|
+
};
|
|
493
|
+
'entity:model:loading': {
|
|
494
|
+
entityId: string;
|
|
495
|
+
files: string[];
|
|
496
|
+
};
|
|
497
|
+
'entity:model:loaded': {
|
|
498
|
+
entityId: string;
|
|
499
|
+
success: boolean;
|
|
500
|
+
meshCount?: number;
|
|
501
|
+
};
|
|
502
|
+
'entity:animation:loaded': {
|
|
503
|
+
entityId: string;
|
|
504
|
+
animationCount: number;
|
|
505
|
+
};
|
|
506
|
+
};
|
|
507
|
+
type ZylemEvents = GameEvents & StageEvents & EntityEvents;
|
|
508
|
+
/**
|
|
509
|
+
* Global event bus for cross-package communication.
|
|
510
|
+
*
|
|
511
|
+
* Usage:
|
|
512
|
+
* ```ts
|
|
513
|
+
* import { zylemEventBus } from '@zylem/game-lib';
|
|
514
|
+
*
|
|
515
|
+
* // Subscribe
|
|
516
|
+
* const unsub = zylemEventBus.on('loading:progress', (e) => console.log(e));
|
|
517
|
+
*
|
|
518
|
+
* // Emit
|
|
519
|
+
* zylemEventBus.emit('loading:progress', { type: 'progress', progress: 0.5 });
|
|
520
|
+
*
|
|
521
|
+
* // Cleanup
|
|
522
|
+
* unsub();
|
|
523
|
+
* ```
|
|
524
|
+
*/
|
|
525
|
+
declare const zylemEventBus: mitt.Emitter<ZylemEvents>;
|
|
526
|
+
|
|
527
|
+
/**
|
|
528
|
+
* Transform state managed by Valtio for batched physics updates.
|
|
529
|
+
*
|
|
530
|
+
* This store accumulates transformation intents during the frame,
|
|
531
|
+
* then applies them all at once after onUpdate() callbacks complete.
|
|
532
|
+
*
|
|
533
|
+
* Design decisions:
|
|
534
|
+
* - Position: Accumulated deltas (additive)
|
|
535
|
+
* - Rotation: Last value wins (replacement)
|
|
536
|
+
* - Velocity: Accumulated deltas (additive)
|
|
537
|
+
* - Angular velocity: Accumulated deltas (additive)
|
|
538
|
+
*/
|
|
539
|
+
interface TransformState {
|
|
540
|
+
/** Position deltas to be applied (accumulated) */
|
|
541
|
+
position: {
|
|
542
|
+
x: number;
|
|
543
|
+
y: number;
|
|
544
|
+
z: number;
|
|
545
|
+
};
|
|
546
|
+
/** Rotation quaternion (last value wins) */
|
|
547
|
+
rotation: {
|
|
548
|
+
x: number;
|
|
549
|
+
y: number;
|
|
550
|
+
z: number;
|
|
551
|
+
w: number;
|
|
552
|
+
};
|
|
553
|
+
/** Linear velocity (accumulated) */
|
|
554
|
+
velocity: {
|
|
555
|
+
x: number;
|
|
556
|
+
y: number;
|
|
557
|
+
z: number;
|
|
558
|
+
};
|
|
559
|
+
/** Angular velocity (accumulated) */
|
|
560
|
+
angularVelocity: {
|
|
561
|
+
x: number;
|
|
562
|
+
y: number;
|
|
563
|
+
z: number;
|
|
564
|
+
};
|
|
565
|
+
/** Dirty flags to track what needs to be applied */
|
|
566
|
+
dirty: {
|
|
567
|
+
position: boolean;
|
|
568
|
+
rotation: boolean;
|
|
569
|
+
velocity: boolean;
|
|
570
|
+
angularVelocity: boolean;
|
|
571
|
+
};
|
|
572
|
+
}
|
|
573
|
+
/**
|
|
574
|
+
* Create a new transform store with optional initial values.
|
|
575
|
+
* The store is a Valtio proxy, making it reactive for debugging/visualization.
|
|
576
|
+
*
|
|
577
|
+
* @param initial Optional initial state values
|
|
578
|
+
* @returns Reactive transform state
|
|
579
|
+
*/
|
|
580
|
+
declare function createTransformStore(initial?: Partial<TransformState>): TransformState;
|
|
581
|
+
/**
|
|
582
|
+
* Reset a transform store to its initial clean state.
|
|
583
|
+
* Called after applying changes to prepare for the next frame.
|
|
584
|
+
*
|
|
585
|
+
* @param store The transform store to reset
|
|
586
|
+
*/
|
|
587
|
+
declare function resetTransformStore(store: TransformState): void;
|
|
588
|
+
|
|
589
|
+
interface EntityWithBody {
|
|
590
|
+
body: RigidBody | null;
|
|
591
|
+
transformStore?: TransformState;
|
|
592
|
+
}
|
|
593
|
+
/**
|
|
594
|
+
* Move an entity along the X axis, preserving other velocities.
|
|
595
|
+
*/
|
|
596
|
+
declare function moveX(entity: EntityWithBody, delta: number): void;
|
|
597
|
+
/**
|
|
598
|
+
* Move an entity along the Y axis, preserving other velocities.
|
|
599
|
+
*/
|
|
600
|
+
declare function moveY(entity: EntityWithBody, delta: number): void;
|
|
601
|
+
/**
|
|
602
|
+
* Move an entity along the Z axis, preserving other velocities.
|
|
603
|
+
*/
|
|
604
|
+
declare function moveZ(entity: EntityWithBody, delta: number): void;
|
|
605
|
+
/**
|
|
606
|
+
* Move an entity along the X and Y axis, preserving Z velocity.
|
|
607
|
+
*/
|
|
608
|
+
declare function moveXY(entity: EntityWithBody, deltaX: number, deltaY: number): void;
|
|
609
|
+
/**
|
|
610
|
+
* Move an entity along the X and Z axis, preserving Y velocity.
|
|
611
|
+
*/
|
|
612
|
+
declare function moveXZ(entity: EntityWithBody, deltaX: number, deltaZ: number): void;
|
|
613
|
+
/**
|
|
614
|
+
* Move entity based on a vector, adding to existing velocities.
|
|
615
|
+
*/
|
|
616
|
+
declare function move(entity: EntityWithBody, vector: Vector3): void;
|
|
617
|
+
/**
|
|
618
|
+
* Reset entity velocity
|
|
619
|
+
*/
|
|
620
|
+
declare function resetVelocity(entity: EntityWithBody): void;
|
|
621
|
+
/**
|
|
622
|
+
* Move entity forward in 2D space, preserving Z velocity
|
|
623
|
+
*/
|
|
624
|
+
declare function moveForwardXY(entity: EntityWithBody, delta: number, rotation2DAngle: number): void;
|
|
625
|
+
/**
|
|
626
|
+
* Get entity position
|
|
627
|
+
*/
|
|
628
|
+
declare function getPosition(entity: EntityWithBody): Vector | null;
|
|
629
|
+
/**
|
|
630
|
+
* Get entity velocity
|
|
631
|
+
*/
|
|
632
|
+
declare function getVelocity(entity: EntityWithBody): Vector | null;
|
|
633
|
+
/**
|
|
634
|
+
* Set entity position
|
|
635
|
+
*/
|
|
636
|
+
declare function setPosition(entity: EntityWithBody, x: number, y: number, z: number): void;
|
|
637
|
+
/**
|
|
638
|
+
* Set entity X position
|
|
639
|
+
*/
|
|
640
|
+
declare function setPositionX(entity: EntityWithBody, x: number): void;
|
|
641
|
+
/**
|
|
642
|
+
* Set entity Y position
|
|
643
|
+
*/
|
|
644
|
+
declare function setPositionY(entity: EntityWithBody, y: number): void;
|
|
645
|
+
/**
|
|
646
|
+
* Set entity Z position
|
|
647
|
+
*/
|
|
648
|
+
declare function setPositionZ(entity: EntityWithBody, z: number): void;
|
|
649
|
+
/**
|
|
650
|
+
* Wrap entity around 2D bounds
|
|
651
|
+
*/
|
|
652
|
+
declare function wrapAroundXY(entity: EntityWithBody, boundsX: number, boundsY: number): void;
|
|
653
|
+
/**
|
|
654
|
+
* Wrap entity around 3D bounds
|
|
655
|
+
*/
|
|
656
|
+
declare function wrapAround3D(entity: EntityWithBody, boundsX: number, boundsY: number, boundsZ: number): void;
|
|
657
|
+
/**
|
|
658
|
+
* Enhanced moveable entity with bound methods
|
|
659
|
+
*/
|
|
660
|
+
interface MoveableEntity extends EntityWithBody {
|
|
661
|
+
moveX(delta: number): void;
|
|
662
|
+
moveY(delta: number): void;
|
|
663
|
+
moveZ(delta: number): void;
|
|
664
|
+
moveXY(deltaX: number, deltaY: number): void;
|
|
665
|
+
moveXZ(deltaX: number, deltaZ: number): void;
|
|
666
|
+
move(vector: Vector3): void;
|
|
667
|
+
resetVelocity(): void;
|
|
668
|
+
moveForwardXY(delta: number, rotation2DAngle: number): void;
|
|
669
|
+
getPosition(): Vector | null;
|
|
670
|
+
getVelocity(): Vector | null;
|
|
671
|
+
setPosition(x: number, y: number, z: number): void;
|
|
672
|
+
setPositionX(x: number): void;
|
|
673
|
+
setPositionY(y: number): void;
|
|
674
|
+
setPositionZ(z: number): void;
|
|
675
|
+
wrapAroundXY(boundsX: number, boundsY: number): void;
|
|
676
|
+
wrapAround3D(boundsX: number, boundsY: number, boundsZ: number): void;
|
|
677
|
+
}
|
|
678
|
+
|
|
679
|
+
interface RotatableEntity {
|
|
680
|
+
body: RigidBody | null;
|
|
681
|
+
group: any;
|
|
682
|
+
transformStore?: TransformState;
|
|
683
|
+
}
|
|
684
|
+
/**
|
|
685
|
+
* Rotate an entity in the direction of a movement vector
|
|
686
|
+
*/
|
|
687
|
+
declare function rotateInDirection(entity: RotatableEntity, moveVector: Vector3): void;
|
|
688
|
+
/**
|
|
689
|
+
* Rotate an entity around the Y axis using Euler angles
|
|
690
|
+
*/
|
|
691
|
+
declare function rotateYEuler(entity: RotatableEntity, amount: number): void;
|
|
692
|
+
/**
|
|
693
|
+
* Rotate an entity using Euler angles
|
|
694
|
+
*/
|
|
695
|
+
declare function rotateEuler(entity: RotatableEntity, rotation: Vector3): void;
|
|
696
|
+
/**
|
|
697
|
+
* Rotate an entity around the Y axis.
|
|
698
|
+
*/
|
|
699
|
+
declare function rotateY(entity: RotatableEntity, delta: number): void;
|
|
700
|
+
/**
|
|
701
|
+
* Rotate an entity around the X axis.
|
|
702
|
+
*/
|
|
703
|
+
declare function rotateX(entity: RotatableEntity, delta: number): void;
|
|
704
|
+
/**
|
|
705
|
+
* Rotate an entity around the Z axis.
|
|
706
|
+
*/
|
|
707
|
+
declare function rotateZ(entity: RotatableEntity, delta: number): void;
|
|
708
|
+
/**
|
|
709
|
+
* Set rotation around Y axis.
|
|
710
|
+
*/
|
|
711
|
+
declare function setRotationY(entity: RotatableEntity, y: number): void;
|
|
712
|
+
/**
|
|
713
|
+
* Set rotation around Y axis
|
|
714
|
+
*/
|
|
715
|
+
declare function setRotationDegreesY(entity: RotatableEntity, y: number): void;
|
|
716
|
+
/**
|
|
717
|
+
* Set rotation around X axis.
|
|
718
|
+
*/
|
|
719
|
+
declare function setRotationX(entity: RotatableEntity, x: number): void;
|
|
720
|
+
/**
|
|
721
|
+
* Set rotation around X axis
|
|
722
|
+
*/
|
|
723
|
+
declare function setRotationDegreesX(entity: RotatableEntity, x: number): void;
|
|
724
|
+
/**
|
|
725
|
+
* Set rotation around Z axis.
|
|
726
|
+
*/
|
|
727
|
+
declare function setRotationZ(entity: RotatableEntity, z: number): void;
|
|
728
|
+
/**
|
|
729
|
+
* Set rotation around Z axis
|
|
730
|
+
*/
|
|
731
|
+
declare function setRotationDegreesZ(entity: RotatableEntity, z: number): void;
|
|
732
|
+
/**
|
|
733
|
+
* Set rotation for all axes.
|
|
734
|
+
*/
|
|
735
|
+
declare function setRotation(entity: RotatableEntity, x: number, y: number, z: number): void;
|
|
736
|
+
/**
|
|
737
|
+
* Set rotation for all axes
|
|
738
|
+
*/
|
|
739
|
+
declare function setRotationDegrees(entity: RotatableEntity, x: number, y: number, z: number): void;
|
|
740
|
+
/**
|
|
741
|
+
* Get current rotation
|
|
742
|
+
*/
|
|
743
|
+
declare function getRotation(entity: RotatableEntity): any;
|
|
744
|
+
/**
|
|
745
|
+
* Rotatable entity API with bound methods
|
|
746
|
+
*/
|
|
747
|
+
interface RotatableEntityAPI extends RotatableEntity {
|
|
748
|
+
rotateInDirection(moveVector: Vector3): void;
|
|
749
|
+
rotateYEuler(amount: number): void;
|
|
750
|
+
rotateEuler(rotation: Vector3): void;
|
|
751
|
+
rotateY(delta: number): void;
|
|
752
|
+
rotateX(delta: number): void;
|
|
753
|
+
rotateZ(delta: number): void;
|
|
754
|
+
setRotationY(y: number): void;
|
|
755
|
+
setRotationX(x: number): void;
|
|
756
|
+
setRotationZ(z: number): void;
|
|
757
|
+
setRotationDegrees(x: number, y: number, z: number): void;
|
|
758
|
+
setRotationDegreesY(y: number): void;
|
|
759
|
+
setRotationDegreesX(x: number): void;
|
|
760
|
+
setRotationDegreesZ(z: number): void;
|
|
761
|
+
setRotation(x: number, y: number, z: number): void;
|
|
762
|
+
getRotation(): any;
|
|
763
|
+
}
|
|
764
|
+
|
|
765
|
+
/**
|
|
766
|
+
* A built collision component containing a rigid body description and collider description.
|
|
767
|
+
* Returned by collision factory functions (boxCollision, sphereCollision, etc.)
|
|
768
|
+
* and consumed by GameEntity.add().
|
|
769
|
+
*/
|
|
770
|
+
interface CollisionComponent {
|
|
771
|
+
__kind: 'collision';
|
|
772
|
+
bodyDesc: RigidBodyDesc;
|
|
773
|
+
colliderDesc: ColliderDesc;
|
|
774
|
+
}
|
|
775
|
+
interface BaseCollisionOptions {
|
|
776
|
+
/** Whether the body is static (fixed) or dynamic */
|
|
777
|
+
static?: boolean;
|
|
778
|
+
/** Whether this collider is a sensor */
|
|
779
|
+
sensor?: boolean;
|
|
780
|
+
/** Position offset relative to the entity origin */
|
|
781
|
+
offset?: Vec3;
|
|
782
|
+
/** Collision type string for group filtering */
|
|
783
|
+
collisionType?: string;
|
|
784
|
+
/** Allowed collision types for filtering */
|
|
785
|
+
collisionFilter?: string[];
|
|
786
|
+
}
|
|
787
|
+
interface BoxCollisionOptions extends BaseCollisionOptions {
|
|
788
|
+
/** Box dimensions (default: 1x1x1) */
|
|
789
|
+
size?: Vec3;
|
|
790
|
+
}
|
|
791
|
+
/**
|
|
792
|
+
* Create a box (cuboid) collision component.
|
|
793
|
+
*/
|
|
794
|
+
declare function boxCollision(opts?: BoxCollisionOptions): CollisionComponent;
|
|
795
|
+
interface SphereCollisionOptions extends BaseCollisionOptions {
|
|
796
|
+
/** Sphere radius (default: 1) */
|
|
797
|
+
radius?: number;
|
|
798
|
+
}
|
|
799
|
+
/**
|
|
800
|
+
* Create a sphere (ball) collision component.
|
|
801
|
+
*/
|
|
802
|
+
declare function sphereCollision(opts?: SphereCollisionOptions): CollisionComponent;
|
|
803
|
+
interface ConeCollisionOptions extends BaseCollisionOptions {
|
|
804
|
+
/** Base radius (default: 1) */
|
|
805
|
+
radius?: number;
|
|
806
|
+
/** Height (default: 2) */
|
|
807
|
+
height?: number;
|
|
808
|
+
}
|
|
809
|
+
/**
|
|
810
|
+
* Create a cone collision component.
|
|
811
|
+
*/
|
|
812
|
+
declare function coneCollision(opts?: ConeCollisionOptions): CollisionComponent;
|
|
813
|
+
interface PyramidCollisionOptions extends BaseCollisionOptions {
|
|
814
|
+
/** Base radius (default: 1) */
|
|
815
|
+
radius?: number;
|
|
816
|
+
/** Height (default: 2) */
|
|
817
|
+
height?: number;
|
|
818
|
+
}
|
|
819
|
+
/**
|
|
820
|
+
* Create a pyramid collision component (approximated as a cone).
|
|
821
|
+
*/
|
|
822
|
+
declare function pyramidCollision(opts?: PyramidCollisionOptions): CollisionComponent;
|
|
823
|
+
interface CylinderCollisionOptions extends BaseCollisionOptions {
|
|
824
|
+
/** Top radius (default: 1) */
|
|
825
|
+
radiusTop?: number;
|
|
826
|
+
/** Bottom radius (default: 1) */
|
|
827
|
+
radiusBottom?: number;
|
|
828
|
+
/** Height (default: 2) */
|
|
829
|
+
height?: number;
|
|
830
|
+
}
|
|
831
|
+
/**
|
|
832
|
+
* Create a cylinder collision component.
|
|
833
|
+
*/
|
|
834
|
+
declare function cylinderCollision(opts?: CylinderCollisionOptions): CollisionComponent;
|
|
835
|
+
interface PillCollisionOptions extends BaseCollisionOptions {
|
|
836
|
+
/** Capsule hemisphere radius (default: 0.5) */
|
|
837
|
+
radius?: number;
|
|
838
|
+
/** Cylindrical section length (default: 1) */
|
|
839
|
+
length?: number;
|
|
840
|
+
}
|
|
841
|
+
/**
|
|
842
|
+
* Create a pill (capsule) collision component.
|
|
843
|
+
*/
|
|
844
|
+
declare function pillCollision(opts?: PillCollisionOptions): CollisionComponent;
|
|
845
|
+
interface PlaneCollisionOptions extends BaseCollisionOptions {
|
|
846
|
+
/** Tile dimensions (default: 10x10) */
|
|
847
|
+
tile?: {
|
|
848
|
+
x: number;
|
|
849
|
+
y: number;
|
|
850
|
+
};
|
|
851
|
+
/** Number of subdivisions per axis (default: 10) */
|
|
852
|
+
subdivisions?: number;
|
|
853
|
+
/** Pre-computed height data for the heightfield */
|
|
854
|
+
heightData?: Float32Array;
|
|
855
|
+
}
|
|
856
|
+
/**
|
|
857
|
+
* Create a plane (heightfield) collision component.
|
|
858
|
+
* For flat planes, pass no heightData — a zeroed heightfield is used.
|
|
859
|
+
*/
|
|
860
|
+
declare function planeCollision(opts?: PlaneCollisionOptions): CollisionComponent;
|
|
861
|
+
interface ZoneCollisionOptions extends BaseCollisionOptions {
|
|
862
|
+
/** Zone dimensions (default: 1x1x1) */
|
|
863
|
+
size?: Vec3;
|
|
864
|
+
}
|
|
865
|
+
/**
|
|
866
|
+
* Create a zone (sensor cuboid) collision component.
|
|
867
|
+
* Always a sensor; static by default.
|
|
868
|
+
*/
|
|
869
|
+
declare function zoneCollision(opts?: ZoneCollisionOptions): CollisionComponent;
|
|
870
|
+
|
|
871
|
+
/**
|
|
872
|
+
* Action interface -- the base contract for all actions.
|
|
873
|
+
*
|
|
874
|
+
* Actions are entity-scoped, self-contained objects that modify entity state
|
|
875
|
+
* over time. They are ticked automatically by the entity update loop.
|
|
876
|
+
*/
|
|
877
|
+
interface Action {
|
|
878
|
+
/** Internal duration in seconds (0 = instant, Infinity = persistent) */
|
|
879
|
+
readonly duration: number;
|
|
880
|
+
/** Whether this action has completed */
|
|
881
|
+
readonly done: boolean;
|
|
882
|
+
/** Whether this action auto-removes when done (set by entity.action()) */
|
|
883
|
+
persistent: boolean;
|
|
884
|
+
/** Advance the action by delta seconds */
|
|
885
|
+
tick(entity: GameEntity<any>, delta: number): void;
|
|
886
|
+
/** Reset the action to its initial state */
|
|
887
|
+
reset(): void;
|
|
888
|
+
}
|
|
889
|
+
|
|
890
|
+
interface CollisionContext<T, O extends GameEntityOptions, TGlobals extends Record<string, unknown> = any> {
|
|
891
|
+
entity: T;
|
|
892
|
+
other: GameEntity<O | any>;
|
|
893
|
+
globals: TGlobals;
|
|
894
|
+
}
|
|
895
|
+
interface CollisionDelegate<T, O extends GameEntityOptions> {
|
|
896
|
+
collision?: ((params: CollisionContext<any, any>) => void)[];
|
|
897
|
+
}
|
|
898
|
+
type IBuilder<BuilderOptions = any> = {
|
|
899
|
+
preBuild: (options: BuilderOptions) => BuilderOptions;
|
|
900
|
+
build: (options: BuilderOptions) => BuilderOptions;
|
|
901
|
+
postBuild: (options: BuilderOptions) => BuilderOptions;
|
|
902
|
+
};
|
|
903
|
+
type GameEntityOptions = {
|
|
904
|
+
name?: string;
|
|
905
|
+
color?: Color;
|
|
906
|
+
size?: Vec3;
|
|
907
|
+
position?: Vec3;
|
|
908
|
+
batched?: boolean;
|
|
909
|
+
collision?: Partial<CollisionOptions>;
|
|
910
|
+
material?: Partial<MaterialOptions>;
|
|
911
|
+
custom?: {
|
|
912
|
+
[key: string]: any;
|
|
913
|
+
};
|
|
914
|
+
collisionType?: string;
|
|
915
|
+
collisionGroup?: string;
|
|
916
|
+
collisionFilter?: string[];
|
|
917
|
+
_builders?: {
|
|
918
|
+
meshBuilder?: IBuilder | EntityMeshBuilder | null;
|
|
919
|
+
collisionBuilder?: IBuilder | EntityCollisionBuilder | null;
|
|
920
|
+
materialBuilder?: MaterialBuilder | null;
|
|
921
|
+
};
|
|
922
|
+
};
|
|
923
|
+
declare abstract class GameEntityLifeCycle {
|
|
924
|
+
abstract _setup(params: SetupContext<this>): void;
|
|
925
|
+
abstract _update(params: UpdateContext<this>): void;
|
|
926
|
+
abstract _destroy(params: DestroyContext<this>): void;
|
|
927
|
+
}
|
|
928
|
+
interface EntityDebugInfo {
|
|
929
|
+
buildInfo: () => Record<string, string>;
|
|
930
|
+
}
|
|
931
|
+
declare class GameEntity<O extends GameEntityOptions> extends BaseNode<O> implements GameEntityLifeCycle, EntityDebugInfo, MoveableEntity, RotatableEntityAPI {
|
|
932
|
+
behaviors: Behavior[];
|
|
933
|
+
group: Group | undefined;
|
|
934
|
+
mesh: Mesh | undefined;
|
|
935
|
+
materials: Material[] | undefined;
|
|
936
|
+
bodyDesc: RigidBodyDesc | null;
|
|
937
|
+
body: RigidBody | null;
|
|
938
|
+
colliderDesc: ColliderDesc | undefined;
|
|
939
|
+
collider: Collider | undefined;
|
|
940
|
+
custom: Record<string, any>;
|
|
941
|
+
/** All collider descriptions for this entity (including primary) */
|
|
942
|
+
colliderDescs: ColliderDesc[];
|
|
943
|
+
/** All colliders attached to this entity's rigid body */
|
|
944
|
+
colliders: Collider[];
|
|
945
|
+
/** Additional meshes for compound visual entities (added via add()) */
|
|
946
|
+
compoundMeshes: Mesh[];
|
|
947
|
+
debugInfo: Record<string, any>;
|
|
948
|
+
debugMaterial: ShaderMaterial | undefined;
|
|
949
|
+
collisionDelegate: CollisionDelegate<this, O>;
|
|
950
|
+
collisionType?: string;
|
|
951
|
+
/** Batch key for instanced rendering (null if not instanced) */
|
|
952
|
+
batchKey: string | null;
|
|
953
|
+
/** Index within the instanced mesh batch */
|
|
954
|
+
instanceId: number;
|
|
955
|
+
/** Whether this entity uses instanced rendering */
|
|
956
|
+
isInstanced: boolean;
|
|
957
|
+
protected eventDelegate: EventEmitterDelegate<EntityEvents>;
|
|
958
|
+
private behaviorRefs;
|
|
959
|
+
transformStore: TransformState;
|
|
960
|
+
moveX: (delta: number) => void;
|
|
961
|
+
moveY: (delta: number) => void;
|
|
962
|
+
moveZ: (delta: number) => void;
|
|
963
|
+
moveXY: (deltaX: number, deltaY: number) => void;
|
|
964
|
+
moveXZ: (deltaX: number, deltaZ: number) => void;
|
|
965
|
+
move: (vector: Vector3) => void;
|
|
966
|
+
resetVelocity: () => void;
|
|
967
|
+
moveForwardXY: (delta: number, rotation2DAngle: number) => void;
|
|
968
|
+
getPosition: () => Vector | null;
|
|
969
|
+
getVelocity: () => Vector | null;
|
|
970
|
+
setPosition: (x: number, y: number, z: number) => void;
|
|
971
|
+
setPositionX: (x: number) => void;
|
|
972
|
+
setPositionY: (y: number) => void;
|
|
973
|
+
setPositionZ: (z: number) => void;
|
|
974
|
+
wrapAroundXY: (boundsX: number, boundsY: number) => void;
|
|
975
|
+
wrapAround3D: (boundsX: number, boundsY: number, boundsZ: number) => void;
|
|
976
|
+
rotateInDirection: (moveVector: Vector3) => void;
|
|
977
|
+
rotateYEuler: (amount: number) => void;
|
|
978
|
+
rotateEuler: (eulerRotation: Vector3) => void;
|
|
979
|
+
rotateX: (delta: number) => void;
|
|
980
|
+
rotateY: (delta: number) => void;
|
|
981
|
+
rotateZ: (delta: number) => void;
|
|
982
|
+
setRotationY: (y: number) => void;
|
|
983
|
+
setRotationX: (x: number) => void;
|
|
984
|
+
setRotationZ: (z: number) => void;
|
|
985
|
+
setRotationDegrees: (x: number, y: number, z: number) => void;
|
|
986
|
+
setRotationDegreesY: (y: number) => void;
|
|
987
|
+
setRotationDegreesX: (x: number) => void;
|
|
988
|
+
setRotationDegreesZ: (z: number) => void;
|
|
989
|
+
setRotation: (x: number, y: number, z: number) => void;
|
|
990
|
+
getRotation: () => any;
|
|
991
|
+
constructor();
|
|
992
|
+
/**
|
|
993
|
+
* Add meshes, collision components, or child entities to this entity.
|
|
994
|
+
* Supports fluent chaining: `entity.add(boxMesh()).add(boxCollision())`.
|
|
995
|
+
*
|
|
996
|
+
* - `Mesh`: First mesh becomes the primary mesh; subsequent meshes are
|
|
997
|
+
* compound meshes grouped together.
|
|
998
|
+
* - `CollisionComponent`: First sets bodyDesc + colliderDesc; subsequent
|
|
999
|
+
* add extra colliders to the same rigid body.
|
|
1000
|
+
* - `NodeInterface`: Added as a child entity (delegates to BaseNode.add).
|
|
1001
|
+
*/
|
|
1002
|
+
add(...components: Array<NodeInterface | Mesh | CollisionComponent>): this;
|
|
1003
|
+
private addMeshComponent;
|
|
1004
|
+
private addCollisionComponent;
|
|
1005
|
+
private _actions;
|
|
1006
|
+
/**
|
|
1007
|
+
* Run a fire-and-forget action. Auto-removed when done.
|
|
1008
|
+
* @example `me.runAction(moveBy({ x: 10, duration: 0.3 }))`
|
|
1009
|
+
*/
|
|
1010
|
+
runAction<A extends Action>(action: A): A;
|
|
1011
|
+
/**
|
|
1012
|
+
* Register a persistent action (throttle, onPress). Not removed when done.
|
|
1013
|
+
* @example `const press = entity.action(onPress())`
|
|
1014
|
+
*/
|
|
1015
|
+
action<A extends Action>(action: A): A;
|
|
1016
|
+
/**
|
|
1017
|
+
* Tick all registered actions. Called automatically before user onUpdate callbacks.
|
|
1018
|
+
*
|
|
1019
|
+
* Resets velocity/angularVelocity accumulation before ticking so that
|
|
1020
|
+
* actions can compose via `+=` without cross-frame build-up.
|
|
1021
|
+
* (The existing move helpers like `moveXY` use `=` which doesn't accumulate,
|
|
1022
|
+
* but action composition needs additive writes on a clean slate each frame.)
|
|
1023
|
+
*/
|
|
1024
|
+
_tickActions(delta: number): void;
|
|
1025
|
+
create(): this;
|
|
1026
|
+
/**
|
|
1027
|
+
* Add collision callbacks
|
|
1028
|
+
*/
|
|
1029
|
+
onCollision(...callbacks: ((params: CollisionContext<this, O>) => void)[]): this;
|
|
1030
|
+
/**
|
|
1031
|
+
* Use a behavior on this entity via typed descriptor.
|
|
1032
|
+
* Behaviors will be auto-registered as systems when the entity is spawned.
|
|
1033
|
+
* @param descriptor The behavior descriptor (import from behaviors module)
|
|
1034
|
+
* @param options Optional overrides for the behavior's default options
|
|
1035
|
+
* @returns BehaviorHandle with behavior-specific methods for lazy FSM access
|
|
1036
|
+
*/
|
|
1037
|
+
use<O extends Record<string, any>, H extends Record<string, any> = Record<string, never>>(descriptor: BehaviorDescriptor<O, H>, options?: Partial<O>): BehaviorHandle<O, H>;
|
|
1038
|
+
/**
|
|
1039
|
+
* Get all behavior references attached to this entity.
|
|
1040
|
+
* Used by the stage to auto-register required systems.
|
|
1041
|
+
*/
|
|
1042
|
+
getBehaviorRefs(): BehaviorRef[];
|
|
1043
|
+
/**
|
|
1044
|
+
* Entity-specific setup - resets actions for a fresh stage session.
|
|
1045
|
+
* (User callbacks are handled by BaseNode's lifecycleCallbacks.setup)
|
|
1046
|
+
*/
|
|
1047
|
+
_setup(params: SetupContext<this>): void;
|
|
1048
|
+
protected _loaded(_params: LoadedContext<this>): Promise<void>;
|
|
1049
|
+
/**
|
|
1050
|
+
* Entity-specific update - updates materials.
|
|
1051
|
+
* Transform changes are applied by the stage after all update callbacks complete.
|
|
1052
|
+
* (User callbacks are handled by BaseNode's lifecycleCallbacks.update)
|
|
1053
|
+
*/
|
|
1054
|
+
_update(params: UpdateContext<this>): void;
|
|
1055
|
+
/**
|
|
1056
|
+
* Entity-specific destroy -- reserved for consumer game logic.
|
|
1057
|
+
* Engine-internal resource disposal runs in _cleanup() instead.
|
|
1058
|
+
*/
|
|
1059
|
+
_destroy(params: DestroyContext<this>): void;
|
|
1060
|
+
/**
|
|
1061
|
+
* Engine-internal resource cleanup -- runs automatically after destroy.
|
|
1062
|
+
* Disposes GPU/DOM resources (meshes, materials, debug material).
|
|
1063
|
+
*
|
|
1064
|
+
* Note: actions, collision callbacks, and behavior refs are intentionally
|
|
1065
|
+
* NOT cleared here -- they are registered by consumer code at module level
|
|
1066
|
+
* and must persist across stage reloads. Actions are reset in _setup().
|
|
1067
|
+
*/
|
|
1068
|
+
protected _cleanup(_params: CleanupContext<this>): void;
|
|
1069
|
+
_collision(other: GameEntity<O>, globals?: any): void;
|
|
1070
|
+
protected updateMaterials(params: any): void;
|
|
1071
|
+
buildInfo(): Record<string, string>;
|
|
1072
|
+
/**
|
|
1073
|
+
* Dispatch an event from this entity.
|
|
1074
|
+
* Events are emitted both locally and to the global event bus.
|
|
1075
|
+
*/
|
|
1076
|
+
dispatch<K extends keyof EntityEvents>(event: K, payload: EntityEvents[K]): void;
|
|
1077
|
+
/**
|
|
1078
|
+
* Listen for events on this entity instance.
|
|
1079
|
+
* @returns Unsubscribe function
|
|
1080
|
+
*/
|
|
1081
|
+
listen<K extends keyof EntityEvents>(event: K, handler: (payload: EntityEvents[K]) => void): () => void;
|
|
1082
|
+
/**
|
|
1083
|
+
* Clean up entity event subscriptions.
|
|
1084
|
+
*/
|
|
1085
|
+
disposeEvents(): void;
|
|
1086
|
+
}
|
|
1087
|
+
/**
|
|
1088
|
+
* Create a bare entity with no mesh or collision.
|
|
1089
|
+
* Use `.add(boxMesh(), boxCollision())` to compose its shape.
|
|
1090
|
+
*
|
|
1091
|
+
* @example
|
|
1092
|
+
* ```ts
|
|
1093
|
+
* const box = create({ position: { x: 0, y: 5, z: 0 } })
|
|
1094
|
+
* .add(boxMesh({ size: { x: 2, y: 2, z: 2 } }))
|
|
1095
|
+
* .add(boxCollision({ size: { x: 2, y: 2, z: 2 } }));
|
|
1096
|
+
* ```
|
|
1097
|
+
*/
|
|
1098
|
+
declare function create(options?: Partial<GameEntityOptions>): GameEntity<GameEntityOptions>;
|
|
1099
|
+
|
|
1100
|
+
export { sphereCollision as $, type Action as A, setRotationZ as B, setRotationDegrees as C, setRotationDegreesY as D, setRotationDegreesX as E, setRotationDegreesZ as F, setRotation as G, getRotation as H, GameEntity as I, type UpdateFunction as J, type DestroyFunction as K, type SetupContext as L, type DestroyContext as M, BaseNode as N, type LoadingEvent as O, type GameEntityOptions as P, type StageEvents as Q, type MaterialOptions as R, type SetupFunction as S, type TransformState as T, type UpdateContext as U, type Vec3 as V, type MoveableEntity as W, type InputPlayer as X, create as Y, type ZylemShader as Z, boxCollision as _, moveX as a, coneCollision as a0, pyramidCollision as a1, cylinderCollision as a2, pillCollision as a3, planeCollision as a4, zoneCollision as a5, type CollisionComponent as a6, EventEmitterDelegate as a7, zylemEventBus as a8, type ZylemEvents as a9, type GameEvents as aa, type EntityEvents as ab, type GameLoadingPayload as ac, type StateDispatchPayload as ad, type StageConfigPayload as ae, type EntityConfigPayload as af, type ZylemShaderObject as ag, type ZylemTSLShader as ah, isTSLShader as ai, isGLSLShader as aj, type InputPlayerNumber as ak, type InputProvider as al, type Inputs as am, GameEntityLifeCycle as an, type IGame as ao, type LoadedContext as ap, type CleanupContext as aq, type NodeInterface as ar, type TexturePath as as, moveY as b, createTransformStore as c, moveZ as d, moveXY as e, moveXZ as f, resetVelocity as g, moveForwardXY as h, getPosition as i, getVelocity as j, setPositionX as k, setPositionY as l, move as m, setPositionZ as n, wrapAround3D as o, rotateInDirection as p, rotateYEuler as q, resetTransformStore as r, setPosition as s, rotateEuler as t, rotateX as u, rotateY as v, wrapAroundXY as w, rotateZ as x, setRotationY as y, setRotationX as z };
|