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.
Files changed (94) hide show
  1. package/README.md +256 -148
  2. package/dist/asset-manager.d.ts +16 -16
  3. package/dist/asset-types.d.ts +18 -16
  4. package/dist/command-buffer.d.ts +30 -20
  5. package/dist/ecspresso-builder.d.ts +193 -0
  6. package/dist/ecspresso.d.ts +323 -209
  7. package/dist/entity-manager.d.ts +76 -30
  8. package/dist/event-bus.d.ts +6 -1
  9. package/dist/index.d.ts +6 -13
  10. package/dist/plugin.d.ts +61 -0
  11. package/dist/plugins/audio.d.ts +273 -0
  12. package/dist/{bundles/utils → plugins}/bounds.d.ts +20 -26
  13. package/dist/plugins/camera.d.ts +88 -0
  14. package/dist/plugins/collision.d.ts +285 -0
  15. package/dist/plugins/coroutine.d.ts +126 -0
  16. package/dist/plugins/diagnostics.d.ts +49 -0
  17. package/dist/{bundles/utils → plugins}/input.d.ts +22 -29
  18. package/dist/plugins/particles.d.ts +225 -0
  19. package/dist/plugins/physics2D.d.ts +163 -0
  20. package/dist/plugins/renderers/renderer2D.d.ts +262 -0
  21. package/dist/plugins/spatial-index.d.ts +58 -0
  22. package/dist/plugins/sprite-animation.d.ts +150 -0
  23. package/dist/plugins/state-machine.d.ts +244 -0
  24. package/dist/plugins/timers.d.ts +151 -0
  25. package/dist/{bundles/utils → plugins}/transform.d.ts +21 -22
  26. package/dist/plugins/tween.d.ts +162 -0
  27. package/dist/reactive-query-manager.d.ts +14 -3
  28. package/dist/resource-manager.d.ts +64 -23
  29. package/dist/screen-manager.d.ts +21 -15
  30. package/dist/screen-types.d.ts +15 -11
  31. package/dist/src/index.js +4 -0
  32. package/dist/src/index.js.map +25 -0
  33. package/dist/src/plugins/audio.js +4 -0
  34. package/dist/src/plugins/audio.js.map +10 -0
  35. package/dist/src/plugins/bounds.js +4 -0
  36. package/dist/src/plugins/bounds.js.map +10 -0
  37. package/dist/src/plugins/camera.js +4 -0
  38. package/dist/src/plugins/camera.js.map +10 -0
  39. package/dist/src/plugins/collision.js +4 -0
  40. package/dist/src/plugins/collision.js.map +11 -0
  41. package/dist/src/plugins/coroutine.js +4 -0
  42. package/dist/src/plugins/coroutine.js.map +10 -0
  43. package/dist/src/plugins/diagnostics.js +5 -0
  44. package/dist/src/plugins/diagnostics.js.map +10 -0
  45. package/dist/src/plugins/input.js +4 -0
  46. package/dist/src/plugins/input.js.map +10 -0
  47. package/dist/src/plugins/particles.js +4 -0
  48. package/dist/src/plugins/particles.js.map +10 -0
  49. package/dist/src/plugins/physics2D.js +4 -0
  50. package/dist/src/plugins/physics2D.js.map +11 -0
  51. package/dist/src/plugins/renderers/renderer2D.js +4 -0
  52. package/dist/src/plugins/renderers/renderer2D.js.map +10 -0
  53. package/dist/src/plugins/spatial-index.js +4 -0
  54. package/dist/src/plugins/spatial-index.js.map +11 -0
  55. package/dist/src/plugins/sprite-animation.js +4 -0
  56. package/dist/src/plugins/sprite-animation.js.map +10 -0
  57. package/dist/src/plugins/state-machine.js +4 -0
  58. package/dist/src/plugins/state-machine.js.map +10 -0
  59. package/dist/src/plugins/timers.js +4 -0
  60. package/dist/src/plugins/timers.js.map +10 -0
  61. package/dist/src/plugins/transform.js +4 -0
  62. package/dist/src/plugins/transform.js.map +10 -0
  63. package/dist/src/plugins/tween.js +4 -0
  64. package/dist/src/plugins/tween.js.map +11 -0
  65. package/dist/system-builder.d.ts +75 -112
  66. package/dist/type-utils.d.ts +247 -7
  67. package/dist/types.d.ts +58 -39
  68. package/dist/utils/check-required-cycle.d.ts +12 -0
  69. package/dist/utils/easing.d.ts +71 -0
  70. package/dist/utils/math.d.ts +67 -0
  71. package/dist/utils/narrowphase.d.ts +63 -0
  72. package/dist/utils/spatial-hash.d.ts +53 -0
  73. package/package.json +65 -27
  74. package/dist/bundle.d.ts +0 -123
  75. package/dist/bundles/renderers/renderer2D.d.ts +0 -220
  76. package/dist/bundles/renderers/renderer2D.js +0 -4
  77. package/dist/bundles/renderers/renderer2D.js.map +0 -10
  78. package/dist/bundles/utils/bounds.js +0 -4
  79. package/dist/bundles/utils/bounds.js.map +0 -10
  80. package/dist/bundles/utils/collision.d.ts +0 -204
  81. package/dist/bundles/utils/collision.js +0 -4
  82. package/dist/bundles/utils/collision.js.map +0 -10
  83. package/dist/bundles/utils/input.js +0 -4
  84. package/dist/bundles/utils/input.js.map +0 -10
  85. package/dist/bundles/utils/movement.d.ts +0 -86
  86. package/dist/bundles/utils/movement.js +0 -4
  87. package/dist/bundles/utils/movement.js.map +0 -10
  88. package/dist/bundles/utils/timers.d.ts +0 -172
  89. package/dist/bundles/utils/timers.js +0 -4
  90. package/dist/bundles/utils/timers.js.map +0 -10
  91. package/dist/bundles/utils/transform.js +0 -4
  92. package/dist/bundles/utils/transform.js.map +0 -10
  93. package/dist/index.js +0 -4
  94. package/dist/index.js.map +0 -22
