@zylem/game-lib 0.6.2 → 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.
Files changed (54) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +9 -16
  3. package/dist/actions.d.ts +30 -21
  4. package/dist/actions.js +628 -145
  5. package/dist/actions.js.map +1 -1
  6. package/dist/behavior/platformer-3d.d.ts +296 -0
  7. package/dist/behavior/platformer-3d.js +518 -0
  8. package/dist/behavior/platformer-3d.js.map +1 -0
  9. package/dist/behavior/ricochet-2d.d.ts +274 -0
  10. package/dist/behavior/ricochet-2d.js +394 -0
  11. package/dist/behavior/ricochet-2d.js.map +1 -0
  12. package/dist/behavior/screen-wrap.d.ts +86 -0
  13. package/dist/behavior/screen-wrap.js +195 -0
  14. package/dist/behavior/screen-wrap.js.map +1 -0
  15. package/dist/behavior/thruster.d.ts +10 -0
  16. package/dist/behavior/thruster.js +234 -0
  17. package/dist/behavior/thruster.js.map +1 -0
  18. package/dist/behavior/world-boundary-2d.d.ts +141 -0
  19. package/dist/behavior/world-boundary-2d.js +181 -0
  20. package/dist/behavior/world-boundary-2d.js.map +1 -0
  21. package/dist/behavior-descriptor-BWNWmIjv.d.ts +142 -0
  22. package/dist/{blueprints-Cq3Ko6_G.d.ts → blueprints-BWGz8fII.d.ts} +2 -2
  23. package/dist/camera-B5e4c78l.d.ts +468 -0
  24. package/dist/camera.d.ts +3 -2
  25. package/dist/camera.js +900 -211
  26. package/dist/camera.js.map +1 -1
  27. package/dist/composition-DrzFrbqI.d.ts +218 -0
  28. package/dist/{core-bO8TzV7u.d.ts → core-DAkskq6Y.d.ts} +60 -62
  29. package/dist/core.d.ts +10 -6
  30. package/dist/core.js +6896 -5020
  31. package/dist/core.js.map +1 -1
  32. package/dist/{entities-DvByhMGU.d.ts → entities-DC9ce_vx.d.ts} +113 -3
  33. package/dist/entities.d.ts +5 -3
  34. package/dist/entities.js +3727 -3167
  35. package/dist/entities.js.map +1 -1
  36. package/dist/entity-BpbZqg19.d.ts +1100 -0
  37. package/dist/global-change-Dc8uCKi2.d.ts +25 -0
  38. package/dist/main.d.ts +418 -15
  39. package/dist/main.js +11384 -8515
  40. package/dist/main.js.map +1 -1
  41. package/dist/{stage-types-Bd-KtcYT.d.ts → stage-types-BFsm3qsZ.d.ts} +205 -13
  42. package/dist/stage.d.ts +10 -7
  43. package/dist/stage.js +5311 -3880
  44. package/dist/stage.js.map +1 -1
  45. package/dist/thruster-DhRaJnoL.d.ts +172 -0
  46. package/dist/world-Be5m1XC1.d.ts +31 -0
  47. package/package.json +29 -13
  48. package/dist/behaviors.d.ts +0 -854
  49. package/dist/behaviors.js +0 -1209
  50. package/dist/behaviors.js.map +0 -1
  51. package/dist/camera-CeJPAgGg.d.ts +0 -116
  52. package/dist/moveable-B_vyA6cw.d.ts +0 -67
  53. package/dist/transformable-CUhvyuYO.d.ts +0 -67
  54. package/dist/world-C8tQ7Plj.d.ts +0 -774
