ecspresso 0.10.2 → 0.11.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 +73 -17
- package/dist/asset-manager.d.ts +15 -15
- package/dist/asset-types.d.ts +16 -14
- package/dist/bundle.d.ts +66 -16
- package/dist/bundles/audio.d.ts +293 -0
- package/dist/bundles/{utils/bounds.d.ts → bounds.d.ts} +9 -7
- package/dist/bundles/camera.d.ts +89 -0
- package/dist/bundles/collision.d.ts +289 -0
- package/dist/bundles/diagnostics.d.ts +48 -0
- package/dist/bundles/{utils/input.d.ts → input.d.ts} +16 -17
- package/dist/bundles/physics2D.d.ts +159 -0
- package/dist/bundles/renderers/renderer2D.d.ts +65 -24
- package/dist/bundles/spatial-index.d.ts +57 -0
- package/dist/bundles/state-machine.d.ts +298 -0
- package/dist/bundles/{utils/timers.d.ts → timers.d.ts} +9 -8
- package/dist/bundles/{utils/transform.d.ts → transform.d.ts} +10 -10
- package/dist/bundles/tween.d.ts +197 -0
- package/dist/command-buffer.d.ts +20 -20
- package/dist/ecspresso-builder.d.ts +165 -0
- package/dist/ecspresso.d.ts +157 -178
- package/dist/entity-manager.d.ts +76 -40
- package/dist/event-bus.d.ts +6 -1
- package/dist/index.d.ts +1 -9
- package/dist/reactive-query-manager.d.ts +14 -3
- package/dist/resource-manager.d.ts +35 -19
- package/dist/screen-manager.d.ts +4 -4
- package/dist/screen-types.d.ts +12 -11
- package/dist/src/bundles/audio.js +4 -0
- package/dist/src/bundles/audio.js.map +10 -0
- package/dist/src/bundles/bounds.js +4 -0
- package/dist/src/bundles/bounds.js.map +10 -0
- package/dist/src/bundles/camera.js +4 -0
- package/dist/src/bundles/camera.js.map +10 -0
- package/dist/src/bundles/collision.js +4 -0
- package/dist/src/bundles/collision.js.map +11 -0
- package/dist/src/bundles/diagnostics.js +5 -0
- package/dist/src/bundles/diagnostics.js.map +10 -0
- package/dist/src/bundles/input.js +4 -0
- package/dist/src/bundles/input.js.map +10 -0
- package/dist/src/bundles/physics2D.js +4 -0
- package/dist/src/bundles/physics2D.js.map +11 -0
- package/dist/src/bundles/renderers/renderer2D.js +4 -0
- package/dist/src/bundles/renderers/renderer2D.js.map +10 -0
- package/dist/src/bundles/spatial-index.js +4 -0
- package/dist/src/bundles/spatial-index.js.map +11 -0
- package/dist/src/bundles/state-machine.js +4 -0
- package/dist/src/bundles/state-machine.js.map +10 -0
- package/dist/src/bundles/timers.js +4 -0
- package/dist/src/bundles/timers.js.map +10 -0
- package/dist/src/bundles/transform.js +4 -0
- package/dist/src/bundles/transform.js.map +10 -0
- package/dist/src/bundles/tween.js +4 -0
- package/dist/src/bundles/tween.js.map +11 -0
- package/dist/src/index.js +4 -0
- package/dist/src/index.js.map +25 -0
- package/dist/system-builder.d.ts +36 -42
- package/dist/type-utils.d.ts +52 -3
- package/dist/types.d.ts +10 -19
- 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 +50 -20
- 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.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,293 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Audio Bundle for ECSpresso
|
|
3
|
+
*
|
|
4
|
+
* Web Audio API integration via Howler.js for sound effects and music playback.
|
|
5
|
+
* User-defined channels with type-safe volume control, hybrid resource + component API,
|
|
6
|
+
* and asset manager integration.
|
|
7
|
+
*/
|
|
8
|
+
import { Bundle } from 'ecspresso';
|
|
9
|
+
import type { SystemPhase, AssetsOfWorld } from 'ecspresso';
|
|
10
|
+
import type { Howl } from 'howler';
|
|
11
|
+
/**
|
|
12
|
+
* Configuration for a single audio channel.
|
|
13
|
+
*/
|
|
14
|
+
export interface AudioChannelConfig {
|
|
15
|
+
readonly volume: number;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Define audio channels with type-safe names and initial volumes.
|
|
19
|
+
* Mirrors `defineCollisionLayers` pattern.
|
|
20
|
+
*
|
|
21
|
+
* @param channels Object mapping channel names to their configuration
|
|
22
|
+
* @returns Frozen channel configuration with inferred channel name union
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* ```typescript
|
|
26
|
+
* const channels = defineAudioChannels({
|
|
27
|
+
* sfx: { volume: 1 },
|
|
28
|
+
* music: { volume: 0.7 },
|
|
29
|
+
* ui: { volume: 0.8 },
|
|
30
|
+
* });
|
|
31
|
+
* type Ch = ChannelsOf<typeof channels>; // 'sfx' | 'music' | 'ui'
|
|
32
|
+
* ```
|
|
33
|
+
*/
|
|
34
|
+
export declare function defineAudioChannels<const T extends Record<string, AudioChannelConfig>>(channels: T): Readonly<T>;
|
|
35
|
+
/**
|
|
36
|
+
* Extract channel name union from a `defineAudioChannels` result.
|
|
37
|
+
*/
|
|
38
|
+
export type ChannelsOf<T> = T extends Record<infer K extends string, AudioChannelConfig> ? K : never;
|
|
39
|
+
/**
|
|
40
|
+
* Audio source component attached to entities for positional/entity-bound audio.
|
|
41
|
+
*/
|
|
42
|
+
export interface AudioSource<Ch extends string = string> {
|
|
43
|
+
/** Asset key for the sound */
|
|
44
|
+
readonly sound: string;
|
|
45
|
+
/** Channel this sound plays on */
|
|
46
|
+
readonly channel: Ch;
|
|
47
|
+
/** Individual volume (0-1) */
|
|
48
|
+
volume: number;
|
|
49
|
+
/** Whether sound loops */
|
|
50
|
+
loop: boolean;
|
|
51
|
+
/** Remove entity when sound ends (like timer autoRemove) */
|
|
52
|
+
autoRemove: boolean;
|
|
53
|
+
/** Whether sound is currently playing (system-managed) */
|
|
54
|
+
playing: boolean;
|
|
55
|
+
/** Howler sound ID (system-managed, -1 = not started) */
|
|
56
|
+
_soundId: number;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Component types provided by the audio bundle.
|
|
60
|
+
*/
|
|
61
|
+
export interface AudioComponentTypes<Ch extends string = string> {
|
|
62
|
+
audioSource: AudioSource<Ch>;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Event to trigger fire-and-forget sound playback from any system.
|
|
66
|
+
*/
|
|
67
|
+
export interface PlaySoundEvent<Ch extends string = string> {
|
|
68
|
+
/** Asset key for the sound */
|
|
69
|
+
sound: string;
|
|
70
|
+
/** Channel to play on */
|
|
71
|
+
channel?: Ch;
|
|
72
|
+
/** Individual volume (0-1) */
|
|
73
|
+
volume?: number;
|
|
74
|
+
/** Whether sound loops */
|
|
75
|
+
loop?: boolean;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Event to stop music on a channel.
|
|
79
|
+
*/
|
|
80
|
+
export interface StopMusicEvent<Ch extends string = string> {
|
|
81
|
+
/** Channel to stop music on. If omitted, stops all music. */
|
|
82
|
+
channel?: Ch;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Event published when a sound finishes playing.
|
|
86
|
+
*/
|
|
87
|
+
export interface SoundEndedEvent {
|
|
88
|
+
/** Entity ID if sound was entity-attached, -1 for fire-and-forget */
|
|
89
|
+
entityId: number;
|
|
90
|
+
/** Howler sound ID */
|
|
91
|
+
soundId: number;
|
|
92
|
+
/** Asset key of the sound */
|
|
93
|
+
sound: string;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Event types provided by the audio bundle.
|
|
97
|
+
*/
|
|
98
|
+
export interface AudioEventTypes<Ch extends string = string> {
|
|
99
|
+
playSound: PlaySoundEvent<Ch>;
|
|
100
|
+
stopMusic: StopMusicEvent<Ch>;
|
|
101
|
+
soundEnded: SoundEndedEvent;
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Play options for fire-and-forget sound effects.
|
|
105
|
+
*/
|
|
106
|
+
export interface PlayOptions<Ch extends string = string> {
|
|
107
|
+
/** Channel to play on (uses first defined channel if omitted) */
|
|
108
|
+
channel?: Ch;
|
|
109
|
+
/** Individual volume (0-1, default: 1) */
|
|
110
|
+
volume?: number;
|
|
111
|
+
/** Whether to loop (default: false) */
|
|
112
|
+
loop?: boolean;
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Music playback options.
|
|
116
|
+
*/
|
|
117
|
+
export interface MusicOptions<Ch extends string = string> {
|
|
118
|
+
/** Channel to play music on (uses first defined channel if omitted) */
|
|
119
|
+
channel?: Ch;
|
|
120
|
+
/** Volume (0-1, default: 1) */
|
|
121
|
+
volume?: number;
|
|
122
|
+
/** Whether to loop (default: true) */
|
|
123
|
+
loop?: boolean;
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Audio state resource providing fire-and-forget SFX and music control.
|
|
127
|
+
* Effective volume = individual * channel * master.
|
|
128
|
+
*/
|
|
129
|
+
export interface AudioState<Ch extends string = string> {
|
|
130
|
+
/** Play a fire-and-forget sound effect. Returns the Howler sound ID. */
|
|
131
|
+
play(sound: string, options?: PlayOptions<Ch>): number;
|
|
132
|
+
/** Stop a specific sound by its Howler sound ID. */
|
|
133
|
+
stop(soundId: number): void;
|
|
134
|
+
/** Play music on a channel. Stops any existing music on that channel first. */
|
|
135
|
+
playMusic(sound: string, options?: MusicOptions<Ch>): void;
|
|
136
|
+
/** Stop music on a channel. If omitted, stops all music. */
|
|
137
|
+
stopMusic(channel?: Ch): void;
|
|
138
|
+
/** Pause music on a channel. If omitted, pauses all music. */
|
|
139
|
+
pauseMusic(channel?: Ch): void;
|
|
140
|
+
/** Resume music on a channel. If omitted, resumes all music. */
|
|
141
|
+
resumeMusic(channel?: Ch): void;
|
|
142
|
+
/** Set volume for a channel (0-1). */
|
|
143
|
+
setChannelVolume(channel: Ch, volume: number): void;
|
|
144
|
+
/** Get current volume for a channel. */
|
|
145
|
+
getChannelVolume(channel: Ch): number;
|
|
146
|
+
/** Set master volume (0-1). */
|
|
147
|
+
setMasterVolume(volume: number): void;
|
|
148
|
+
/** Get current master volume. */
|
|
149
|
+
getMasterVolume(): number;
|
|
150
|
+
/** Mute all audio. */
|
|
151
|
+
mute(): void;
|
|
152
|
+
/** Unmute all audio. */
|
|
153
|
+
unmute(): void;
|
|
154
|
+
/** Toggle mute state. */
|
|
155
|
+
toggleMute(): void;
|
|
156
|
+
/** Check if audio is muted. */
|
|
157
|
+
isMuted(): boolean;
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Resource types provided by the audio bundle.
|
|
161
|
+
*/
|
|
162
|
+
export interface AudioResourceTypes<Ch extends string = string> {
|
|
163
|
+
audioState: AudioState<Ch>;
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Configuration options for the audio bundle.
|
|
167
|
+
*/
|
|
168
|
+
export interface AudioBundleOptions<Ch extends string, G extends string = 'audio'> {
|
|
169
|
+
/** Channel definitions from defineAudioChannels */
|
|
170
|
+
channels: Readonly<Record<Ch, AudioChannelConfig>>;
|
|
171
|
+
/** System group name (default: 'audio') */
|
|
172
|
+
systemGroup?: G;
|
|
173
|
+
/** Priority for audio sync system (default: 0) */
|
|
174
|
+
priority?: number;
|
|
175
|
+
/** Execution phase (default: 'update') */
|
|
176
|
+
phase?: SystemPhase;
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Create an audioSource component for entity-attached audio.
|
|
180
|
+
*
|
|
181
|
+
* @param sound Asset key for the sound
|
|
182
|
+
* @param channel Channel to play on
|
|
183
|
+
* @param options Optional configuration
|
|
184
|
+
* @returns Component object suitable for spreading into spawn()
|
|
185
|
+
*
|
|
186
|
+
* @example
|
|
187
|
+
* ```typescript
|
|
188
|
+
* ecs.spawn({
|
|
189
|
+
* ...createAudioSource('explosion', 'sfx'),
|
|
190
|
+
* ...createTransform(100, 200),
|
|
191
|
+
* });
|
|
192
|
+
* ```
|
|
193
|
+
*/
|
|
194
|
+
export declare function createAudioSource<Ch extends string>(sound: string, channel: Ch, options?: {
|
|
195
|
+
volume?: number;
|
|
196
|
+
loop?: boolean;
|
|
197
|
+
autoRemove?: boolean;
|
|
198
|
+
}): Pick<AudioComponentTypes<Ch>, 'audioSource'>;
|
|
199
|
+
/**
|
|
200
|
+
* Create a loader function for use with the asset manager.
|
|
201
|
+
* Returns a factory function that loads a Howl when called.
|
|
202
|
+
*
|
|
203
|
+
* @param src URL(s) for the sound file
|
|
204
|
+
* @param options Optional Howl configuration
|
|
205
|
+
* @returns Factory function compatible with asset manager's loader parameter
|
|
206
|
+
*
|
|
207
|
+
* @example
|
|
208
|
+
* ```typescript
|
|
209
|
+
* const ecs = ECSpresso.create()
|
|
210
|
+
* .withAssets(a => a
|
|
211
|
+
* .add('explosion', loadSound('/sounds/explosion.mp3'))
|
|
212
|
+
* .add('bgm', loadSound(['/sounds/bgm.webm', '/sounds/bgm.mp3']))
|
|
213
|
+
* )
|
|
214
|
+
* .build();
|
|
215
|
+
* ```
|
|
216
|
+
*/
|
|
217
|
+
export declare function loadSound(src: string | string[], options?: {
|
|
218
|
+
html5?: boolean;
|
|
219
|
+
preload?: boolean;
|
|
220
|
+
}): () => Promise<Howl>;
|
|
221
|
+
/**
|
|
222
|
+
* Create an audio bundle for ECSpresso.
|
|
223
|
+
*
|
|
224
|
+
* Provides:
|
|
225
|
+
* - `audioState` resource for fire-and-forget SFX and music
|
|
226
|
+
* - `audioSource` component for entity-attached sounds
|
|
227
|
+
* - Volume hierarchy: individual * channel * master
|
|
228
|
+
* - `playSound` / `stopMusic` event handlers
|
|
229
|
+
* - `soundEnded` event on completion
|
|
230
|
+
* - Automatic cleanup on entity removal (dispose callback)
|
|
231
|
+
*
|
|
232
|
+
* Sounds must be preloaded through the asset pipeline (`loadSound` helper).
|
|
233
|
+
*
|
|
234
|
+
* @example
|
|
235
|
+
* ```typescript
|
|
236
|
+
* const channels = defineAudioChannels({
|
|
237
|
+
* sfx: { volume: 1 },
|
|
238
|
+
* music: { volume: 0.7 },
|
|
239
|
+
* });
|
|
240
|
+
*
|
|
241
|
+
* const ecs = ECSpresso.create()
|
|
242
|
+
* .withAssets(a => a.add('explosion', loadSound('/sfx/boom.mp3')))
|
|
243
|
+
* .withBundle(createAudioBundle({ channels }))
|
|
244
|
+
* .build();
|
|
245
|
+
*
|
|
246
|
+
* await ecs.initialize();
|
|
247
|
+
* const audio = ecs.getResource('audioState');
|
|
248
|
+
* audio.play('explosion', { channel: 'sfx' });
|
|
249
|
+
* ```
|
|
250
|
+
*/
|
|
251
|
+
export declare function createAudioBundle<Ch extends string, G extends string = 'audio'>(options: AudioBundleOptions<Ch, G>): Bundle<AudioComponentTypes<Ch>, AudioEventTypes<Ch>, AudioResourceTypes<Ch>, {}, {}, 'audio-sync', G, never, 'audio-sources'>;
|
|
252
|
+
type AnyECSpresso = import('ecspresso').default<any, any, any, any, any, any, any>;
|
|
253
|
+
/**
|
|
254
|
+
* Kit result from createAudioKit.
|
|
255
|
+
*/
|
|
256
|
+
export interface AudioKit<W extends AnyECSpresso, Ch extends string, G extends string = 'audio'> {
|
|
257
|
+
bundle: Bundle<AudioComponentTypes<Ch>, AudioEventTypes<Ch>, AudioResourceTypes<Ch>, {}, {}, 'audio-sync', G, never, 'audio-sources'>;
|
|
258
|
+
createAudioSource: (sound: keyof AssetsOfWorld<W> & string, channel: Ch, options?: {
|
|
259
|
+
volume?: number;
|
|
260
|
+
loop?: boolean;
|
|
261
|
+
autoRemove?: boolean;
|
|
262
|
+
}) => Pick<AudioComponentTypes<Ch>, 'audioSource'>;
|
|
263
|
+
loadSound: typeof loadSound;
|
|
264
|
+
}
|
|
265
|
+
/**
|
|
266
|
+
* Create a typed audio kit that captures the world type W and channel type Ch.
|
|
267
|
+
*
|
|
268
|
+
* The returned `createAudioSource` validates sound keys against the world's
|
|
269
|
+
* asset types at compile time.
|
|
270
|
+
*
|
|
271
|
+
* @template W - Concrete ECS world type (e.g. `typeof ecs`)
|
|
272
|
+
* @template Ch - Channel name union from defineAudioChannels
|
|
273
|
+
* @template G - System group name (default: 'audio')
|
|
274
|
+
* @param options - Bundle configuration including channel definitions
|
|
275
|
+
* @returns A kit object with bundle, createAudioSource, loadSound
|
|
276
|
+
*
|
|
277
|
+
* @example
|
|
278
|
+
* ```typescript
|
|
279
|
+
* const channels = defineAudioChannels({ sfx: { volume: 1 }, music: { volume: 0.7 } });
|
|
280
|
+
* type Ch = ChannelsOf<typeof channels>;
|
|
281
|
+
* const kit = createAudioKit<typeof ecs, Ch>({ channels });
|
|
282
|
+
*
|
|
283
|
+
* const ecs = ECSpresso.create()
|
|
284
|
+
* .withBundle(kit.bundle)
|
|
285
|
+
* .withAssets(a => a.add('boom', loadSound('/sfx/boom.mp3')))
|
|
286
|
+
* .build();
|
|
287
|
+
*
|
|
288
|
+
* // Type-safe: 'boom' must be a registered asset
|
|
289
|
+
* kit.createAudioSource('boom', 'sfx');
|
|
290
|
+
* ```
|
|
291
|
+
*/
|
|
292
|
+
export declare function createAudioKit<W extends AnyECSpresso, Ch extends string, G extends string = 'audio'>(options: AudioBundleOptions<Ch, G>): AudioKit<W, Ch, G>;
|
|
293
|
+
export {};
|
|
@@ -31,13 +31,15 @@ export interface WrapAtBounds {
|
|
|
31
31
|
}
|
|
32
32
|
/**
|
|
33
33
|
* Component types provided by the bounds bundle.
|
|
34
|
-
*
|
|
34
|
+
* Included automatically via `.withBundle(createBoundsBundle())`.
|
|
35
35
|
*
|
|
36
36
|
* @example
|
|
37
37
|
* ```typescript
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
* }
|
|
38
|
+
* const ecs = ECSpresso.create()
|
|
39
|
+
* .withBundle(createTransformBundle())
|
|
40
|
+
* .withBundle(createBoundsBundle({ width: 800, height: 600 }))
|
|
41
|
+
* .withComponentTypes<{ sprite: Sprite }>()
|
|
42
|
+
* .build();
|
|
41
43
|
* ```
|
|
42
44
|
*/
|
|
43
45
|
export interface BoundsComponentTypes {
|
|
@@ -82,9 +84,9 @@ export interface BoundsEventTypes {
|
|
|
82
84
|
/**
|
|
83
85
|
* Configuration options for the bounds bundle.
|
|
84
86
|
*/
|
|
85
|
-
export interface BoundsBundleOptions {
|
|
87
|
+
export interface BoundsBundleOptions<G extends string = 'physics'> {
|
|
86
88
|
/** System group name (default: 'physics') */
|
|
87
|
-
systemGroup?:
|
|
89
|
+
systemGroup?: G;
|
|
88
90
|
/** Priority for bounds systems (default: 50) */
|
|
89
91
|
priority?: number;
|
|
90
92
|
/** Resource key for bounds rectangle (default: 'bounds') */
|
|
@@ -185,5 +187,5 @@ type CombinedComponentTypes = BoundsComponentTypes & TransformComponentTypes;
|
|
|
185
187
|
* });
|
|
186
188
|
* ```
|
|
187
189
|
*/
|
|
188
|
-
export declare function createBoundsBundle<ResourceTypes extends BoundsResourceTypes = BoundsResourceTypes>(options?: BoundsBundleOptions): Bundle<CombinedComponentTypes, BoundsEventTypes, ResourceTypes>;
|
|
190
|
+
export declare function createBoundsBundle<ResourceTypes extends BoundsResourceTypes = BoundsResourceTypes, G extends string = 'physics'>(options?: BoundsBundleOptions<G>): Bundle<CombinedComponentTypes, BoundsEventTypes, ResourceTypes, {}, {}, 'bounds-destroy' | 'bounds-clamp' | 'bounds-wrap', G>;
|
|
189
191
|
export {};
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Camera / Viewport Bundle for ECSpresso
|
|
3
|
+
*
|
|
4
|
+
* Provides a camera entity with world/screen coordinate conversion, smooth follow,
|
|
5
|
+
* trauma-based shake, bounds clamping, and logical viewport dimensions.
|
|
6
|
+
*
|
|
7
|
+
* This bundle is renderer-agnostic. PixiJS or other renderer integration (applying
|
|
8
|
+
* cameraState to a container/stage transform) is the consumer's responsibility.
|
|
9
|
+
*
|
|
10
|
+
* Camera uses its own x/y/zoom/rotation rather than localTransform/worldTransform.
|
|
11
|
+
* It reads the target entity's worldTransform for follow, but doesn't participate
|
|
12
|
+
* in the transform hierarchy itself.
|
|
13
|
+
*/
|
|
14
|
+
import { Bundle } from 'ecspresso';
|
|
15
|
+
import type { SystemPhase } from 'ecspresso';
|
|
16
|
+
import type ECSpresso from 'ecspresso';
|
|
17
|
+
import type { TransformComponentTypes } from './transform';
|
|
18
|
+
export interface Camera {
|
|
19
|
+
x: number;
|
|
20
|
+
y: number;
|
|
21
|
+
zoom: number;
|
|
22
|
+
rotation: number;
|
|
23
|
+
}
|
|
24
|
+
export interface CameraFollow {
|
|
25
|
+
target: number;
|
|
26
|
+
smoothing: number;
|
|
27
|
+
deadzoneX: number;
|
|
28
|
+
deadzoneY: number;
|
|
29
|
+
offsetX: number;
|
|
30
|
+
offsetY: number;
|
|
31
|
+
}
|
|
32
|
+
export interface CameraShake {
|
|
33
|
+
trauma: number;
|
|
34
|
+
traumaDecay: number;
|
|
35
|
+
maxOffsetX: number;
|
|
36
|
+
maxOffsetY: number;
|
|
37
|
+
maxRotation: number;
|
|
38
|
+
}
|
|
39
|
+
export interface CameraBounds {
|
|
40
|
+
minX: number;
|
|
41
|
+
minY: number;
|
|
42
|
+
maxX: number;
|
|
43
|
+
maxY: number;
|
|
44
|
+
}
|
|
45
|
+
export interface CameraComponentTypes {
|
|
46
|
+
camera: Camera;
|
|
47
|
+
cameraFollow: CameraFollow;
|
|
48
|
+
cameraShake: CameraShake;
|
|
49
|
+
cameraBounds: CameraBounds;
|
|
50
|
+
}
|
|
51
|
+
type CombinedComponentTypes = CameraComponentTypes & TransformComponentTypes;
|
|
52
|
+
export interface CameraState {
|
|
53
|
+
x: number;
|
|
54
|
+
y: number;
|
|
55
|
+
zoom: number;
|
|
56
|
+
rotation: number;
|
|
57
|
+
shakeOffsetX: number;
|
|
58
|
+
shakeOffsetY: number;
|
|
59
|
+
shakeRotation: number;
|
|
60
|
+
viewportWidth: number;
|
|
61
|
+
viewportHeight: number;
|
|
62
|
+
}
|
|
63
|
+
export interface CameraResourceTypes {
|
|
64
|
+
cameraState: CameraState;
|
|
65
|
+
}
|
|
66
|
+
export interface CameraBundleOptions<G extends string = 'camera'> {
|
|
67
|
+
viewportWidth?: number;
|
|
68
|
+
viewportHeight?: number;
|
|
69
|
+
systemGroup?: G;
|
|
70
|
+
phase?: SystemPhase;
|
|
71
|
+
randomFn?: () => number;
|
|
72
|
+
}
|
|
73
|
+
export declare const DEFAULT_CAMERA: Readonly<Camera>;
|
|
74
|
+
export declare const DEFAULT_CAMERA_STATE: Readonly<CameraState>;
|
|
75
|
+
export declare function createCamera(x?: number, y?: number, zoom?: number, rotation?: number): Pick<CameraComponentTypes, 'camera'>;
|
|
76
|
+
export declare function createCameraFollow(target: number, options?: Partial<Omit<CameraFollow, 'target'>>): Pick<CameraComponentTypes, 'cameraFollow'>;
|
|
77
|
+
export declare function createCameraShake(options?: Partial<CameraShake>): Pick<CameraComponentTypes, 'cameraShake'>;
|
|
78
|
+
export declare function createCameraBounds(minX: number, minY: number, maxX: number, maxY: number): Pick<CameraComponentTypes, 'cameraBounds'>;
|
|
79
|
+
export declare function addTrauma<C extends CombinedComponentTypes, R extends CameraResourceTypes>(ecs: ECSpresso<C, any, R>, entityId: number, amount: number): void;
|
|
80
|
+
export declare function worldToScreen(worldX: number, worldY: number, state: CameraState): {
|
|
81
|
+
x: number;
|
|
82
|
+
y: number;
|
|
83
|
+
};
|
|
84
|
+
export declare function screenToWorld(screenX: number, screenY: number, state: CameraState): {
|
|
85
|
+
x: number;
|
|
86
|
+
y: number;
|
|
87
|
+
};
|
|
88
|
+
export declare function createCameraBundle<G extends string = 'camera'>(options?: CameraBundleOptions<G>): Bundle<CombinedComponentTypes, {}, CameraResourceTypes, {}, {}, 'camera-follow' | 'camera-shake-update' | 'camera-bounds' | 'camera-state-sync', G>;
|
|
89
|
+
export {};
|