@@ -1,15 +1,15 @@
1
1
  /**
2
- * Input Bundle for ECSpresso
2
+ * Input Plugin for ECSpresso
3
3
  *
4
4
  * Provides frame-accurate keyboard, pointer (mouse + touch via PointerEvent),
5
- * and action mapping input. Resource-only bundle — input is polled via the
5
+ * and action mapping input. Resource-only plugin — input is polled via the
6
6
  * `inputState` resource. No ECS components or events.
7
7
  *
8
8
  * DOM events are accumulated between frames and snapshotted once per frame
9
9
  * in the system's process step, so all systems see consistent state.
10
10
  */
11
- import { Bundle } from 'ecspresso';
12
- import type { SystemPhase } from 'ecspresso';
11
+ import { type Plugin, type BasePluginOptions } from 'ecspresso';
12
+ import type { WorldConfigFrom, EmptyConfig } from '../type-utils';
13
13
  export interface Vec2 {
14
14
  x: number;
15
15
  y: number;
@@ -48,35 +48,29 @@ export interface PointerState {
48
48
  justPressed(button: number): boolean;
49
49
  justReleased(button: number): boolean;
50
50
  }
51
- export interface ActionState {
52
- isActive(action: string): boolean;
53
- justActivated(action: string): boolean;
54
- justDeactivated(action: string): boolean;
51
+ export interface ActionState<A extends string = string> {
52
+ isActive(action: A): boolean;
53
+ justActivated(action: A): boolean;
54
+ justDeactivated(action: A): boolean;
55
55
  }
56
- export interface InputState {
56
+ export interface InputState<A extends string = string> {
57
57
  readonly keyboard: KeyboardState;
58
58
  readonly pointer: PointerState;
59
- readonly actions: ActionState;
60
- setActionMap(actions: ActionMap): void;
61
- getActionMap(): Readonly<ActionMap>;
59
+ readonly actions: ActionState<A>;
60
+ setActionMap(actions: ActionMap<A>): void;
61
+ getActionMap(): Readonly<ActionMap<A>>;
62
62
  }
63
63
  export interface ActionBinding {
64
64
  keys?: KeyCode[];
65
65
  buttons?: number[];
66
66
  }
67
- export type ActionMap = Record<string, ActionBinding>;
68
- export interface InputResourceTypes {
69
- inputState: InputState;
67
+ export type ActionMap<A extends string = string> = Record<A, ActionBinding>;
68
+ export interface InputResourceTypes<A extends string = string> {
69
+ inputState: InputState<A>;
70
70
  }
71
- export interface InputBundleOptions {
72
- /** System group name (default: 'input') */
73
- systemGroup?: string;
74
- /** Priority for input system (default: 100) */
75
- priority?: number;
76
- /** Execution phase (default: 'preUpdate') */
77
- phase?: SystemPhase;
71
+ export interface InputPluginOptions<A extends string = string, G extends string = 'input'> extends BasePluginOptions<G> {
78
72
  /** Initial action mappings */
79
- actions?: ActionMap;
73
+ actions?: ActionMap<A>;
80
74
  /** EventTarget to attach listeners to (default: globalThis). Pass a custom target for testability. */
81
75
  target?: EventTarget;
82
76
  }
@@ -88,9 +82,9 @@ export interface InputBundleOptions {
88
82
  */
89
83
  export declare function createActionBinding(binding: ActionBinding): ActionBinding;
90
84
  /**
91
- * Create an input bundle for ECSpresso.
85
+ * Create an input plugin for ECSpresso.
92
86
  *
93
- * This bundle provides:
87
+ * This plugin provides:
94
88
  * - Frame-accurate keyboard state (isDown, justPressed, justReleased)
95
89
  * - Pointer position/delta and button state (mouse + touch via PointerEvent)
96
90
  * - Named action mapping with runtime remapping
@@ -98,9 +92,8 @@ export declare function createActionBinding(binding: ActionBinding): ActionBindi
98
92
  *
99
93
  * @example
100
94
  * ```typescript
101
- * const ecs = ECSpresso
102
- * .create<Components, Events, Resources>()
103
- * .withBundle(createInputBundle({
95
+ * const ecs = ECSpresso.create()
96
+ * .withPlugin(createInputPlugin({
104
97
  * actions: {
105
98
  * jump: { keys: [' ', 'ArrowUp'] },
106
99
  * shoot: { keys: ['z'], buttons: [0] },
@@ -114,5 +107,5 @@ export declare function createActionBinding(binding: ActionBinding): ActionBindi
114
107
  * if (input.keyboard.isDown('ArrowRight')) { ... }
115
108
  * ```
116
109
  */
117
- export declare function createInputBundle(options?: InputBundleOptions): Bundle<{}, {}, InputResourceTypes>;
110
+ export declare function createInputPlugin<A extends string = string, G extends string = 'input'>(options?: InputPluginOptions<A, G>): Plugin<WorldConfigFrom<{}, {}, InputResourceTypes<A>>, EmptyConfig, 'input-state', G>;
118
111
  export {};
@@ -0,0 +1,225 @@
1
+ /**
2
+ * Particle System Plugin for ECSpresso
3
+ *
4
+ * High-performance particle system where particles live outside the ECS in
5
+ * pre-allocated pools. Renders via PixiJS v8's ParticleContainer + Particle API.
6
+ * Renderer2D is a required dependency.
7
+ *
8
+ * Follows the established plugin pattern: immutable shared config
9
+ * (ParticleEffectConfig) + mutable per-entity state (ParticleEmitter) component,
10
+ * side-storage Map for PixiJS objects, kit pattern for typed helpers.
11
+ */
12
+ import { type Plugin, type BasePluginOptions } from 'ecspresso';
13
+ import type { BaseWorld } from 'ecspresso';
14
+ import type { WorldConfigFrom } from '../type-utils';
15
+ import type { TransformComponentTypes } from 'ecspresso/plugins/transform';
16
+ /** BaseWorld narrowed to particle components for typed access in helpers. */
17
+ type ParticleWorld = BaseWorld<ParticleComponentTypes>;
18
+ /** Fixed value or random range [min, max] */
19
+ export type ParticleValue = number | readonly [number, number];
20
+ /** Emission geometry */
21
+ export type EmissionShape = 'point' | 'circle';
22
+ /** Blend modes for particle rendering */
23
+ export type ParticleBlendMode = 'normal' | 'add' | 'multiply' | 'screen';
24
+ /**
25
+ * User-facing config input for defining a particle effect.
26
+ * All properties optional except maxParticles and texture.
27
+ */
28
+ export interface ParticleEffectInput {
29
+ /** Pool size — maximum simultaneous particles */
30
+ maxParticles: number;
31
+ /** PixiJS Texture for particles */
32
+ texture: unknown;
33
+ /** Particles per second (0 = burst-only, default: 10) */
34
+ spawnRate?: number;
35
+ /** Particles per burst (default: 0) */
36
+ burstCount?: number;
37
+ /** Emitter lifetime in seconds (-1 = infinite, default: -1) */
38
+ duration?: number;
39
+ /** Per-particle lifetime in seconds (default: 1) */
40
+ lifetime?: ParticleValue;
41
+ /** Initial speed in pixels/second (default: 100) */
42
+ speed?: ParticleValue;
43
+ /** Emission direction in radians (default: [0, 2*PI]) */
44
+ angle?: ParticleValue;
45
+ /** Spawn geometry (default: 'point') */
46
+ emissionShape?: EmissionShape;
47
+ /** Radius for 'circle' shape (default: 0) */
48
+ emissionRadius?: number;
49
+ /** Acceleration in pixels/second^2 (default: {x: 0, y: 0}) */
50
+ gravity?: {
51
+ readonly x: number;
52
+ readonly y: number;
53
+ };
54
+ /** Initial scale (default: 1) */
55
+ startSize?: ParticleValue;
56
+ /** Final scale (default: same as startSize) */
57
+ endSize?: ParticleValue;
58
+ /** Initial opacity (default: 1) */
59
+ startAlpha?: ParticleValue;
60
+ /** Final opacity (default: 0) */
61
+ endAlpha?: ParticleValue;
62
+ /** Initial hex color (default: 0xffffff) */
63
+ startTint?: number;
64
+ /** Final hex color (default: same as startTint) */
65
+ endTint?: number;
66
+ /** Initial rotation in radians (default: 0) */
67
+ startRotation?: ParticleValue;
68
+ /** Rotation velocity in rad/s (default: 0) */
69
+ rotationSpeed?: ParticleValue;
70
+ /** Blend mode (default: 'normal') */
71
+ blendMode?: ParticleBlendMode;
72
+ /** Particles in world coordinates (default: true) */
73
+ worldSpace?: boolean;
74
+ }
75
+ /**
76
+ * Frozen, fully-resolved particle effect config.
77
+ * Output of defineParticleEffect.
78
+ */
79
+ export interface ParticleEffectConfig {
80
+ readonly maxParticles: number;
81
+ readonly texture: unknown;
82
+ readonly spawnRate: number;
83
+ readonly burstCount: number;
84
+ readonly duration: number;
85
+ readonly lifetime: ParticleValue;
86
+ readonly speed: ParticleValue;
87
+ readonly angle: ParticleValue;
88
+ readonly emissionShape: EmissionShape;
89
+ readonly emissionRadius: number;
90
+ readonly gravity: {
91
+ readonly x: number;
92
+ readonly y: number;
93
+ };
94
+ readonly startSize: ParticleValue;
95
+ readonly endSize: ParticleValue;
96
+ readonly startAlpha: ParticleValue;
97
+ readonly endAlpha: ParticleValue;
98
+ readonly startTint: number;
99
+ readonly endTint: number;
100
+ readonly startRotation: ParticleValue;
101
+ readonly rotationSpeed: ParticleValue;
102
+ readonly blendMode: ParticleBlendMode;
103
+ readonly worldSpace: boolean;
104
+ }
105
+ /**
106
+ * Mutable per-particle state. Pre-allocated, never GC'd.
107
+ */
108
+ export interface ParticleState {
109
+ active: boolean;
110
+ x: number;
111
+ y: number;
112
+ vx: number;
113
+ vy: number;
114
+ life: number;
115
+ maxLife: number;
116
+ size: number;
117
+ startSize: number;
118
+ endSize: number;
119
+ alpha: number;
120
+ startAlpha: number;
121
+ endAlpha: number;
122
+ tint: number;
123
+ rotation: number;
124
+ rotationSpeed: number;
125
+ }
126
+ /**
127
+ * Per-entity emitter state stored as an ECS component.
128
+ */
129
+ export interface ParticleEmitter {
130
+ readonly config: ParticleEffectConfig;
131
+ activeCount: number;
132
+ spawnAccumulator: number;
133
+ elapsed: number;
134
+ playing: boolean;
135
+ pendingBurst: number;
136
+ finished: boolean;
137
+ onComplete?: (data: ParticleEmitterEventData) => void;
138
+ }
139
+ /**
140
+ * Component types provided by the particle plugin.
141
+ */
142
+ export interface ParticleComponentTypes {
143
+ particleEmitter: ParticleEmitter;
144
+ }
145
+ /**
146
+ * Data published when an emitter completes.
147
+ */
148
+ export interface ParticleEmitterEventData {
149
+ entityId: number;
150
+ }
151
+ export interface ParticlePluginOptions<G extends string = 'particles'> extends BasePluginOptions<G> {
152
+ }
153
+ /**
154
+ * Sample a ParticleValue: returns fixed value or random within [min, max].
155
+ */
156
+ export declare function sampleRange(value: ParticleValue): number;
157
+ /**
158
+ * Linear interpolation between two hex colors (RGB channels).
159
+ */
160
+ export declare function lerpTint(start: number, end: number, t: number): number;
161
+ /**
162
+ * Define a particle effect config with defaults applied and frozen.
163
+ */
164
+ export declare function defineParticleEffect(input: ParticleEffectInput): ParticleEffectConfig;
165
+ /**
166
+ * Create a particleEmitter component suitable for spreading into spawn().
167
+ */
168
+ export declare function createParticleEmitter(config: ParticleEffectConfig, options?: {
169
+ playing?: boolean;
170
+ onComplete?: (data: ParticleEmitterEventData) => void;
171
+ }): Pick<ParticleComponentTypes, 'particleEmitter'>;
172
+ /**
173
+ * Queue a burst of particles on an emitter.
174
+ * Returns false if entity has no particleEmitter component.
175
+ */
176
+ export declare function burstParticles(ecs: ParticleWorld, entityId: number, count?: number): boolean;
177
+ /**
178
+ * Stop an emitter from spawning new particles.
179
+ * Existing particles continue their lifecycle.
180
+ */
181
+ export declare function stopEmitter(ecs: ParticleWorld, entityId: number): boolean;
182
+ /**
183
+ * Resume a stopped emitter.
184
+ */
185
+ export declare function resumeEmitter(ecs: ParticleWorld, entityId: number): boolean;
186
+ /**
187
+ * Runtime data stored outside the ECS, keyed by entity ID.
188
+ */
189
+ export interface EmitterRuntimeData {
190
+ particles: ParticleState[];
191
+ pixiContainer: unknown;
192
+ pixiParticles: unknown[];
193
+ }
194
+ export declare const particlePresets: {
195
+ readonly explosion: (texture: unknown, overrides?: Partial<ParticleEffectInput>) => ParticleEffectConfig;
196
+ readonly smoke: (texture: unknown, overrides?: Partial<ParticleEffectInput>) => ParticleEffectConfig;
197
+ readonly fire: (texture: unknown, overrides?: Partial<ParticleEffectInput>) => ParticleEffectConfig;
198
+ readonly sparkle: (texture: unknown, overrides?: Partial<ParticleEffectInput>) => ParticleEffectConfig;
199
+ readonly trail: (texture: unknown, overrides?: Partial<ParticleEffectInput>) => ParticleEffectConfig;
200
+ };
201
+ type ParticleLabels = 'particle-update' | 'particle-render-sync';
202
+ type ParticleRequires = WorldConfigFrom<TransformComponentTypes & {
203
+ renderLayer: string;
204
+ }>;
205
+ /**
206
+ * Create a particle system plugin for ECSpresso.
207
+ *
208
+ * Provides:
209
+ * - Pre-allocated particle pools outside the entity system
210
+ * - Continuous and burst emission modes
211
+ * - Velocity, gravity, lifetime, interpolation (size, alpha, tint, rotation)
212
+ * - World-space and local-space particle emission
213
+ * - PixiJS ParticleContainer rendering (via renderer2D dependency)
214
+ * - Presets for common effects (explosion, smoke, fire, sparkle, trail)
215
+ *
216
+ * Renderer2D is a required dependency.
217
+ */
218
+ export declare function createParticlePlugin<G extends string = 'particles'>(options?: ParticlePluginOptions<G>): Plugin<WorldConfigFrom<ParticleComponentTypes>, ParticleRequires, ParticleLabels, G, never, 'particle-emitters'>;
219
+ /**
220
+ * Get the runtime data for an emitter entity.
221
+ * Useful for tests and advanced usage.
222
+ * @internal Exported for testing only.
223
+ */
224
+ export declare function getEmitterData(emitterDataMap: Map<number, EmitterRuntimeData>, entityId: number): EmitterRuntimeData | undefined;
225
+ export {};
@@ -0,0 +1,163 @@
1
+ /**
2
+ * Physics 2D Plugin for ECSpresso
3
+ *
4
+ * Provides ECS-native arcade physics: gravity, forces, drag, semi-implicit Euler
5
+ * integration, and impulse-based collision response with friction.
6
+ *
7
+ * Reuses collider types from the collision plugin for shape definitions.
8
+ * Has its own collision detection in fixedUpdate for physics response;
9
+ * the existing collision plugin can still run in postUpdate for game logic events.
10
+ */
11
+ import { type Plugin } from 'ecspresso';
12
+ import type { SystemPhase } from 'ecspresso';
13
+ import type { WorldConfigFrom } from '../type-utils';
14
+ import type { TransformComponentTypes, TransformWorldConfig } from './transform';
15
+ import type { CollisionComponentTypes, LayerFactories } from './collision';
16
+ import type { Vector2D } from 'ecspresso';
17
+ /**
18
+ * Rigid body types for physics simulation.
19
+ * - 'dynamic': Fully simulated (gravity, forces, collisions)
20
+ * - 'kinematic': Moves via velocity only (ignores gravity/forces, immovable in collisions)
21
+ * - 'static': Immovable (ignores gravity, forces, and velocity)
22
+ */
23
+ export type BodyType = 'dynamic' | 'kinematic' | 'static';
24
+ /**
25
+ * Rigid body component controlling physics behavior.
26
+ */
27
+ export interface RigidBody {
28
+ type: BodyType;
29
+ /** Mass in arbitrary units. Affects force→acceleration. Infinity = immovable. */
30
+ mass: number;
31
+ /** Linear velocity damping coefficient (units/sec, 0 = none) */
32
+ drag: number;
33
+ /** Bounciness 0–1 (0 = no bounce, 1 = perfectly elastic) */
34
+ restitution: number;
35
+ /** Surface friction coefficient 0–1 */
36
+ friction: number;
37
+ /** Per-entity gravity multiplier (0 = no gravity) */
38
+ gravityScale: number;
39
+ }
40
+ /**
41
+ * Component types directly provided by the physics plugin.
42
+ */
43
+ export interface Physics2DOwnComponentTypes {
44
+ rigidBody: RigidBody;
45
+ velocity: Vector2D;
46
+ force: Vector2D;
47
+ }
48
+ /**
49
+ * Full component types available when using the physics plugin
50
+ * (own components + transform + collision dependencies).
51
+ * Convenience alias for consumer code.
52
+ */
53
+ export interface Physics2DComponentTypes<L extends string = never> extends TransformComponentTypes, CollisionComponentTypes<L>, Physics2DOwnComponentTypes {
54
+ }
55
+ /**
56
+ * Physics configuration resource.
57
+ */
58
+ export interface Physics2DConfig {
59
+ gravity: Vector2D;
60
+ }
61
+ export interface Physics2DResourceTypes {
62
+ physicsConfig: Physics2DConfig;
63
+ }
64
+ /**
65
+ * Event emitted for each physics collision pair.
66
+ */
67
+ export interface Physics2DCollisionEvent {
68
+ entityA: number;
69
+ entityB: number;
70
+ /** Unit normal pointing from A toward B */
71
+ normal: Vector2D;
72
+ /** Penetration depth (positive) */
73
+ depth: number;
74
+ }
75
+ export interface Physics2DEventTypes {
76
+ physicsCollision: Physics2DCollisionEvent;
77
+ }
78
+ export interface Physics2DPluginOptions<G extends string = 'physics2D', CG extends string = never> {
79
+ /** World gravity vector (default: {x: 0, y: 0}) */
80
+ gravity?: Vector2D;
81
+ /** System group name (default: 'physics2D') */
82
+ systemGroup?: G;
83
+ /** Additional group for the collision system only (default: none).
84
+ * When set, the collision system belongs to both `systemGroup` and this group,
85
+ * allowing independent enable/disable of collision detection. */
86
+ collisionSystemGroup?: CG;
87
+ /** Priority for integration system (default: 1000) */
88
+ integrationPriority?: number;
89
+ /** Priority for collision system (default: 900) */
90
+ collisionPriority?: number;
91
+ /** Execution phase (default: 'fixedUpdate') */
92
+ phase?: SystemPhase;
93
+ }
94
+ export interface RigidBodyOptions {
95
+ mass?: number;
96
+ drag?: number;
97
+ restitution?: number;
98
+ friction?: number;
99
+ gravityScale?: number;
100
+ }
101
+ /**
102
+ * Create a rigid body + force component pair.
103
+ * Static bodies automatically get mass=Infinity.
104
+ */
105
+ export declare function createRigidBody(type: BodyType, options?: RigidBodyOptions): {
106
+ rigidBody: RigidBody;
107
+ force: Vector2D;
108
+ };
109
+ /**
110
+ * Create a force component with initial values.
111
+ */
112
+ export declare function createForce(x: number, y: number): {
113
+ force: Vector2D;
114
+ };
115
+ /**
116
+ * Accumulate a force onto an entity's force component.
117
+ */
118
+ export declare function applyForce(ecs: {
119
+ getComponent(id: number, name: 'force'): Vector2D | undefined;
120
+ }, entityId: number, fx: number, fy: number): void;
121
+ /**
122
+ * Apply an instantaneous impulse: velocity += impulse / mass.
123
+ */
124
+ export declare function applyImpulse(ecs: {
125
+ getComponent(id: number, name: 'velocity'): Vector2D | undefined;
126
+ getComponent(id: number, name: 'rigidBody'): RigidBody | undefined;
127
+ }, entityId: number, ix: number, iy: number): void;
128
+ /**
129
+ * Directly set an entity's velocity.
130
+ */
131
+ export declare function setVelocity(ecs: {
132
+ getComponent(id: number, name: 'velocity'): Vector2D | undefined;
133
+ }, entityId: number, vx: number, vy: number): void;
134
+ /**
135
+ * Create a 2D physics plugin for ECSpresso.
136
+ *
137
+ * Provides:
138
+ * - Semi-implicit Euler integration (gravity, forces, drag → velocity → position)
139
+ * - Impulse-based collision response with restitution and friction
140
+ * - physicsCollision events with contact normal and depth
141
+ *
142
+ * @example
143
+ * ```typescript
144
+ * const ecs = ECSpresso.create()
145
+ * .withPlugin(createTransformPlugin())
146
+ * .withPlugin(createPhysics2DPlugin({ gravity: { x: 0, y: 980 } }))
147
+ * .withFixedTimestep(1/60)
148
+ * .build();
149
+ *
150
+ * ecs.spawn({
151
+ * ...createTransform(100, 200),
152
+ * ...createRigidBody('dynamic', { mass: 1, restitution: 0.5 }),
153
+ * velocity: { x: 0, y: 0 },
154
+ * ...createAABBCollider(32, 32),
155
+ * ...createCollisionLayer('player', ['ground']),
156
+ * });
157
+ * ```
158
+ */
159
+ type Physics2DProvides<L extends string = never> = Physics2DOwnComponentTypes & CollisionComponentTypes<L>;
160
+ export declare function createPhysics2DPlugin<L extends string = never, G extends string = 'physics2D', CG extends string = never>(options?: Physics2DPluginOptions<G, CG> & {
161
+ layers?: LayerFactories<Record<L, readonly string[]>>;
162
+ }): Plugin<WorldConfigFrom<Physics2DProvides<L>, Physics2DEventTypes, Physics2DResourceTypes>, TransformWorldConfig, 'physics2D-integration' | 'physics2D-collision', G | CG>;
163
+ export {};