@@ -0,0 +1,25 @@
1
+ import { U as UpdateContext } from './entity-BpbZqg19.js';
2
+
3
+ /**
4
+ * Listen for a single global key change inside an onUpdate pipeline.
5
+ * Usage: onUpdate(globalChange('p1Score', (value) => { ... }))
6
+ */
7
+ declare function globalChange<T = any>(key: string, callback: (value: T, ctx: UpdateContext<any>) => void): (ctx: UpdateContext<any>) => void;
8
+ /**
9
+ * Listen for multiple global key changes inside an onUpdate pipeline.
10
+ * Calls back when any of the provided keys changes.
11
+ * Usage: onUpdate(globalChanges(['p1Score','p2Score'], ([p1,p2]) => { ... }))
12
+ */
13
+ declare function globalChanges<T = any>(keys: string[], callback: (values: T[], ctx: UpdateContext<any>) => void): (ctx: UpdateContext<any>) => void;
14
+ /**
15
+ * Listen for a single stage variable change inside an onUpdate pipeline.
16
+ * Usage: onUpdate(variableChange('score', (value, ctx) => { ... }))
17
+ */
18
+ declare function variableChange<T = any>(key: string, callback: (value: T, ctx: UpdateContext<any>) => void): (ctx: UpdateContext<any>) => void;
19
+ /**
20
+ * Listen for multiple stage variable changes; fires when any changes.
21
+ * Usage: onUpdate(variableChanges(['a','b'], ([a,b], ctx) => { ... }))
22
+ */
23
+ declare function variableChanges<T = any>(keys: string[], callback: (values: T[], ctx: UpdateContext<any>) => void): (ctx: UpdateContext<any>) => void;
24
+
25
+ export { globalChanges as a, variableChanges as b, globalChange as g, variableChange as v };
package/dist/main.d.ts CHANGED
@@ -1,24 +1,37 @@
1
- import { G as Game } from './core-bO8TzV7u.js';
2
- export { V as Vect3, Z as ZylemGameConfig, c as createGame, g as gameConfig, a as globalChange, b as globalChanges, d as variableChange, e as variableChanges, v as vessel } from './core-bO8TzV7u.js';
3
- export { a as StageOptions, d as createDisk, c as createStage } from './stage-types-Bd-KtcYT.js';
4
- import { S as StageBlueprint } from './blueprints-Cq3Ko6_G.js';
5
- export { e as entitySpawner } from './blueprints-Cq3Ko6_G.js';
6
- export { P as PerspectiveType, d as Perspectives, c as createCamera } from './camera-CeJPAgGg.js';
7
- export { A as ACTOR_TYPE, B as BOX_TYPE, P as PLANE_TYPE, R as RECT_TYPE, a as SPHERE_TYPE, S as SPRITE_TYPE, T as TEXT_TYPE, g as ZONE_TYPE, e as ZylemBox, o as createActor, j as createBox, m as createPlane, q as createRect, k as createSphere, l as createSprite, p as createText, n as createZone } from './entities-DvByhMGU.js';
8
- import { G as GameEntity, g as GameEntityOptions } from './world-C8tQ7Plj.js';
9
- export { q as BehaviorDescriptor, s as BehaviorHandle, r as BehaviorRef, e as BehaviorSystem, f as BehaviorSystemFactory, t as DefineBehaviorConfig, o as EntityConfigPayload, k as EntityEvents, E as EventEmitterDelegate, j as GameEvents, l as GameLoadingPayload, L as LoadingEvent, a as SetupContext, n as StageConfigPayload, h as StageEvents, m as StateDispatchPayload, b as UpdateContext, i as ZylemEvents, Z as ZylemShaderObject, p as defineBehavior, z as zylemEventBus } from './world-C8tQ7Plj.js';
10
- export { Behavior, BoundaryRicochetCoordinator, MovementSequence2DBehavior, MovementSequence2DCurrentStep, MovementSequence2DEvent, MovementSequence2DFSM, MovementSequence2DHandle, MovementSequence2DMovement, MovementSequence2DOptions, MovementSequence2DProgress, MovementSequence2DState, MovementSequence2DStep, PhysicsBodyComponent, PhysicsStepBehavior, PhysicsSyncBehavior, PlayerInput, Ricochet2DBehavior, Ricochet2DCollisionContext, Ricochet2DEvent, Ricochet2DFSM, Ricochet2DHandle, Ricochet2DOptions, Ricochet2DResult, Ricochet2DState, ScreenWrapBehavior, ScreenWrapEvent, ScreenWrapFSM, ScreenWrapOptions, ScreenWrapState, ThrusterBehavior, ThrusterBehaviorOptions, ThrusterEntity, ThrusterEvent, ThrusterFSM, ThrusterFSMContext, ThrusterInputComponent, ThrusterMovementBehavior, ThrusterMovementComponent, ThrusterState, ThrusterStateComponent, TransformComponent, WorldBoundary2DBehavior, WorldBoundary2DBounds, WorldBoundary2DEvent, WorldBoundary2DFSM, WorldBoundary2DHandle, WorldBoundary2DHit, WorldBoundary2DHits, WorldBoundary2DOptions, WorldBoundary2DPosition, WorldBoundary2DState, computeWorldBoundary2DHits, createPhysicsBodyComponent, createThrusterInputComponent, createThrusterMovementComponent, createThrusterStateComponent, createTransformComponent, hasAnyWorldBoundary2DHit, useBehavior } from './behaviors.js';
11
- export { m as makeMoveable, b as move, a as moveable, r as resetVelocity } from './moveable-B_vyA6cw.js';
12
- export { m as makeRotatable, a as makeTransformable, r as rotatable, b as rotateInDirection } from './transformable-CUhvyuYO.js';
13
- export { Howl } from 'howler';
1
+ import { G as Game } from './core-DAkskq6Y.js';
2
+ export { V as Vect3, c as createGame, g as gameConfig, v as vessel } from './core-DAkskq6Y.js';
3
+ import { G as GameInputConfig } from './stage-types-BFsm3qsZ.js';
4
+ export { a as StageOptions, Z as ZylemGameConfig, d as createDisk, c as createStage } from './stage-types-BFsm3qsZ.js';
5
+ import { S as StageBlueprint } from './blueprints-BWGz8fII.js';
6
+ export { e as entitySpawner } from './blueprints-BWGz8fII.js';
7
+ export { C as CameraManager, e as CameraOptions, c as CameraWrapper, P as PerspectiveType, f as Perspectives, g as RendererType, V as Viewport, h as ZylemRenderer, d as createCamera, i as isWebGPUSupported } from './camera-B5e4c78l.js';
8
+ export { A as ACTOR_TYPE, B as BOX_TYPE, C as CONE_TYPE, m as CYLINDER_TYPE, o as PILL_TYPE, P as PLANE_TYPE, k as PYRAMID_TYPE, R as RECT_TYPE, a as SPHERE_TYPE, S as SPRITE_TYPE, T as TEXT_TYPE, g as ZONE_TYPE, e as ZylemBox, v as createActor, q as createBox, y as createCone, D as createCylinder, E as createPill, t as createPlane, z as createPyramid, x as createRect, r as createSphere, s as createSprite, w as createText, u as createZone } from './entities-DC9ce_vx.js';
9
+ import { I as GameEntity, P as GameEntityOptions, V as Vec3, R as MaterialOptions, W as MoveableEntity, N as BaseNode, X as InputPlayer } from './entity-BpbZqg19.js';
10
+ export { A as Action, a6 as CollisionComponent, af as EntityConfigPayload, ab as EntityEvents, a7 as EventEmitterDelegate, aa as GameEvents, ac as GameLoadingPayload, O as LoadingEvent, L as SetupContext, ae as StageConfigPayload, Q as StageEvents, ad as StateDispatchPayload, U as UpdateContext, a9 as ZylemEvents, Z as ZylemShader, ag as ZylemShaderObject, ah as ZylemTSLShader, _ as boxCollision, a0 as coneCollision, Y as create, a2 as cylinderCollision, aj as isGLSLShader, ai as isTSLShader, m as move, a3 as pillCollision, a4 as planeCollision, a1 as pyramidCollision, g as resetVelocity, p as rotateInDirection, $ as sphereCollision, a5 as zoneCollision, a8 as zylemEventBus } from './entity-BpbZqg19.js';
11
+ import { Color, Mesh, Vector2 } from 'three';
14
12
  import * as three from 'three';
