ecspresso 0.10.2 → 0.12.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 +256 -148
- package/dist/asset-manager.d.ts +16 -16
- package/dist/asset-types.d.ts +18 -16
- package/dist/command-buffer.d.ts +30 -20
- package/dist/ecspresso-builder.d.ts +193 -0
- package/dist/ecspresso.d.ts +323 -209
- package/dist/entity-manager.d.ts +76 -30
- package/dist/event-bus.d.ts +6 -1
- package/dist/index.d.ts +6 -13
- package/dist/plugin.d.ts +61 -0
- package/dist/plugins/audio.d.ts +273 -0
- package/dist/{bundles/utils → plugins}/bounds.d.ts +20 -26
- package/dist/plugins/camera.d.ts +88 -0
- package/dist/plugins/collision.d.ts +285 -0
- package/dist/plugins/coroutine.d.ts +126 -0
- package/dist/plugins/diagnostics.d.ts +49 -0
- package/dist/{bundles/utils → plugins}/input.d.ts +22 -29
- package/dist/plugins/particles.d.ts +225 -0
- package/dist/plugins/physics2D.d.ts +163 -0
- package/dist/plugins/renderers/renderer2D.d.ts +262 -0
- package/dist/plugins/spatial-index.d.ts +58 -0
- package/dist/plugins/sprite-animation.d.ts +150 -0
- package/dist/plugins/state-machine.d.ts +244 -0
- package/dist/plugins/timers.d.ts +151 -0
- package/dist/{bundles/utils → plugins}/transform.d.ts +21 -22
- package/dist/plugins/tween.d.ts +162 -0
- package/dist/reactive-query-manager.d.ts +14 -3
- package/dist/resource-manager.d.ts +64 -23
- package/dist/screen-manager.d.ts +21 -15
- package/dist/screen-types.d.ts +15 -11
- package/dist/src/index.js +4 -0
- package/dist/src/index.js.map +25 -0
- package/dist/src/plugins/audio.js +4 -0
- package/dist/src/plugins/audio.js.map +10 -0
- package/dist/src/plugins/bounds.js +4 -0
- package/dist/src/plugins/bounds.js.map +10 -0
- package/dist/src/plugins/camera.js +4 -0
- package/dist/src/plugins/camera.js.map +10 -0
- package/dist/src/plugins/collision.js +4 -0
- package/dist/src/plugins/collision.js.map +11 -0
- package/dist/src/plugins/coroutine.js +4 -0
- package/dist/src/plugins/coroutine.js.map +10 -0
- package/dist/src/plugins/diagnostics.js +5 -0
- package/dist/src/plugins/diagnostics.js.map +10 -0
- package/dist/src/plugins/input.js +4 -0
- package/dist/src/plugins/input.js.map +10 -0
- package/dist/src/plugins/particles.js +4 -0
- package/dist/src/plugins/particles.js.map +10 -0
- package/dist/src/plugins/physics2D.js +4 -0
- package/dist/src/plugins/physics2D.js.map +11 -0
- package/dist/src/plugins/renderers/renderer2D.js +4 -0
- package/dist/src/plugins/renderers/renderer2D.js.map +10 -0
- package/dist/src/plugins/spatial-index.js +4 -0
- package/dist/src/plugins/spatial-index.js.map +11 -0
- package/dist/src/plugins/sprite-animation.js +4 -0
- package/dist/src/plugins/sprite-animation.js.map +10 -0
- package/dist/src/plugins/state-machine.js +4 -0
- package/dist/src/plugins/state-machine.js.map +10 -0
- package/dist/src/plugins/timers.js +4 -0
- package/dist/src/plugins/timers.js.map +10 -0
- package/dist/src/plugins/transform.js +4 -0
- package/dist/src/plugins/transform.js.map +10 -0
- package/dist/src/plugins/tween.js +4 -0
- package/dist/src/plugins/tween.js.map +11 -0
- package/dist/system-builder.d.ts +75 -112
- package/dist/type-utils.d.ts +247 -7
- package/dist/types.d.ts +58 -39
- package/dist/utils/check-required-cycle.d.ts +12 -0
- package/dist/utils/easing.d.ts +71 -0
- package/dist/utils/math.d.ts +67 -0
- package/dist/utils/narrowphase.d.ts +63 -0
- package/dist/utils/spatial-hash.d.ts +53 -0
- package/package.json +65 -27
- package/dist/bundle.d.ts +0 -123
- package/dist/bundles/renderers/renderer2D.d.ts +0 -220
- package/dist/bundles/renderers/renderer2D.js +0 -4
- package/dist/bundles/renderers/renderer2D.js.map +0 -10
- package/dist/bundles/utils/bounds.js +0 -4
- package/dist/bundles/utils/bounds.js.map +0 -10
- package/dist/bundles/utils/collision.d.ts +0 -204
- package/dist/bundles/utils/collision.js +0 -4
- package/dist/bundles/utils/collision.js.map +0 -10
- package/dist/bundles/utils/input.js +0 -4
- package/dist/bundles/utils/input.js.map +0 -10
- package/dist/bundles/utils/movement.d.ts +0 -86
- package/dist/bundles/utils/movement.js +0 -4
- package/dist/bundles/utils/movement.js.map +0 -10
- package/dist/bundles/utils/timers.d.ts +0 -172
- package/dist/bundles/utils/timers.js +0 -4
- package/dist/bundles/utils/timers.js.map +0 -10
- package/dist/bundles/utils/transform.js +0 -4
- package/dist/bundles/utils/transform.js.map +0 -10
- package/dist/index.js +0 -4
- package/dist/index.js.map +0 -22
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 2D Renderer Plugin for ECSpresso
|
|
3
|
+
*
|
|
4
|
+
* An opt-in PixiJS-based 2D rendering plugin that automates scene graph wiring.
|
|
5
|
+
* Import from 'ecspresso/plugins/renderers/renderer2D'
|
|
6
|
+
*
|
|
7
|
+
* This plugin includes transform propagation automatically.
|
|
8
|
+
*/
|
|
9
|
+
import type { Application, ApplicationOptions, Container, Sprite, Graphics } from 'pixi.js';
|
|
10
|
+
import { type Plugin } from 'ecspresso';
|
|
11
|
+
import type { WorldConfigFrom, EmptyConfig } from '../../type-utils';
|
|
12
|
+
import { type LocalTransform, type WorldTransform, type TransformComponentTypes, type TransformPluginOptions } from 'ecspresso/plugins/transform';
|
|
13
|
+
import { type BoundsRect } from 'ecspresso/plugins/bounds';
|
|
14
|
+
import type { CameraResourceTypes } from 'ecspresso/plugins/camera';
|
|
15
|
+
export type { LocalTransform, WorldTransform, TransformComponentTypes };
|
|
16
|
+
export type { BoundsRect };
|
|
17
|
+
export { createTransform, createLocalTransform, createWorldTransform, DEFAULT_LOCAL_TRANSFORM, DEFAULT_WORLD_TRANSFORM } from 'ecspresso/plugins/transform';
|
|
18
|
+
/**
|
|
19
|
+
* Visibility and alpha component
|
|
20
|
+
*/
|
|
21
|
+
export interface Visible {
|
|
22
|
+
visible: boolean;
|
|
23
|
+
alpha?: number;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Aggregate component types for the 2D renderer plugin.
|
|
27
|
+
* Included automatically via `.withPlugin(createRenderer2DPlugin({ ... }))`.
|
|
28
|
+
*
|
|
29
|
+
* @example
|
|
30
|
+
* ```typescript
|
|
31
|
+
* const ecs = ECSpresso.create()
|
|
32
|
+
* .withPlugin(createRenderer2DPlugin({ ... }))
|
|
33
|
+
* .withComponentTypes<{ velocity: { x: number; y: number }; player: true }>()
|
|
34
|
+
* .build();
|
|
35
|
+
* ```
|
|
36
|
+
*/
|
|
37
|
+
export interface Renderer2DComponentTypes extends TransformComponentTypes {
|
|
38
|
+
sprite: Sprite;
|
|
39
|
+
graphics: Graphics;
|
|
40
|
+
container: Container;
|
|
41
|
+
visible: Visible;
|
|
42
|
+
/** Assigns the entity to a named render layer for z-ordering */
|
|
43
|
+
renderLayer: string;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Events emitted by the 2D renderer plugin
|
|
47
|
+
*/
|
|
48
|
+
export interface Renderer2DEventTypes {
|
|
49
|
+
hierarchyChanged: {
|
|
50
|
+
entityId: number;
|
|
51
|
+
oldParent: number | null;
|
|
52
|
+
newParent: number | null;
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Resources provided by the 2D renderer plugin
|
|
57
|
+
*/
|
|
58
|
+
export interface Renderer2DResourceTypes {
|
|
59
|
+
pixiApp: Application;
|
|
60
|
+
rootContainer: Container;
|
|
61
|
+
/** Screen bounds derived from PixiJS screen dimensions, updated on resize */
|
|
62
|
+
bounds: BoundsRect;
|
|
63
|
+
}
|
|
64
|
+
export type ScaleMode = 'fit' | 'cover' | 'stretch';
|
|
65
|
+
export interface ScreenScaleOptions {
|
|
66
|
+
readonly width: number;
|
|
67
|
+
readonly height: number;
|
|
68
|
+
readonly mode?: ScaleMode;
|
|
69
|
+
}
|
|
70
|
+
export interface ViewportScale {
|
|
71
|
+
scaleX: number;
|
|
72
|
+
scaleY: number;
|
|
73
|
+
offsetX: number;
|
|
74
|
+
offsetY: number;
|
|
75
|
+
physicalWidth: number;
|
|
76
|
+
physicalHeight: number;
|
|
77
|
+
readonly designWidth: number;
|
|
78
|
+
readonly designHeight: number;
|
|
79
|
+
}
|
|
80
|
+
export interface ViewportScaleResourceTypes {
|
|
81
|
+
viewportScale: ViewportScale;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Common options shared between both initialization modes
|
|
85
|
+
*/
|
|
86
|
+
interface Renderer2DPluginCommonOptions<G extends string = 'renderer2d'> {
|
|
87
|
+
/** Optional custom root container (defaults to app.stage) */
|
|
88
|
+
rootContainer?: Container;
|
|
89
|
+
/** System group name (default: 'renderer2d') */
|
|
90
|
+
systemGroup?: G;
|
|
91
|
+
/** Priority for render sync system (default: 500) */
|
|
92
|
+
renderSyncPriority?: number;
|
|
93
|
+
/** Options for the included transform plugin */
|
|
94
|
+
transform?: TransformPluginOptions;
|
|
95
|
+
/** When true, wires up pixiApp.ticker to drive ecs.update() automatically (default: true) */
|
|
96
|
+
startLoop?: boolean;
|
|
97
|
+
/** Ordered render layer names (back-to-front). Entities with a renderLayer component are placed in the corresponding container. */
|
|
98
|
+
renderLayers?: string[];
|
|
99
|
+
/** Automatically apply cameraState resource to rootContainer each frame.
|
|
100
|
+
* Requires the camera plugin to be installed. (default: false) */
|
|
101
|
+
camera?: boolean;
|
|
102
|
+
/** Enforce a logical design resolution with automatic aspect-ratio-aware scaling.
|
|
103
|
+
* When set, systems work in design-resolution coordinate space. */
|
|
104
|
+
screenScale?: ScreenScaleOptions;
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Options when providing a pre-initialized PixiJS Application
|
|
108
|
+
*/
|
|
109
|
+
export interface Renderer2DPluginAppOptions<G extends string = 'renderer2d'> extends Renderer2DPluginCommonOptions<G> {
|
|
110
|
+
/** The PixiJS Application instance (already initialized) */
|
|
111
|
+
app: Application;
|
|
112
|
+
init?: never;
|
|
113
|
+
container?: never;
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Options when letting the plugin create and manage the PixiJS Application
|
|
117
|
+
*/
|
|
118
|
+
export interface Renderer2DPluginManagedOptions<G extends string = 'renderer2d'> extends Renderer2DPluginCommonOptions<G> {
|
|
119
|
+
app?: never;
|
|
120
|
+
/** PixiJS ApplicationOptions - plugin will create and initialize the Application */
|
|
121
|
+
init: Partial<ApplicationOptions>;
|
|
122
|
+
/** Container element to append the canvas to, or CSS selector string */
|
|
123
|
+
container?: HTMLElement | string;
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Configuration options for the 2D renderer plugin.
|
|
127
|
+
*
|
|
128
|
+
* Supports two modes:
|
|
129
|
+
* 1. **Pre-initialized**: Pass an already-initialized Application via `app`
|
|
130
|
+
* 2. **Managed**: Pass `init` options and the plugin creates the Application during `ecs.initialize()`
|
|
131
|
+
*
|
|
132
|
+
* This plugin includes transform propagation automatically - no need to add createTransformPlugin() separately.
|
|
133
|
+
*
|
|
134
|
+
* @example Pre-initialized mode (full control)
|
|
135
|
+
* ```typescript
|
|
136
|
+
* const app = new Application();
|
|
137
|
+
* await app.init({ resizeTo: window });
|
|
138
|
+
* const ecs = ECSpresso.create()
|
|
139
|
+
* .withPlugin(createRenderer2DPlugin({ app }))
|
|
140
|
+
* .withComponentTypes<{ player: true }>()
|
|
141
|
+
* .build();
|
|
142
|
+
* ```
|
|
143
|
+
*
|
|
144
|
+
* @example Managed mode (convenience)
|
|
145
|
+
* ```typescript
|
|
146
|
+
* const ecs = ECSpresso.create()
|
|
147
|
+
* .withPlugin(createRenderer2DPlugin({
|
|
148
|
+
* init: { background: '#1099bb', resizeTo: window },
|
|
149
|
+
* container: document.body,
|
|
150
|
+
* }))
|
|
151
|
+
* .withComponentTypes<{ player: true }>()
|
|
152
|
+
* .build();
|
|
153
|
+
* await ecs.initialize(); // Application created here
|
|
154
|
+
* ```
|
|
155
|
+
*/
|
|
156
|
+
export type Renderer2DPluginOptions<G extends string = 'renderer2d'> = Renderer2DPluginAppOptions<G> | Renderer2DPluginManagedOptions<G>;
|
|
157
|
+
interface PositionOption {
|
|
158
|
+
x?: number;
|
|
159
|
+
y?: number;
|
|
160
|
+
}
|
|
161
|
+
interface TransformOptions {
|
|
162
|
+
rotation?: number;
|
|
163
|
+
scale?: number | {
|
|
164
|
+
x: number;
|
|
165
|
+
y: number;
|
|
166
|
+
};
|
|
167
|
+
visible?: boolean;
|
|
168
|
+
alpha?: number;
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Create components for a sprite entity.
|
|
172
|
+
* Returns an object suitable for spreading into spawn().
|
|
173
|
+
*
|
|
174
|
+
* @example
|
|
175
|
+
* ```typescript
|
|
176
|
+
* const player = ecs.spawn({
|
|
177
|
+
* ...createSpriteComponents(new Sprite(texture), { x: 100, y: 100 }),
|
|
178
|
+
* velocity: { x: 0, y: 0 },
|
|
179
|
+
* });
|
|
180
|
+
* ```
|
|
181
|
+
*/
|
|
182
|
+
export declare function createSpriteComponents(sprite: Sprite, position?: PositionOption, options?: TransformOptions & {
|
|
183
|
+
anchor?: {
|
|
184
|
+
x: number;
|
|
185
|
+
y: number;
|
|
186
|
+
};
|
|
187
|
+
}): Pick<Renderer2DComponentTypes, 'sprite' | 'localTransform' | 'worldTransform' | 'visible'>;
|
|
188
|
+
/**
|
|
189
|
+
* Create components for a graphics entity.
|
|
190
|
+
* Returns an object suitable for spreading into spawn().
|
|
191
|
+
*
|
|
192
|
+
* @example
|
|
193
|
+
* ```typescript
|
|
194
|
+
* const rect = ecs.spawn({
|
|
195
|
+
* ...createGraphicsComponents(graphics, { x: 50, y: 50 }),
|
|
196
|
+
* });
|
|
197
|
+
* ```
|
|
198
|
+
*/
|
|
199
|
+
export declare function createGraphicsComponents(graphics: Graphics, position?: PositionOption, options?: TransformOptions): Pick<Renderer2DComponentTypes, 'graphics' | 'localTransform' | 'worldTransform' | 'visible'>;
|
|
200
|
+
/**
|
|
201
|
+
* Create components for a container entity.
|
|
202
|
+
* Returns an object suitable for spreading into spawn().
|
|
203
|
+
*
|
|
204
|
+
* @example
|
|
205
|
+
* ```typescript
|
|
206
|
+
* const group = ecs.spawn({
|
|
207
|
+
* ...createContainerComponents(new Container(), { x: 0, y: 0 }),
|
|
208
|
+
* });
|
|
209
|
+
* ```
|
|
210
|
+
*/
|
|
211
|
+
export declare function createContainerComponents(container: Container, position?: PositionOption, options?: TransformOptions): Pick<Renderer2DComponentTypes, 'container' | 'localTransform' | 'worldTransform' | 'visible'>;
|
|
212
|
+
export declare function computeViewportScale(physicalW: number, physicalH: number, designW: number, designH: number, mode: ScaleMode): ViewportScale;
|
|
213
|
+
/**
|
|
214
|
+
* Convert physical canvas pixel coordinates to design-resolution (logical) coordinates.
|
|
215
|
+
* Compose with camera `screenToWorld()` for full physical→world conversion.
|
|
216
|
+
*/
|
|
217
|
+
export declare function physicalToLogical(physicalX: number, physicalY: number, viewport: ViewportScale): {
|
|
218
|
+
x: number;
|
|
219
|
+
y: number;
|
|
220
|
+
};
|
|
221
|
+
/**
|
|
222
|
+
* Create a 2D rendering plugin for ECSpresso.
|
|
223
|
+
*
|
|
224
|
+
* This plugin provides:
|
|
225
|
+
* - Transform propagation (localTransform -> worldTransform)
|
|
226
|
+
* - Render sync system (updates PixiJS objects from ECS components)
|
|
227
|
+
* - Scene graph management (mirrors ECS hierarchy in PixiJS scene graph)
|
|
228
|
+
*
|
|
229
|
+
* @example Pre-initialized mode
|
|
230
|
+
* ```typescript
|
|
231
|
+
* const app = new Application();
|
|
232
|
+
* await app.init({ resizeTo: window });
|
|
233
|
+
*
|
|
234
|
+
* const ecs = ECSpresso.create<GameComponents, {}, {}>()
|
|
235
|
+
* .withPlugin(createRenderer2DPlugin({ app }))
|
|
236
|
+
* .build();
|
|
237
|
+
* ```
|
|
238
|
+
*
|
|
239
|
+
* @example Managed mode
|
|
240
|
+
* ```typescript
|
|
241
|
+
* const ecs = ECSpresso.create<GameComponents, {}, {}>()
|
|
242
|
+
* .withPlugin(createRenderer2DPlugin({
|
|
243
|
+
* init: { background: '#1099bb', resizeTo: window },
|
|
244
|
+
* container: document.body,
|
|
245
|
+
* }))
|
|
246
|
+
* .build();
|
|
247
|
+
* await ecs.initialize();
|
|
248
|
+
* ```
|
|
249
|
+
*/
|
|
250
|
+
type Renderer2DLabels = 'renderer2d-sync' | 'renderer2d-scene-graph' | 'renderer2d-camera-sync' | 'transform-propagation';
|
|
251
|
+
type Renderer2DReactiveQueryNames = 'renderer2d-sprites' | 'renderer2d-graphics' | 'renderer2d-containers';
|
|
252
|
+
export declare function createRenderer2DPlugin<G extends string = 'renderer2d'>(options: Renderer2DPluginOptions<G> & {
|
|
253
|
+
screenScale: ScreenScaleOptions;
|
|
254
|
+
camera: true;
|
|
255
|
+
}): Plugin<WorldConfigFrom<Renderer2DComponentTypes, Renderer2DEventTypes, Renderer2DResourceTypes & ViewportScaleResourceTypes & CameraResourceTypes>, EmptyConfig, Renderer2DLabels, G, never, Renderer2DReactiveQueryNames>;
|
|
256
|
+
export declare function createRenderer2DPlugin<G extends string = 'renderer2d'>(options: Renderer2DPluginOptions<G> & {
|
|
257
|
+
screenScale: ScreenScaleOptions;
|
|
258
|
+
}): Plugin<WorldConfigFrom<Renderer2DComponentTypes, Renderer2DEventTypes, Renderer2DResourceTypes & ViewportScaleResourceTypes>, EmptyConfig, Renderer2DLabels, G, never, Renderer2DReactiveQueryNames>;
|
|
259
|
+
export declare function createRenderer2DPlugin<G extends string = 'renderer2d'>(options: Renderer2DPluginOptions<G> & {
|
|
260
|
+
camera: true;
|
|
261
|
+
}): Plugin<WorldConfigFrom<Renderer2DComponentTypes, Renderer2DEventTypes, Renderer2DResourceTypes & CameraResourceTypes>, EmptyConfig, Renderer2DLabels, G, never, Renderer2DReactiveQueryNames>;
|
|
262
|
+
export declare function createRenderer2DPlugin<G extends string = 'renderer2d'>(options: Renderer2DPluginOptions<G>): Plugin<WorldConfigFrom<Renderer2DComponentTypes, Renderer2DEventTypes, Renderer2DResourceTypes>, EmptyConfig, Renderer2DLabels, G, never, Renderer2DReactiveQueryNames>;
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Spatial Index Plugin for ECSpresso
|
|
3
|
+
*
|
|
4
|
+
* Provides a uniform-grid spatial hash for broadphase collision detection
|
|
5
|
+
* and proximity queries. Replaces O(n²) brute-force with O(n·d) where
|
|
6
|
+
* d = local density.
|
|
7
|
+
*
|
|
8
|
+
* Standalone usage: queryRect / queryRadius for proximity queries.
|
|
9
|
+
* Automatic acceleration: collision and physics2D plugins detect the
|
|
10
|
+
* spatialIndex resource at runtime and use it for broadphase when present.
|
|
11
|
+
*/
|
|
12
|
+
import { type Plugin } from 'ecspresso';
|
|
13
|
+
import type { WorldConfigFrom, EmptyConfig } from '../type-utils';
|
|
14
|
+
import type { TransformComponentTypes } from './transform';
|
|
15
|
+
import type { CollisionComponentTypes } from './collision';
|
|
16
|
+
import { type SpatialIndex } from '../utils/spatial-hash';
|
|
17
|
+
export interface SpatialIndexResourceTypes {
|
|
18
|
+
spatialIndex: SpatialIndex;
|
|
19
|
+
}
|
|
20
|
+
type SpatialIndexComponentTypes = TransformComponentTypes & Pick<CollisionComponentTypes<string>, 'aabbCollider' | 'circleCollider'>;
|
|
21
|
+
export type SpatialIndexPhase = 'fixedUpdate' | 'postUpdate';
|
|
22
|
+
type SpatialIndexLabel = `spatial-index-rebuild-${SpatialIndexPhase}`;
|
|
23
|
+
export interface SpatialIndexPluginOptions<G extends string = 'spatialIndex'> {
|
|
24
|
+
/** Cell size for the spatial hash grid (default: 64) */
|
|
25
|
+
cellSize?: number;
|
|
26
|
+
/** System group name (default: 'spatialIndex') */
|
|
27
|
+
systemGroup?: G;
|
|
28
|
+
/** Priority for rebuild systems (default: 2000, before collision) */
|
|
29
|
+
priority?: number;
|
|
30
|
+
/** Phases to register rebuild systems in (default: ['fixedUpdate', 'postUpdate']) */
|
|
31
|
+
phases?: ReadonlyArray<SpatialIndexPhase>;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Create a spatial index plugin for ECSpresso.
|
|
35
|
+
*
|
|
36
|
+
* Provides a uniform-grid spatial hash that accelerates collision detection.
|
|
37
|
+
* When installed alongside the collision or physics2D plugins, they
|
|
38
|
+
* automatically use the spatial index for broadphase instead of O(n²)
|
|
39
|
+
* brute-force.
|
|
40
|
+
*
|
|
41
|
+
* Also provides proximity query methods for game logic (e.g. "find all
|
|
42
|
+
* enemies within 200 units").
|
|
43
|
+
*
|
|
44
|
+
* @example
|
|
45
|
+
* ```typescript
|
|
46
|
+
* const ecs = ECSpresso.create()
|
|
47
|
+
* .withPlugin(createTransformPlugin())
|
|
48
|
+
* .withPlugin(createCollisionPlugin({ layers }))
|
|
49
|
+
* .withPlugin(createSpatialIndexPlugin({ cellSize: 128 }))
|
|
50
|
+
* .build();
|
|
51
|
+
*
|
|
52
|
+
* // Proximity query in a system:
|
|
53
|
+
* const si = ecs.getResource('spatialIndex');
|
|
54
|
+
* const nearby = si.queryRadius(playerX, playerY, 200);
|
|
55
|
+
* ```
|
|
56
|
+
*/
|
|
57
|
+
export declare function createSpatialIndexPlugin<G extends string = 'spatialIndex'>(options?: SpatialIndexPluginOptions<G>): Plugin<WorldConfigFrom<SpatialIndexComponentTypes, {}, SpatialIndexResourceTypes>, EmptyConfig, SpatialIndexLabel, G>;
|
|
58
|
+
export {};
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sprite Animation Plugin for ECSpresso
|
|
3
|
+
*
|
|
4
|
+
* ECS-native frame-based sprite animation. Advances through spritesheet frames,
|
|
5
|
+
* handles loop modes (once, loop, pingPong), publishes completion events, and
|
|
6
|
+
* syncs the current frame's texture to the PixiJS Sprite via structural access.
|
|
7
|
+
*
|
|
8
|
+
* Renderer2D is a required dependency — the `sprite` component comes from that plugin.
|
|
9
|
+
* This plugin declares only `spriteAnimation` as its component type.
|
|
10
|
+
*/
|
|
11
|
+
import { type Plugin, type BasePluginOptions } from 'ecspresso';
|
|
12
|
+
import type { BaseWorld } from 'ecspresso';
|
|
13
|
+
import type { WorldConfigFrom, EmptyConfig } from '../type-utils';
|
|
14
|
+
/** BaseWorld narrowed to sprite-animation components for typed access in helpers. */
|
|
15
|
+
type SpriteAnimationWorld = BaseWorld<SpriteAnimationComponentTypes>;
|
|
16
|
+
export type AnimationLoopMode = 'once' | 'loop' | 'pingPong';
|
|
17
|
+
/**
|
|
18
|
+
* A single animation clip: an ordered sequence of texture frames with timing.
|
|
19
|
+
* Immutable and shared across entities.
|
|
20
|
+
*/
|
|
21
|
+
export interface SpriteAnimationClip {
|
|
22
|
+
readonly frames: readonly unknown[];
|
|
23
|
+
readonly frameDuration: number;
|
|
24
|
+
readonly frameDurations: readonly number[] | null;
|
|
25
|
+
readonly loop: AnimationLoopMode;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Input format for defining a clip. Accepts either uniform or per-frame timing.
|
|
29
|
+
*/
|
|
30
|
+
export interface SpriteAnimationClipInput {
|
|
31
|
+
/** Array of PixiJS Texture objects */
|
|
32
|
+
frames: readonly unknown[];
|
|
33
|
+
/** Uniform seconds-per-frame (used when frameDurations is not provided) */
|
|
34
|
+
frameDuration?: number;
|
|
35
|
+
/** Per-frame durations in seconds (overrides frameDuration) */
|
|
36
|
+
frameDurations?: readonly number[];
|
|
37
|
+
/** Loop mode (default: 'loop') */
|
|
38
|
+
loop?: AnimationLoopMode;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* A named collection of animation clips. Immutable and shared across entities.
|
|
42
|
+
* Parameterized by A (animation name union) for compile-time validation.
|
|
43
|
+
*/
|
|
44
|
+
export interface SpriteAnimationSet<A extends string = string> {
|
|
45
|
+
readonly id: string;
|
|
46
|
+
readonly clips: {
|
|
47
|
+
readonly [K in A]: SpriteAnimationClip;
|
|
48
|
+
};
|
|
49
|
+
readonly defaultClip: A;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Per-entity runtime animation state.
|
|
53
|
+
*/
|
|
54
|
+
export interface SpriteAnimation<A extends string = string> {
|
|
55
|
+
readonly set: SpriteAnimationSet<A>;
|
|
56
|
+
current: A;
|
|
57
|
+
currentFrame: number;
|
|
58
|
+
elapsed: number;
|
|
59
|
+
playing: boolean;
|
|
60
|
+
speed: number;
|
|
61
|
+
direction: 1 | -1;
|
|
62
|
+
totalLoops: number;
|
|
63
|
+
completedLoops: number;
|
|
64
|
+
justFinished: boolean;
|
|
65
|
+
onComplete?: (data: SpriteAnimationEventData) => void;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Component types provided by the sprite animation plugin.
|
|
69
|
+
*/
|
|
70
|
+
export interface SpriteAnimationComponentTypes<A extends string = string> {
|
|
71
|
+
spriteAnimation: SpriteAnimation<A>;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Data published when an animation completes.
|
|
75
|
+
*/
|
|
76
|
+
export interface SpriteAnimationEventData {
|
|
77
|
+
entityId: number;
|
|
78
|
+
animation: string;
|
|
79
|
+
}
|
|
80
|
+
export interface SpriteAnimationPluginOptions<G extends string = 'spriteAnimation'> extends BasePluginOptions<G> {
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Define a single-clip animation set named 'default'.
|
|
84
|
+
* For simple use cases like spinning coins, pulsing effects, etc.
|
|
85
|
+
*
|
|
86
|
+
* @param id Unique identifier for this animation set
|
|
87
|
+
* @param clip Clip definition
|
|
88
|
+
* @returns A frozen SpriteAnimationSet with one clip named 'default'
|
|
89
|
+
*/
|
|
90
|
+
export declare function defineSpriteAnimation(id: string, clip: SpriteAnimationClipInput): SpriteAnimationSet<'default'>;
|
|
91
|
+
/**
|
|
92
|
+
* Define a multi-clip animation set with named animations.
|
|
93
|
+
* Animation names are inferred from the keys of the clips object.
|
|
94
|
+
*
|
|
95
|
+
* @param id Unique identifier for this animation set
|
|
96
|
+
* @param clips Object mapping animation names to clip definitions
|
|
97
|
+
* @param options Optional configuration (defaultClip)
|
|
98
|
+
* @returns A frozen SpriteAnimationSet with inferred animation name union
|
|
99
|
+
*/
|
|
100
|
+
export declare function defineSpriteAnimations<A extends string>(id: string, clips: Record<A, SpriteAnimationClipInput>, options?: {
|
|
101
|
+
defaultClip?: NoInfer<A>;
|
|
102
|
+
}): SpriteAnimationSet<A>;
|
|
103
|
+
/**
|
|
104
|
+
* Create a spriteAnimation component from an animation set.
|
|
105
|
+
*
|
|
106
|
+
* @param set The animation set to use
|
|
107
|
+
* @param options Optional configuration (initial clip, speed, onComplete event)
|
|
108
|
+
* @returns Component object suitable for spreading into spawn()
|
|
109
|
+
*/
|
|
110
|
+
export declare function createSpriteAnimation<A extends string>(set: SpriteAnimationSet<A>, options?: {
|
|
111
|
+
initial?: A;
|
|
112
|
+
speed?: number;
|
|
113
|
+
totalLoops?: number;
|
|
114
|
+
onComplete?: (data: SpriteAnimationEventData) => void;
|
|
115
|
+
}): Pick<SpriteAnimationComponentTypes<A>, 'spriteAnimation'>;
|
|
116
|
+
/**
|
|
117
|
+
* Switch an entity's current animation at runtime.
|
|
118
|
+
* Resets state if switching to a different animation (or restart=true).
|
|
119
|
+
*
|
|
120
|
+
* @returns false if entity has no spriteAnimation or animation name doesn't exist
|
|
121
|
+
*/
|
|
122
|
+
export declare function playAnimation(ecs: SpriteAnimationWorld, entityId: number, animation: string, options?: {
|
|
123
|
+
restart?: boolean;
|
|
124
|
+
speed?: number;
|
|
125
|
+
}): boolean;
|
|
126
|
+
/**
|
|
127
|
+
* Pause an entity's animation.
|
|
128
|
+
*
|
|
129
|
+
* @returns false if entity has no spriteAnimation
|
|
130
|
+
*/
|
|
131
|
+
export declare function stopAnimation(ecs: SpriteAnimationWorld, entityId: number): boolean;
|
|
132
|
+
/**
|
|
133
|
+
* Resume a paused animation.
|
|
134
|
+
*
|
|
135
|
+
* @returns false if entity has no spriteAnimation
|
|
136
|
+
*/
|
|
137
|
+
export declare function resumeAnimation(ecs: SpriteAnimationWorld, entityId: number): boolean;
|
|
138
|
+
/**
|
|
139
|
+
* Create a sprite animation plugin for ECSpresso.
|
|
140
|
+
*
|
|
141
|
+
* Provides:
|
|
142
|
+
* - Frame-based animation system processing spriteAnimation components
|
|
143
|
+
* - Loop modes: once, loop, pingPong
|
|
144
|
+
* - justFinished one-frame flag for completion detection
|
|
145
|
+
* - onComplete event publishing
|
|
146
|
+
* - Sprite texture sync via structural cross-plugin access
|
|
147
|
+
* - Change detection via markChanged
|
|
148
|
+
*/
|
|
149
|
+
export declare function createSpriteAnimationPlugin<G extends string = 'spriteAnimation'>(options?: SpriteAnimationPluginOptions<G>): Plugin<WorldConfigFrom<SpriteAnimationComponentTypes>, EmptyConfig, 'sprite-animation-update', G>;
|
|
150
|
+
export {};
|