15
13
  export { three as THREE };
14
+ import { b as BehaviorDescriptor } from './behavior-descriptor-BWNWmIjv.js';
15
+ export { c as BehaviorHandle, d as BehaviorRef, B as BehaviorSystem, a as BehaviorSystemFactory, D as DefineBehaviorConfig, e as defineBehavior } from './behavior-descriptor-BWNWmIjv.js';
16
+ export { B as Behavior, P as PhysicsBodyComponent, m as PlayerInput, p as ThrusterBehavior, q as ThrusterBehaviorOptions, o as ThrusterEntity, j as ThrusterEvent, k as ThrusterFSM, l as ThrusterFSMContext, d as ThrusterInputComponent, n as ThrusterMovementBehavior, b as ThrusterMovementComponent, i as ThrusterState, e as ThrusterStateComponent, T as TransformComponent, a as createPhysicsBodyComponent, g as createThrusterInputComponent, f as createThrusterMovementComponent, h as createThrusterStateComponent, c as createTransformComponent } from './thruster-DhRaJnoL.js';
17
+ export { ScreenWrapBehavior, ScreenWrapEvent, ScreenWrapFSM, ScreenWrapOptions, ScreenWrapState } from './behavior/screen-wrap.js';
18
+ import { WorldBoundary2DHandle } from './behavior/world-boundary-2d.js';
19
+ export { WorldBoundary2DBehavior, WorldBoundary2DBounds, WorldBoundary2DEvent, WorldBoundary2DFSM, WorldBoundary2DHit, WorldBoundary2DHits, WorldBoundary2DOptions, WorldBoundary2DPosition, WorldBoundary2DState, computeWorldBoundary2DHits, hasAnyWorldBoundary2DHit } from './behavior/world-boundary-2d.js';
20
+ import { Ricochet2DHandle } from './behavior/ricochet-2d.js';
21
+ export { Ricochet2DBehavior, Ricochet2DCollisionContext, Ricochet2DEvent, Ricochet2DFSM, Ricochet2DOptions, Ricochet2DResult, Ricochet2DState, RicochetCallback } from './behavior/ricochet-2d.js';
22
+ export { Platformer3DBehavior, Platformer3DBehaviorOptions, Platformer3DContext, Platformer3DEntity, Platformer3DEvent, Platformer3DFSM, Platformer3DInputComponent, Platformer3DMovementBehavior, Platformer3DMovementComponent, Platformer3DState, Platformer3DStateComponent, PlatformerCollisionContext, createPlatformer3DInputComponent, createPlatformer3DMovementComponent, createPlatformer3DStateComponent } from './behavior/platformer-3d.js';
23
+ export { c as callFunc, d as delay, m as moveBy, a as moveTo, o as onPress, b as onRelease, p as parallel, e as repeat, f as repeatForever, r as rotateBy, s as sequence, t as throttle } from './composition-DrzFrbqI.js';
24
+ export { Howl } from 'howler';
16
25
  import * as RAPIER from '@dimforge/rapier3d-compat';
17
26
  export { RAPIER };
27
+ export { g as globalChange, a as globalChanges, v as variableChange, b as variableChanges } from './global-change-Dc8uCKi2.js';
18
28
  export { S as StageEntity } from './entity-Bq_eNEDI.js';
29
+ export { Fn, float, time, uniform, uv, vec3, vec4 } from 'three/tsl';
19
30
  import 'bitecs';
31
+ import './world-Be5m1XC1.js';
20
32
  import './entity-types-DAu8sGJH.js';
21
33
  import '@sinclair/typebox';
34
+ import 'three/webgpu';
22
35
  import 'three/examples/jsm/postprocessing/EffectComposer.js';
23
36
  import 'mitt';
24
37
  import 'typescript-fsm';
@@ -39,8 +52,8 @@ declare const StageManager: {
39
52
  data?: {
40
53
  [x: string]: any;
41
54
  } | undefined;
42
- type: string;
43
55
  id: string;
56
+ type: string;
44
57
  }[];
45
58
  }>;
46
59
  registerStaticStage(id: string, blueprint: StageBlueprint): void;
@@ -85,6 +98,357 @@ interface TemplateFactory<E extends GameEntity<O>, O extends GameEntityOptions =
85
98
  */
86
99
  declare function createEntityFactory<E extends GameEntity<O>, O extends GameEntityOptions = GameEntityOptions>(template: E): TemplateFactory<E, O>;
87
100
 
101
+ /** Shared options that every mesh factory accepts. */
102
+ interface BaseMeshOptions {
103
+ /** Offset position relative to the entity origin */
104
+ position?: Vec3;
105
+ /** Material options (texture, shader, etc.) */
106
+ material?: Partial<MaterialOptions>;
107
+ /** Convenience color override */
108
+ color?: Color;
109
+ }
110
+ interface BoxMeshOptions extends BaseMeshOptions {
111
+ /** Box dimensions (default: 1x1x1) */
112
+ size?: Vec3;
113
+ }
114
+ /**
115
+ * Create a box mesh.
116
+ */
117
+ declare function boxMesh(opts?: BoxMeshOptions): Mesh;
118
+ interface SphereMeshOptions extends BaseMeshOptions {
119
+ /** Sphere radius (default: 1) */
120
+ radius?: number;
121
+ }
122
+ /**
123
+ * Create a sphere mesh.
124
+ */
125
+ declare function sphereMesh(opts?: SphereMeshOptions): Mesh;
126
+ interface ConeMeshOptions extends BaseMeshOptions {
127
+ /** Base radius (default: 1) */
128
+ radius?: number;
129
+ /** Height (default: 2) */
130
+ height?: number;
131
+ /** Radial segments (default: 32) */
132
+ radialSegments?: number;
133
+ }
134
+ /**
135
+ * Create a cone mesh.
136
+ */
137
+ declare function coneMesh(opts?: ConeMeshOptions): Mesh;
138
+ interface PyramidMeshOptions extends BaseMeshOptions {
139
+ /** Base radius (default: 1) */
140
+ radius?: number;
141
+ /** Height (default: 2) */
142
+ height?: number;
143
+ }
144
+ /**
145
+ * Create a pyramid mesh (4-sided cone).
146
+ */
147
+ declare function pyramidMesh(opts?: PyramidMeshOptions): Mesh;
148
+ interface CylinderMeshOptions extends BaseMeshOptions {
149
+ /** Top radius (default: 1) */
150
+ radiusTop?: number;
151
+ /** Bottom radius (default: 1) */
152
+ radiusBottom?: number;
153
+ /** Height (default: 2) */
154
+ height?: number;
155
+ /** Radial segments (default: 32) */
156
+ radialSegments?: number;
157
+ }
158
+ /**
159
+ * Create a cylinder mesh.
160
+ */
161
+ declare function cylinderMesh(opts?: CylinderMeshOptions): Mesh;
162
+ interface PillMeshOptions extends BaseMeshOptions {
163
+ /** Capsule hemisphere radius (default: 0.5) */
164
+ radius?: number;
165
+ /** Cylindrical section length (default: 1) */
166
+ length?: number;
167
+ /** Cap segments (default: 10) */
168
+ capSegments?: number;
169
+ /** Radial segments (default: 20) */
170
+ radialSegments?: number;
171
+ }
172
+ /**
173
+ * Create a pill (capsule) mesh.
174
+ */
175
+ declare function pillMesh(opts?: PillMeshOptions): Mesh;
176
+
177
+ /**
178
+ * Type-safe helper to apply a behavior to an entity and return the entity cast to the behavior's interface.
179
+ *
180
+ * @param entity The entity to apply the behavior to
181
+ * @param descriptor The behavior descriptor
182
+ * @param options Behavior options
183
+ * @returns The entity, cast to E & I (where I is the behavior's interface)
184
+ */
185
+ declare function useBehavior<E extends GameEntity<any>, O extends Record<string, any>, H extends Record<string, any>, I>(entity: E, descriptor: BehaviorDescriptor<O, H, I>, options?: Partial<O>): E & I;
186
+
187
+ /**
188
+ * CooldownBehavior
189
+ *
190
+ * A stage-scoped behavior that manages named cooldowns via the global CooldownStore.
191
+ * Entities use this to register, check, and fire cooldowns.
192
+ * UI components (CooldownIcon) can read from the same store.
193
+ */
194
+ interface CooldownConfig {
195
+ /** Duration in seconds */
196
+ duration: number;
197
+ /** Whether the cooldown starts ready (default: true) */
198
+ immediate?: boolean;
199
+ }
200
+ interface CooldownOptions {
201
+ /**
202
+ * Named cooldowns to register.
203
+ * Keys are the cooldown names, values are their config.
204
+ */
205
+ cooldowns: Record<string, CooldownConfig>;
206
+ }
207
+ /**
208
+ * Handle methods returned by entity.use(CooldownBehavior, ...).
209
+ */
210
+ interface CooldownHandle {
211
+ /** Check if a named cooldown is ready */
212
+ isReady(name: string): boolean;
213
+ /** Fire (trigger) a named cooldown, resetting its timer */
214
+ fire(name: string): void;
215
+ /** Force a cooldown to ready immediately */
216
+ reset(name: string): void;
217
+ /** Get cooldown progress 0..1 (0 = just fired, 1 = ready) */
218
+ getProgress(name: string): number;
219
+ }
220
+ /**
221
+ * CooldownBehavior
222
+ *
223
+ * @example
224
+ * ```ts
225
+ * import { CooldownBehavior, moveBy } from '@zylem/game-lib';
226
+ *
227
+ * const hero = createBox({ ... });
228
+ * const cd = hero.use(CooldownBehavior, {
229
+ * cooldowns: {
230
+ * attack: { duration: 5 },
231
+ * dash: { duration: 2, immediate: false },
232
+ * },
233
+ * });
234
+ *
235
+ * hero.onUpdate(({ me, inputs }) => {
236
+ * if (cd.isReady('attack') && inputs.p1.buttons.A.pressed) {
237
+ * cd.fire('attack');
238
+ * // perform attack
239
+ * }
240
+ * if (cd.isReady('dash') && inputs.p1.buttons.B.pressed) {
241
+ * cd.fire('dash');
242
+ * me.runAction(moveBy({ x: 10, duration: 0.3 }));
243
+ * }
244
+ * });
245
+ * ```
246
+ */
247
+ declare const CooldownBehavior: BehaviorDescriptor<CooldownOptions, CooldownHandle, unknown>;
248
+
249
+ /**
250
+ * A single cooldown entry in the global store.
251
+ */
252
+ interface CooldownEntry {
253
+ /** Identifier for this cooldown */
254
+ name: string;
255
+ /** Total cooldown time in seconds */
256
+ duration: number;
257
+ /** Time accumulated since last fire */
258
+ elapsed: number;
259
+ /** Whether the cooldown is ready (elapsed >= duration) */
260
+ ready: boolean;
261
+ /** Normalized progress 0..1 (0 = just fired, 1 = ready) */
262
+ progress: number;
263
+ /** Whether this cooldown is currently counting down */
264
+ active: boolean;
265
+ }
266
+ /**
267
+ * Register a named cooldown in the global store.
268
+ * If a cooldown with the same name already exists, it is overwritten.
269
+ *
270
+ * @param name Unique cooldown identifier
271
+ * @param duration Cooldown duration in seconds
272
+ * @param immediate If true, the cooldown starts ready (default: true)
273
+ */
274
+ declare function registerCooldown(name: string, duration: number, immediate?: boolean): void;
275
+ /**
276
+ * Get a cooldown entry by name.
277
+ * Returns undefined if the cooldown has not been registered.
278
+ */
279
+ declare function getCooldown(name: string): CooldownEntry | undefined;
280
+ /**
281
+ * Fire (trigger) a cooldown, resetting its timer.
282
+ * Sets the cooldown to not-ready and starts the countdown.
283
+ */
284
+ declare function fireCooldown(name: string): void;
285
+ /**
286
+ * Force a cooldown to ready immediately.
287
+ */
288
+ declare function resetCooldown(name: string): void;
289
+ /**
290
+ * Advance all active cooldowns by delta seconds.
291
+ * Called once per frame by the CooldownBehavior system.
292
+ */
293
+ declare function tickCooldowns(delta: number): void;
294
+ /**
295
+ * Get the raw cooldown store (for advanced/debugging use).
296
+ */
297
+ declare function getCooldownStore(): Record<string, CooldownEntry>;
298
+
299
+ /**
300
+ * Coordinator that bridges WorldBoundary2DBehavior and Ricochet2DBehavior.
301
+ *
302
+ * Automatically handles:
303
+ * 1. Checking boundary hits
304
+ * 2. Computing collision normals
305
+ * 3. Requesting ricochet result
306
+ * 4. Applying movement
307
+ */
308
+ declare class BoundaryRicochetCoordinator {
309
+ private entity;
310
+ private boundary;
311
+ private ricochet;
312
+ constructor(entity: GameEntity<any> & MoveableEntity, boundary: WorldBoundary2DHandle, ricochet: Ricochet2DHandle);
313
+ /**
314
+ * Update loop - call this every frame.
315
+ * Applies ricochet via transformStore and notifies listeners.
316
+ *
317
+ * @returns true if ricochet was applied, false otherwise
318
+ */
319
+ update(): boolean;
320
+ }
321
+
322
+ /**
323
+ * CooldownIcon -- a WoW-style cooldown icon UI entity.
324
+ *
325
+ * Renders a square icon with a semi-transparent clockwise sweep overlay
326
+ * that reflects cooldown progress from the CooldownStore. Optionally shows
327
+ * remaining time text in the center.
328
+ *
329
+ * Modeled after ZylemRect's canvas-based viewport-attached sprite pattern.
330
+ */
331
+
332
+ /**
333
+ * Reference point on the viewport for positioning UI elements.
334
+ * The offset in `screenPosition` is applied relative to this anchor.
335
+ */
336
+ type ScreenAnchor = 'top-left' | 'top-center' | 'top-right' | 'center-left' | 'center' | 'center-right' | 'bottom-left' | 'bottom-center' | 'bottom-right';
337
+ /** Preset icon sizes in view units. */
338
+ declare const ICON_SIZE_PRESETS: {
339
+ readonly xs: 8;
340
+ readonly sm: 16;
341
+ readonly md: 32;
342
+ readonly lg: 48;
343
+ readonly xl: 64;
344
+ };
345
+ /** Named size preset. */
346
+ type IconSizePreset = keyof typeof ICON_SIZE_PRESETS;
347
+ /**
348
+ * Icon size expressed as a named preset, a square unit value, or
349
+ * a `{ width, height }` object for non-square icons.
350
+ *
351
+ * All numeric values are in **view units** (viewport height = 192 units).
352
+ */
353
+ type IconSize = IconSizePreset | number | {
354
+ width: number;
355
+ height: number;
356
+ };
357
+ type ZylemCooldownIconOptions = GameEntityOptions & {
358
+ /** Name of the cooldown in the CooldownStore */
359
+ cooldown: string;
360
+ /** Texture path for the icon background (optional) */
361
+ icon?: string;
362
+ /** Solid fill color when no icon texture is provided */
363
+ fillColor?: Color | string;
364
+ /**
365
+ * Size of the icon in view units, a named preset, or a `{ width, height }` object.
366
+ *
367
+ * Presets: `'xs'` (8), `'sm'` (16), `'md'` (32), `'lg'` (48), `'xl'` (64).
368
+ * A bare number creates a square icon of that many units.
369
+ * The viewport height equals 192 units; width scales with aspect ratio.
370
+ *
371
+ * @default 'md'
372
+ */
373
+ iconSize?: IconSize;
374
+ /** Whether to show remaining time text */
375
+ showTimer?: boolean;
376
+ /** Whether to attach to the camera viewport (default: true) */
377
+ stickToViewport?: boolean;
378
+ /**
379
+ * Viewport anchor the icon is positioned relative to.
380
+ * @default 'top-left'
381
+ */
382
+ screenAnchor?: ScreenAnchor;
383
+ /**
384
+ * Offset from the {@link screenAnchor} in **view units**.
385
+ * Positive x = right, positive y = down.
386
+ * Accepts a `Vector2` or a plain `{ x, y }` object.
387
+ * @default { x: 0, y: 0 }
388
+ */
389
+ screenPosition?: Vector2 | {
390
+ x: number;
391
+ y: number;
392
+ };
393
+ /** Distance from camera (default: 1) */
394
+ zDistance?: number;
395
+ /** Color of the sweep overlay (default: semi-transparent black) */
396
+ overlayColor?: string;
397
+ };
398
+ declare class ZylemCooldownIcon extends GameEntity<ZylemCooldownIconOptions> {
399
+ static type: symbol;
400
+ private _sprite;
401
+ private _texture;
402
+ private _canvas;
403
+ private _ctx;
404
+ private _cameraRef;
405
+ private _iconTexture;
406
+ private _iconImage;
407
+ private _lastRenderedProgress;
408
+ constructor(options?: ZylemCooldownIconOptions);
409
+ private createSprite;
410
+ private redraw;
411
+ private toCssColor;
412
+ private getResolution;
413
+ private iconSetup;
414
+ private iconUpdate;
415
+ /**
416
+ * Resolve screen position to pixels.
417
+ * Computes the anchor point in pixels, then adds the view-unit offset.
418
+ */
419
+ private resolveScreenPosition;
420
+ /**
421
+ * Resolve `iconSize` to screen pixels using the view-unit grid.
422
+ * Viewport height = {@link VIEW_UNITS_HEIGHT} units; width scales with aspect ratio.
423
+ */
424
+ private resolveIconSize;
425
+ /** Compute the world-space half-extents at a given distance from the camera. */
426
+ private computeWorldExtents;
427
+ private updateStickyTransform;
428
+ /**
429
+ * Dispose Three.js / DOM resources when the entity is destroyed.
430
+ */
431
+ private iconDestroy;
432
+ }
433
+ type CooldownIconOptions = BaseNode | Partial<ZylemCooldownIconOptions>;
434
+ /**
435
+ * Create a WoW-style cooldown icon UI entity.
436
+ *
437
+ * @example
438
+ * ```ts
439
+ * const attackIcon = createCooldownIcon({
440
+ * cooldown: 'attack',
441
+ * icon: swordIconPath,
442
+ * screenAnchor: 'top-center', // reference point on the viewport
443
+ * screenPosition: { x: 0, y: 10 }, // offset in view units from anchor
444
+ * iconSize: 'sm', // preset (16 × 16 view units)
445
+ * // iconSize: 24, // square (24 × 24 view units)
446
+ * // iconSize: { width: 16, height: 24 }, // custom rectangle
447
+ * });
448
+ * ```
449
+ */
450
+ declare function createCooldownIcon(...args: Array<CooldownIconOptions>): ZylemCooldownIcon;
451
+
88
452
  declare function destroy(entity: any, globals?: any): void;
89
453
 
90
454
  /**
@@ -97,6 +461,45 @@ declare function ricochetSound(frequency?: number, duration?: number): void;
97
461
  */
98
462
  declare function pingPongBeep(frequency?: number, duration?: number): void;
99
463
 
464
+ /**
465
+ * Maps arrow keys to axes (Horizontal/Vertical) for the given player.
466
+ * @example stage.setInputConfiguration(useArrowsForAxes('p1'));
467
+ */
468
+ declare function useArrowsForAxes(player: InputPlayer): GameInputConfig;
469
+ /**
470
+ * Maps arrow keys to directions (Up/Down/Left/Right) for the given player.
471
+ * Useful when `includeDefaults` is false and you still want arrow-key directions.
472
+ * @example stage.setInputConfiguration(useArrowsForDirections('p1'));
473
+ */
474
+ declare function useArrowsForDirections(player: InputPlayer): GameInputConfig;
475
+ /**
476
+ * Maps W/A/S/D keys to directions (Up/Down/Left/Right) for the given player.
477
+ * @example stage.setInputConfiguration(useWASDForDirections('p1'));
478
+ */
479
+ declare function useWASDForDirections(player: InputPlayer): GameInputConfig;
480
+ /**
481
+ * Maps W/A/S/D keys to axes (Horizontal/Vertical) for the given player.
482
+ * @example stage.setInputConfiguration(useWASDForAxes('p1'));
483
+ */
484
+ declare function useWASDForAxes(player: InputPlayer): GameInputConfig;
485
+ /**
486
+ * Maps I/J/K/L keys to axes (Horizontal/Vertical) for the given player.
487
+ * @example stage.setInputConfiguration(useIJKLForAxes('p1'));
488
+ */
489
+ declare function useIJKLForAxes(player: InputPlayer): GameInputConfig;
490
+ /**
491
+ * Maps I/J/K/L keys to directions (Up/Down/Left/Right) for the given player.
492
+ * @example stage.setInputConfiguration(useIJKLForDirections('p1'));
493
+ */
494
+ declare function useIJKLForDirections(player: InputPlayer): GameInputConfig;
495
+ /**
496
+ * Deep-merges multiple GameInputConfig objects into one.
497
+ * At the player level, configs are merged (both apply).
498
+ * At the key level, later configs win on conflict.
499
+ * @example mergeInputConfigs(useArrowsForAxes('p1'), useWASDForDirections('p1'));
500
+ */
501
+ declare function mergeInputConfigs(...configs: GameInputConfig[]): GameInputConfig;
502
+
100
503
  /**
101
504
  * Set a global value by path.
102
505
  * Emits a 'game:state:updated' event when the value changes.
@@ -248,4 +651,4 @@ declare const debugShader: {
248
651
 
249
652
  declare const objectVertexShader = "\nuniform vec2 uvScale;\nvarying vec2 vUv;\n\nvoid main() {\n\tvUv = uv;\n\tvec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );\n\tgl_Position = projectionMatrix * mvPosition;\n}\n";
250
653
 
251
- export { type DebugTools, Game, StageBlueprint, StageManager, type TemplateFactory, ZylemGameElement, type ZylemGameState, clearGlobalSubscriptions, createEntityFactory, createGlobal, createVariable, debugShader, debugState, destroy, fireShader, getGlobal, getGlobals, getVariable, objectVertexShader, onGlobalChange, onGlobalChanges, onVariableChange, onVariableChanges, pingPongBeep, ricochetSound, setDebugTool, setGlobal, setPaused, setVariable, stageState, standardShader, starShader };
654
+ export { BehaviorDescriptor, BoundaryRicochetCoordinator, CooldownBehavior, type CooldownConfig, type CooldownEntry, type CooldownHandle, type CooldownOptions, type DebugTools, Game, type IconSize, type IconSizePreset, Ricochet2DHandle, type ScreenAnchor, StageBlueprint, StageManager, type TemplateFactory, WorldBoundary2DHandle, ZylemGameElement, type ZylemGameState, boxMesh, clearGlobalSubscriptions, coneMesh, createCooldownIcon, createEntityFactory, createGlobal, createVariable, cylinderMesh, debugShader, debugState, destroy, fireCooldown, fireShader, getCooldown, getCooldownStore, getGlobal, getGlobals, getVariable, mergeInputConfigs, objectVertexShader, onGlobalChange, onGlobalChanges, onVariableChange, onVariableChanges, pillMesh, pingPongBeep, pyramidMesh, registerCooldown, resetCooldown, ricochetSound, setDebugTool, setGlobal, setPaused, setVariable, sphereMesh, stageState, standardShader, starShader, tickCooldowns, useArrowsForAxes, useArrowsForDirections, useBehavior, useIJKLForAxes, useIJKLForDirections, useWASDForAxes, useWASDForDirections };