blecsd 0.1.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/LICENSE +20 -0
- package/README.md +220 -0
- package/dist/3d/index.d.ts +5 -0
- package/dist/3d/index.js +1 -0
- package/dist/audio/index.d.ts +177 -0
- package/dist/audio/index.js +1 -0
- package/dist/border-D_Jb4ZJV.d.ts +257 -0
- package/dist/cell-DwIu2ryP.d.ts +505 -0
- package/dist/chunk-2UBBZFE4.js +1 -0
- package/dist/chunk-35LCBY6P.js +1 -0
- package/dist/chunk-3B7MIVW6.js +1 -0
- package/dist/chunk-3EGGGI5J.js +3 -0
- package/dist/chunk-4LWWONFK.js +1 -0
- package/dist/chunk-4X4N4HNQ.js +2 -0
- package/dist/chunk-5PELJRUQ.js +1 -0
- package/dist/chunk-AEJIX2MW.js +1 -0
- package/dist/chunk-AQ7LW75B.js +1 -0
- package/dist/chunk-AXZQAH4X.js +1 -0
- package/dist/chunk-B6Z2JFRY.js +1 -0
- package/dist/chunk-BCADUCOZ.js +1 -0
- package/dist/chunk-C5PCEQ6G.js +1 -0
- package/dist/chunk-CIK4AMUA.js +1 -0
- package/dist/chunk-DNRXW56C.js +1 -0
- package/dist/chunk-FC5FFAAC.js +12 -0
- package/dist/chunk-FGHEFXLK.js +1 -0
- package/dist/chunk-FYEBZAWN.js +1 -0
- package/dist/chunk-G7GIWWLE.js +1 -0
- package/dist/chunk-GYHI26UE.js +1 -0
- package/dist/chunk-H2YAOJDW.js +1 -0
- package/dist/chunk-J4JZ2NU2.js +1 -0
- package/dist/chunk-JKVHO4LH.js +1 -0
- package/dist/chunk-K2B2OXQ5.js +5 -0
- package/dist/chunk-K37L3G4Z.js +4 -0
- package/dist/chunk-KD55INV7.js +1 -0
- package/dist/chunk-KFAK4A3G.js +1 -0
- package/dist/chunk-LCN2ZITE.js +1 -0
- package/dist/chunk-LYSK5S63.js +1 -0
- package/dist/chunk-NZ55KBM6.js +1 -0
- package/dist/chunk-OMMJ7B5P.js +1 -0
- package/dist/chunk-OUXUPF3V.js +33 -0
- package/dist/chunk-OVT2PPGW.js +19 -0
- package/dist/chunk-P6CJO3BC.js +1 -0
- package/dist/chunk-PSXXMBVJ.js +1 -0
- package/dist/chunk-PXXGH3BV.js +1 -0
- package/dist/chunk-QIKIOVP2.js +1 -0
- package/dist/chunk-SHUC6JWA.js +1 -0
- package/dist/chunk-TDXJDLY6.js +6 -0
- package/dist/chunk-TWSWTBYL.js +1 -0
- package/dist/chunk-TYMY2TBR.js +3 -0
- package/dist/chunk-VNZ6CWJA.js +2 -0
- package/dist/chunk-VOCM5T2G.js +5 -0
- package/dist/chunk-W5OU7Z6J.js +1 -0
- package/dist/chunk-WNG4A3K7.js +4 -0
- package/dist/chunk-XQIGERNI.js +1 -0
- package/dist/chunk-XZA63ZPO.js +1 -0
- package/dist/chunk-YAMOSPWB.js +4 -0
- package/dist/chunk-YD6ULIUR.js +1 -0
- package/dist/chunk-Z4EZERNE.js +1 -0
- package/dist/cli/init.d.ts +86 -0
- package/dist/cli/init.js +179 -0
- package/dist/color-B78w3zH-.d.ts +79 -0
- package/dist/components/index.d.ts +10298 -0
- package/dist/components/index.js +1 -0
- package/dist/core/index.d.ts +6700 -0
- package/dist/core/index.js +1 -0
- package/dist/debug/index.d.ts +711 -0
- package/dist/debug/index.js +1 -0
- package/dist/doubleBuffer-CKQFmlPN.d.ts +95 -0
- package/dist/errors/index.d.ts +1110 -0
- package/dist/errors/index.js +1 -0
- package/dist/events-BbbxkgvX.d.ts +125 -0
- package/dist/game/index.d.ts +486 -0
- package/dist/game/index.js +1 -0
- package/dist/gameLoop-BIPW7-OY.d.ts +219 -0
- package/dist/index-zSGJ2eUk.d.ts +3156 -0
- package/dist/index.d.ts +246 -0
- package/dist/index.js +1 -0
- package/dist/input/index.d.ts +158 -0
- package/dist/input/index.js +1 -0
- package/dist/inputActions-CefRUBuT.d.ts +2637 -0
- package/dist/keyParser-Bwm8-l7v.d.ts +229 -0
- package/dist/mouseParser-Cfrbn3AX.d.ts +177 -0
- package/dist/parser-iMHmQuUh.d.ts +265 -0
- package/dist/program-BZaKqDKH.d.ts +141 -0
- package/dist/renderable-jTMOA-GK.d.ts +302 -0
- package/dist/scheduler-DcfoFuum.d.ts +86 -0
- package/dist/schemas/index.d.ts +936 -0
- package/dist/schemas/index.js +1 -0
- package/dist/systems/index.d.ts +4036 -0
- package/dist/systems/index.js +1 -0
- package/dist/terminal/index.d.ts +7357 -0
- package/dist/terminal/index.js +1 -0
- package/dist/terminus-14-bold-HWSPRLJD.js +1 -0
- package/dist/terminus-14-normal-T3SWMH4D.js +1 -0
- package/dist/tilemap-D1HJvKy3.d.ts +1211 -0
- package/dist/types-BcsvoKzf.d.ts +68 -0
- package/dist/utils/index.d.ts +6104 -0
- package/dist/utils/index.js +1 -0
- package/dist/viewport3d-xI33-_wq.d.ts +182 -0
- package/dist/virtualScrollback-DvZTRU8a.d.ts +274 -0
- package/dist/virtualViewport-Dx2iJliO.d.ts +2334 -0
- package/dist/virtualizedLineStore-DwPEvPkk.d.ts +297 -0
- package/dist/widgets/bigText.d.ts +230 -0
- package/dist/widgets/bigText.js +1 -0
- package/dist/widgets/fonts/index.d.ts +211 -0
- package/dist/widgets/fonts/index.js +1 -0
- package/dist/widgets/index.d.ts +8591 -0
- package/dist/widgets/index.js +1 -0
- package/package.json +213 -0
|
@@ -0,0 +1,1211 @@
|
|
|
1
|
+
import { E as Entity, W as World } from './types-BcsvoKzf.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Collision component for entity collision detection.
|
|
5
|
+
* @module components/collision
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Collider shape types.
|
|
10
|
+
*/
|
|
11
|
+
declare enum ColliderType {
|
|
12
|
+
/** Axis-aligned bounding box */
|
|
13
|
+
BOX = 0,
|
|
14
|
+
/** Circle collider */
|
|
15
|
+
CIRCLE = 1
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Collider component store using SoA (Structure of Arrays) for performance.
|
|
19
|
+
*
|
|
20
|
+
* - `type`: Collider shape (BOX or CIRCLE)
|
|
21
|
+
* - `width`, `height`: Dimensions (for BOX, height ignored for CIRCLE where width=diameter)
|
|
22
|
+
* - `offsetX`, `offsetY`: Offset from entity position
|
|
23
|
+
* - `layer`: Collision layer bitmask (what layer this entity is on)
|
|
24
|
+
* - `mask`: Collision mask bitmask (what layers to collide with)
|
|
25
|
+
* - `isTrigger`: Whether collider is a trigger (events only, no physics response)
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* ```typescript
|
|
29
|
+
* import { setCollider, ColliderType } from 'blecsd';
|
|
30
|
+
*
|
|
31
|
+
* // Box collider
|
|
32
|
+
* setCollider(world, entity, {
|
|
33
|
+
* type: ColliderType.BOX,
|
|
34
|
+
* width: 2,
|
|
35
|
+
* height: 1,
|
|
36
|
+
* });
|
|
37
|
+
*
|
|
38
|
+
* // Circle collider as trigger
|
|
39
|
+
* setCollider(world, entity, {
|
|
40
|
+
* type: ColliderType.CIRCLE,
|
|
41
|
+
* width: 3, // diameter
|
|
42
|
+
* isTrigger: true,
|
|
43
|
+
* });
|
|
44
|
+
* ```
|
|
45
|
+
*/
|
|
46
|
+
declare const Collider: {
|
|
47
|
+
/** Collider type (0=BOX, 1=CIRCLE) */
|
|
48
|
+
type: Uint8Array<ArrayBuffer>;
|
|
49
|
+
/** Width (or diameter for circles) */
|
|
50
|
+
width: Float32Array<ArrayBuffer>;
|
|
51
|
+
/** Height (ignored for circles) */
|
|
52
|
+
height: Float32Array<ArrayBuffer>;
|
|
53
|
+
/** X offset from entity position */
|
|
54
|
+
offsetX: Float32Array<ArrayBuffer>;
|
|
55
|
+
/** Y offset from entity position */
|
|
56
|
+
offsetY: Float32Array<ArrayBuffer>;
|
|
57
|
+
/** Collision layer bitmask */
|
|
58
|
+
layer: Uint16Array<ArrayBuffer>;
|
|
59
|
+
/** Collision mask (layers to collide with) */
|
|
60
|
+
mask: Uint16Array<ArrayBuffer>;
|
|
61
|
+
/** Whether this is a trigger (1) or solid (0) */
|
|
62
|
+
isTrigger: Uint8Array<ArrayBuffer>;
|
|
63
|
+
};
|
|
64
|
+
/**
|
|
65
|
+
* Collider data returned by getCollider.
|
|
66
|
+
*/
|
|
67
|
+
interface ColliderData {
|
|
68
|
+
readonly type: ColliderType;
|
|
69
|
+
readonly width: number;
|
|
70
|
+
readonly height: number;
|
|
71
|
+
readonly offsetX: number;
|
|
72
|
+
readonly offsetY: number;
|
|
73
|
+
readonly layer: number;
|
|
74
|
+
readonly mask: number;
|
|
75
|
+
readonly isTrigger: boolean;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Options for setting a collider.
|
|
79
|
+
*/
|
|
80
|
+
interface ColliderOptions {
|
|
81
|
+
/** Collider type (default: BOX) */
|
|
82
|
+
type?: ColliderType;
|
|
83
|
+
/** Width or diameter (default: 1) */
|
|
84
|
+
width?: number;
|
|
85
|
+
/** Height, ignored for circles (default: 1) */
|
|
86
|
+
height?: number;
|
|
87
|
+
/** X offset from position (default: 0) */
|
|
88
|
+
offsetX?: number;
|
|
89
|
+
/** Y offset from position (default: 0) */
|
|
90
|
+
offsetY?: number;
|
|
91
|
+
/** Collision layer bitmask (default: 1) */
|
|
92
|
+
layer?: number;
|
|
93
|
+
/** Collision mask (default: 0xFFFF - collide with all) */
|
|
94
|
+
mask?: number;
|
|
95
|
+
/** Whether this is a trigger only (default: false) */
|
|
96
|
+
isTrigger?: boolean;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Default collision layer.
|
|
100
|
+
*/
|
|
101
|
+
declare const DEFAULT_LAYER = 1;
|
|
102
|
+
/**
|
|
103
|
+
* Default collision mask (collide with all layers).
|
|
104
|
+
*/
|
|
105
|
+
declare const DEFAULT_MASK = 65535;
|
|
106
|
+
/**
|
|
107
|
+
* Sets a collider on an entity.
|
|
108
|
+
* Adds the Collider component if not already present.
|
|
109
|
+
*
|
|
110
|
+
* @param world - The ECS world
|
|
111
|
+
* @param eid - The entity ID
|
|
112
|
+
* @param options - Collider options
|
|
113
|
+
* @returns The entity ID for chaining
|
|
114
|
+
*
|
|
115
|
+
* @example
|
|
116
|
+
* ```typescript
|
|
117
|
+
* import { setCollider, ColliderType } from 'blecsd';
|
|
118
|
+
*
|
|
119
|
+
* // Create a box collider
|
|
120
|
+
* setCollider(world, player, {
|
|
121
|
+
* type: ColliderType.BOX,
|
|
122
|
+
* width: 1,
|
|
123
|
+
* height: 2,
|
|
124
|
+
* layer: 0b0001, // Player layer
|
|
125
|
+
* mask: 0b0110, // Collide with enemies and walls
|
|
126
|
+
* });
|
|
127
|
+
*
|
|
128
|
+
* // Create a trigger zone
|
|
129
|
+
* setCollider(world, checkpoint, {
|
|
130
|
+
* type: ColliderType.BOX,
|
|
131
|
+
* width: 3,
|
|
132
|
+
* height: 3,
|
|
133
|
+
* isTrigger: true,
|
|
134
|
+
* });
|
|
135
|
+
* ```
|
|
136
|
+
*/
|
|
137
|
+
declare function setCollider(world: World, eid: Entity, options?: ColliderOptions): Entity;
|
|
138
|
+
/**
|
|
139
|
+
* Gets the collider data of an entity.
|
|
140
|
+
*
|
|
141
|
+
* @param world - The ECS world
|
|
142
|
+
* @param eid - The entity ID
|
|
143
|
+
* @returns Collider data or undefined
|
|
144
|
+
*
|
|
145
|
+
* @example
|
|
146
|
+
* ```typescript
|
|
147
|
+
* import { getCollider } from 'blecsd';
|
|
148
|
+
*
|
|
149
|
+
* const collider = getCollider(world, entity);
|
|
150
|
+
* if (collider) {
|
|
151
|
+
* console.log(`Collider: ${collider.width}x${collider.height}`);
|
|
152
|
+
* }
|
|
153
|
+
* ```
|
|
154
|
+
*/
|
|
155
|
+
declare function getCollider(world: World, eid: Entity): ColliderData | undefined;
|
|
156
|
+
/**
|
|
157
|
+
* Checks if an entity has a Collider component.
|
|
158
|
+
*
|
|
159
|
+
* @param world - The ECS world
|
|
160
|
+
* @param eid - The entity ID
|
|
161
|
+
* @returns true if entity has Collider component
|
|
162
|
+
*/
|
|
163
|
+
declare function hasCollider(world: World, eid: Entity): boolean;
|
|
164
|
+
/**
|
|
165
|
+
* Removes the collider from an entity.
|
|
166
|
+
*
|
|
167
|
+
* @param world - The ECS world
|
|
168
|
+
* @param eid - The entity ID
|
|
169
|
+
* @returns The entity ID for chaining
|
|
170
|
+
*/
|
|
171
|
+
declare function removeCollider(world: World, eid: Entity): Entity;
|
|
172
|
+
/**
|
|
173
|
+
* Sets the collision layer for an entity.
|
|
174
|
+
*
|
|
175
|
+
* @param world - The ECS world
|
|
176
|
+
* @param eid - The entity ID
|
|
177
|
+
* @param layer - The collision layer bitmask
|
|
178
|
+
* @returns The entity ID for chaining
|
|
179
|
+
*
|
|
180
|
+
* @example
|
|
181
|
+
* ```typescript
|
|
182
|
+
* import { setCollisionLayer } from 'blecsd';
|
|
183
|
+
*
|
|
184
|
+
* // Put entity on layer 2
|
|
185
|
+
* setCollisionLayer(world, entity, 0b0010);
|
|
186
|
+
* ```
|
|
187
|
+
*/
|
|
188
|
+
declare function setCollisionLayer(world: World, eid: Entity, layer: number): Entity;
|
|
189
|
+
/**
|
|
190
|
+
* Sets the collision mask for an entity.
|
|
191
|
+
*
|
|
192
|
+
* @param world - The ECS world
|
|
193
|
+
* @param eid - The entity ID
|
|
194
|
+
* @param mask - The collision mask bitmask
|
|
195
|
+
* @returns The entity ID for chaining
|
|
196
|
+
*
|
|
197
|
+
* @example
|
|
198
|
+
* ```typescript
|
|
199
|
+
* import { setCollisionMask } from 'blecsd';
|
|
200
|
+
*
|
|
201
|
+
* // Only collide with layers 1 and 3
|
|
202
|
+
* setCollisionMask(world, entity, 0b0101);
|
|
203
|
+
* ```
|
|
204
|
+
*/
|
|
205
|
+
declare function setCollisionMask(world: World, eid: Entity, mask: number): Entity;
|
|
206
|
+
/**
|
|
207
|
+
* Sets whether the collider is a trigger.
|
|
208
|
+
*
|
|
209
|
+
* @param world - The ECS world
|
|
210
|
+
* @param eid - The entity ID
|
|
211
|
+
* @param isTrigger - Whether collider is trigger-only
|
|
212
|
+
* @returns The entity ID for chaining
|
|
213
|
+
*/
|
|
214
|
+
declare function setTrigger(world: World, eid: Entity, isTrigger: boolean): Entity;
|
|
215
|
+
/**
|
|
216
|
+
* Checks if a collider is a trigger.
|
|
217
|
+
*
|
|
218
|
+
* @param world - The ECS world
|
|
219
|
+
* @param eid - The entity ID
|
|
220
|
+
* @returns true if collider is a trigger
|
|
221
|
+
*/
|
|
222
|
+
declare function isTrigger(world: World, eid: Entity): boolean;
|
|
223
|
+
/**
|
|
224
|
+
* Checks if two layers can collide based on layer/mask.
|
|
225
|
+
*
|
|
226
|
+
* @param layerA - Layer of entity A
|
|
227
|
+
* @param maskA - Mask of entity A
|
|
228
|
+
* @param layerB - Layer of entity B
|
|
229
|
+
* @param maskB - Mask of entity B
|
|
230
|
+
* @returns true if the entities can collide
|
|
231
|
+
*
|
|
232
|
+
* @example
|
|
233
|
+
* ```typescript
|
|
234
|
+
* import { canLayersCollide } from 'blecsd';
|
|
235
|
+
*
|
|
236
|
+
* // Check if player (layer 1, mask 6) can collide with enemy (layer 2, mask 1)
|
|
237
|
+
* const canCollide = canLayersCollide(1, 6, 2, 1); // true
|
|
238
|
+
* ```
|
|
239
|
+
*/
|
|
240
|
+
declare function canLayersCollide(layerA: number, maskA: number, layerB: number, maskB: number): boolean;
|
|
241
|
+
/**
|
|
242
|
+
* Axis-aligned bounding box.
|
|
243
|
+
*/
|
|
244
|
+
interface AABB {
|
|
245
|
+
readonly minX: number;
|
|
246
|
+
readonly minY: number;
|
|
247
|
+
readonly maxX: number;
|
|
248
|
+
readonly maxY: number;
|
|
249
|
+
}
|
|
250
|
+
/**
|
|
251
|
+
* Gets the AABB for an entity's collider at a given position.
|
|
252
|
+
*
|
|
253
|
+
* @param eid - The entity ID
|
|
254
|
+
* @param posX - Entity X position
|
|
255
|
+
* @param posY - Entity Y position
|
|
256
|
+
* @returns The AABB bounds
|
|
257
|
+
*
|
|
258
|
+
* @example
|
|
259
|
+
* ```typescript
|
|
260
|
+
* import { getColliderAABB, Position } from 'blecsd';
|
|
261
|
+
*
|
|
262
|
+
* const bounds = getColliderAABB(entity, Position.x[entity], Position.y[entity]);
|
|
263
|
+
* console.log(`Bounds: ${bounds.minX},${bounds.minY} to ${bounds.maxX},${bounds.maxY}`);
|
|
264
|
+
* ```
|
|
265
|
+
*/
|
|
266
|
+
declare function getColliderAABB(eid: Entity, posX: number, posY: number): AABB;
|
|
267
|
+
/**
|
|
268
|
+
* Tests if two AABBs overlap.
|
|
269
|
+
*
|
|
270
|
+
* @param a - First AABB
|
|
271
|
+
* @param b - Second AABB
|
|
272
|
+
* @returns true if the AABBs overlap
|
|
273
|
+
*
|
|
274
|
+
* @example
|
|
275
|
+
* ```typescript
|
|
276
|
+
* import { testAABBOverlap } from 'blecsd';
|
|
277
|
+
*
|
|
278
|
+
* const overlaps = testAABBOverlap(boundsA, boundsB);
|
|
279
|
+
* ```
|
|
280
|
+
*/
|
|
281
|
+
declare function testAABBOverlap(a: AABB, b: AABB): boolean;
|
|
282
|
+
/**
|
|
283
|
+
* Tests if two circles overlap.
|
|
284
|
+
*
|
|
285
|
+
* @param x1 - Center X of first circle
|
|
286
|
+
* @param y1 - Center Y of first circle
|
|
287
|
+
* @param r1 - Radius of first circle
|
|
288
|
+
* @param x2 - Center X of second circle
|
|
289
|
+
* @param y2 - Center Y of second circle
|
|
290
|
+
* @param r2 - Radius of second circle
|
|
291
|
+
* @returns true if the circles overlap
|
|
292
|
+
*/
|
|
293
|
+
declare function testCircleOverlap(x1: number, y1: number, r1: number, x2: number, y2: number, r2: number): boolean;
|
|
294
|
+
/**
|
|
295
|
+
* Tests if a circle overlaps with an AABB.
|
|
296
|
+
*
|
|
297
|
+
* @param cx - Circle center X
|
|
298
|
+
* @param cy - Circle center Y
|
|
299
|
+
* @param radius - Circle radius
|
|
300
|
+
* @param box - The AABB
|
|
301
|
+
* @returns true if they overlap
|
|
302
|
+
*/
|
|
303
|
+
declare function testCircleAABBOverlap(cx: number, cy: number, radius: number, box: AABB): boolean;
|
|
304
|
+
/**
|
|
305
|
+
* Tests if two entities' colliders overlap.
|
|
306
|
+
* Handles all combinations of BOX and CIRCLE colliders.
|
|
307
|
+
*
|
|
308
|
+
* @param eidA - First entity
|
|
309
|
+
* @param posAX - First entity X position
|
|
310
|
+
* @param posAY - First entity Y position
|
|
311
|
+
* @param eidB - Second entity
|
|
312
|
+
* @param posBX - Second entity X position
|
|
313
|
+
* @param posBY - Second entity Y position
|
|
314
|
+
* @returns true if the colliders overlap
|
|
315
|
+
*
|
|
316
|
+
* @example
|
|
317
|
+
* ```typescript
|
|
318
|
+
* import { testCollision, Position } from 'blecsd';
|
|
319
|
+
*
|
|
320
|
+
* const colliding = testCollision(
|
|
321
|
+
* entityA, Position.x[entityA], Position.y[entityA],
|
|
322
|
+
* entityB, Position.x[entityB], Position.y[entityB]
|
|
323
|
+
* );
|
|
324
|
+
* ```
|
|
325
|
+
*/
|
|
326
|
+
declare function testCollision(eidA: Entity, posAX: number, posAY: number, eidB: Entity, posBX: number, posBY: number): boolean;
|
|
327
|
+
/**
|
|
328
|
+
* Represents a collision between two entities.
|
|
329
|
+
*/
|
|
330
|
+
interface CollisionPair {
|
|
331
|
+
readonly entityA: Entity;
|
|
332
|
+
readonly entityB: Entity;
|
|
333
|
+
readonly isTrigger: boolean;
|
|
334
|
+
}
|
|
335
|
+
/**
|
|
336
|
+
* Creates a normalized collision pair (lower entity ID first).
|
|
337
|
+
* This ensures consistent ordering for collision tracking.
|
|
338
|
+
*
|
|
339
|
+
* @param eidA - First entity
|
|
340
|
+
* @param eidB - Second entity
|
|
341
|
+
* @param isTrigger - Whether this is a trigger collision
|
|
342
|
+
* @returns Normalized collision pair
|
|
343
|
+
*/
|
|
344
|
+
declare function createCollisionPair(eidA: Entity, eidB: Entity, isTrigger: boolean): CollisionPair;
|
|
345
|
+
/**
|
|
346
|
+
* Creates a unique key for a collision pair.
|
|
347
|
+
*
|
|
348
|
+
* @param pair - The collision pair
|
|
349
|
+
* @returns A unique string key
|
|
350
|
+
*/
|
|
351
|
+
declare function collisionPairKey(pair: CollisionPair): string;
|
|
352
|
+
|
|
353
|
+
/**
|
|
354
|
+
* Particle and ParticleEmitter components for visual effects.
|
|
355
|
+
*
|
|
356
|
+
* Provides SoA component stores for particles and emitters,
|
|
357
|
+
* along with helper functions for color interpolation, aging,
|
|
358
|
+
* and emitter configuration.
|
|
359
|
+
*
|
|
360
|
+
* @module components/particle
|
|
361
|
+
*/
|
|
362
|
+
|
|
363
|
+
/**
|
|
364
|
+
* Particle component store using SoA (Structure of Arrays).
|
|
365
|
+
*
|
|
366
|
+
* - `lifetime`: Total lifetime in seconds
|
|
367
|
+
* - `age`: Current age in seconds
|
|
368
|
+
* - `fadeOut`: 1 if particle should fade as it ages, 0 otherwise
|
|
369
|
+
* - `char`: Character code point to render
|
|
370
|
+
* - `startFg`: Foreground color at birth (packed RGBA)
|
|
371
|
+
* - `endFg`: Foreground color at death (packed RGBA)
|
|
372
|
+
* - `emitter`: Entity ID of the emitter that spawned this particle
|
|
373
|
+
*
|
|
374
|
+
* @example
|
|
375
|
+
* ```typescript
|
|
376
|
+
* import { Particle, setParticle, getParticle, isParticleDead } from 'blecsd';
|
|
377
|
+
*
|
|
378
|
+
* setParticle(world, entity, {
|
|
379
|
+
* lifetime: 2,
|
|
380
|
+
* char: '*'.codePointAt(0)!,
|
|
381
|
+
* startFg: 0xffff0000,
|
|
382
|
+
* endFg: 0xff880000,
|
|
383
|
+
* fadeOut: true,
|
|
384
|
+
* });
|
|
385
|
+
* ```
|
|
386
|
+
*/
|
|
387
|
+
declare const Particle: {
|
|
388
|
+
/** Total lifetime in seconds */
|
|
389
|
+
lifetime: Float32Array<ArrayBuffer>;
|
|
390
|
+
/** Current age in seconds */
|
|
391
|
+
age: Float32Array<ArrayBuffer>;
|
|
392
|
+
/** 1 if particle fades out, 0 otherwise */
|
|
393
|
+
fadeOut: Uint8Array<ArrayBuffer>;
|
|
394
|
+
/** Character code point to render */
|
|
395
|
+
char: Uint32Array<ArrayBuffer>;
|
|
396
|
+
/** Foreground color at birth (packed RGBA) */
|
|
397
|
+
startFg: Uint32Array<ArrayBuffer>;
|
|
398
|
+
/** Foreground color at death (packed RGBA) */
|
|
399
|
+
endFg: Uint32Array<ArrayBuffer>;
|
|
400
|
+
/** Entity ID of the emitter that spawned this particle (0 = none) */
|
|
401
|
+
emitter: Uint32Array<ArrayBuffer>;
|
|
402
|
+
};
|
|
403
|
+
/**
|
|
404
|
+
* ParticleEmitter component store using SoA (Structure of Arrays).
|
|
405
|
+
*
|
|
406
|
+
* - `rate`: Particles per second (continuous emission)
|
|
407
|
+
* - `burstCount`: Number of particles to emit in a burst
|
|
408
|
+
* - `lifetime`: Default lifetime for spawned particles
|
|
409
|
+
* - `spread`: Emission spread angle in radians (0 = forward, PI = half-circle, 2*PI = full circle)
|
|
410
|
+
* - `speed`: Initial speed of spawned particles (cells/sec)
|
|
411
|
+
* - `gravity`: Downward acceleration (cells/sec^2)
|
|
412
|
+
* - `angle`: Base emission angle in radians (0 = right)
|
|
413
|
+
* - `active`: 1 if emitter is actively emitting, 0 if paused
|
|
414
|
+
* - `accumulator`: Internal accumulator for rate-based emission
|
|
415
|
+
*
|
|
416
|
+
* @example
|
|
417
|
+
* ```typescript
|
|
418
|
+
* import { ParticleEmitter, setEmitter, burstParticles } from 'blecsd';
|
|
419
|
+
*
|
|
420
|
+
* setEmitter(world, entity, {
|
|
421
|
+
* rate: 10,
|
|
422
|
+
* lifetime: 1.5,
|
|
423
|
+
* speed: 5,
|
|
424
|
+
* spread: Math.PI / 4,
|
|
425
|
+
* gravity: 2,
|
|
426
|
+
* });
|
|
427
|
+
*
|
|
428
|
+
* burstParticles(world, entity, 20);
|
|
429
|
+
* ```
|
|
430
|
+
*/
|
|
431
|
+
declare const ParticleEmitter: {
|
|
432
|
+
/** Particles per second */
|
|
433
|
+
rate: Float32Array<ArrayBuffer>;
|
|
434
|
+
/** Burst count */
|
|
435
|
+
burstCount: Uint16Array<ArrayBuffer>;
|
|
436
|
+
/** Default particle lifetime in seconds */
|
|
437
|
+
lifetime: Float32Array<ArrayBuffer>;
|
|
438
|
+
/** Emission spread angle in radians */
|
|
439
|
+
spread: Float32Array<ArrayBuffer>;
|
|
440
|
+
/** Initial speed in cells per second */
|
|
441
|
+
speed: Float32Array<ArrayBuffer>;
|
|
442
|
+
/** Downward gravity in cells/sec^2 */
|
|
443
|
+
gravity: Float32Array<ArrayBuffer>;
|
|
444
|
+
/** Base emission angle in radians (0 = right) */
|
|
445
|
+
angle: Float32Array<ArrayBuffer>;
|
|
446
|
+
/** 1 if active, 0 if paused */
|
|
447
|
+
active: Uint8Array<ArrayBuffer>;
|
|
448
|
+
/** Internal accumulator for rate-based emission */
|
|
449
|
+
accumulator: Float32Array<ArrayBuffer>;
|
|
450
|
+
};
|
|
451
|
+
/**
|
|
452
|
+
* Particle data returned by getParticle.
|
|
453
|
+
*/
|
|
454
|
+
interface ParticleData {
|
|
455
|
+
readonly lifetime: number;
|
|
456
|
+
readonly age: number;
|
|
457
|
+
readonly fadeOut: boolean;
|
|
458
|
+
readonly char: number;
|
|
459
|
+
readonly startFg: number;
|
|
460
|
+
readonly endFg: number;
|
|
461
|
+
readonly emitter: number;
|
|
462
|
+
}
|
|
463
|
+
/**
|
|
464
|
+
* Options for setting a particle.
|
|
465
|
+
*/
|
|
466
|
+
interface ParticleOptions {
|
|
467
|
+
/** Total lifetime in seconds */
|
|
468
|
+
lifetime: number;
|
|
469
|
+
/** Character code point to render */
|
|
470
|
+
char: number;
|
|
471
|
+
/** Foreground color at birth (packed RGBA) */
|
|
472
|
+
startFg: number;
|
|
473
|
+
/** Foreground color at death (packed RGBA, default: same as startFg) */
|
|
474
|
+
endFg?: number;
|
|
475
|
+
/** Whether particle fades out (default: false) */
|
|
476
|
+
fadeOut?: boolean;
|
|
477
|
+
/** Entity ID of the emitter (default: 0) */
|
|
478
|
+
emitter?: number;
|
|
479
|
+
}
|
|
480
|
+
/**
|
|
481
|
+
* Emitter data returned by getEmitter.
|
|
482
|
+
*/
|
|
483
|
+
interface EmitterData {
|
|
484
|
+
readonly rate: number;
|
|
485
|
+
readonly burstCount: number;
|
|
486
|
+
readonly lifetime: number;
|
|
487
|
+
readonly spread: number;
|
|
488
|
+
readonly speed: number;
|
|
489
|
+
readonly gravity: number;
|
|
490
|
+
readonly angle: number;
|
|
491
|
+
readonly active: boolean;
|
|
492
|
+
}
|
|
493
|
+
/**
|
|
494
|
+
* Options for configuring an emitter.
|
|
495
|
+
*/
|
|
496
|
+
interface EmitterOptions {
|
|
497
|
+
/** Particles per second (default: 0, continuous off) */
|
|
498
|
+
rate?: number;
|
|
499
|
+
/** Burst count (default: 0) */
|
|
500
|
+
burstCount?: number;
|
|
501
|
+
/** Default particle lifetime in seconds */
|
|
502
|
+
lifetime: number;
|
|
503
|
+
/** Emission spread angle in radians (default: 2*PI, full circle) */
|
|
504
|
+
spread?: number;
|
|
505
|
+
/** Initial particle speed in cells/sec (default: 3) */
|
|
506
|
+
speed?: number;
|
|
507
|
+
/** Gravity in cells/sec^2 (default: 0) */
|
|
508
|
+
gravity?: number;
|
|
509
|
+
/** Base emission angle in radians (default: 0, right) */
|
|
510
|
+
angle?: number;
|
|
511
|
+
/** Whether emitter is active (default: true) */
|
|
512
|
+
active?: boolean;
|
|
513
|
+
}
|
|
514
|
+
/**
|
|
515
|
+
* Options for configuring emitter characters and colors.
|
|
516
|
+
*/
|
|
517
|
+
interface EmitterAppearance {
|
|
518
|
+
/** Characters to randomly pick from for spawned particles */
|
|
519
|
+
chars: ReadonlyArray<number>;
|
|
520
|
+
/** Start foreground color (packed RGBA) */
|
|
521
|
+
startFg: number;
|
|
522
|
+
/** End foreground color (packed RGBA, default: same as startFg) */
|
|
523
|
+
endFg?: number;
|
|
524
|
+
/** Whether particles should fade out (default: true) */
|
|
525
|
+
fadeOut?: boolean;
|
|
526
|
+
}
|
|
527
|
+
/**
|
|
528
|
+
* Sets particle data on an entity.
|
|
529
|
+
*
|
|
530
|
+
* @param world - The ECS world
|
|
531
|
+
* @param eid - The entity ID
|
|
532
|
+
* @param options - Particle configuration
|
|
533
|
+
* @returns The entity ID for chaining
|
|
534
|
+
*
|
|
535
|
+
* @example
|
|
536
|
+
* ```typescript
|
|
537
|
+
* import { setParticle, packColor } from 'blecsd';
|
|
538
|
+
*
|
|
539
|
+
* setParticle(world, entity, {
|
|
540
|
+
* lifetime: 1.5,
|
|
541
|
+
* char: '*'.codePointAt(0)!,
|
|
542
|
+
* startFg: packColor(255, 255, 0),
|
|
543
|
+
* endFg: packColor(255, 0, 0),
|
|
544
|
+
* fadeOut: true,
|
|
545
|
+
* });
|
|
546
|
+
* ```
|
|
547
|
+
*/
|
|
548
|
+
declare function setParticle(world: World, eid: Entity, options: ParticleOptions): Entity;
|
|
549
|
+
/**
|
|
550
|
+
* Gets particle data for an entity.
|
|
551
|
+
*
|
|
552
|
+
* @param world - The ECS world
|
|
553
|
+
* @param eid - The entity ID
|
|
554
|
+
* @returns ParticleData or undefined if not a particle
|
|
555
|
+
*/
|
|
556
|
+
declare function getParticle(world: World, eid: Entity): ParticleData | undefined;
|
|
557
|
+
/**
|
|
558
|
+
* Checks if an entity has a Particle component.
|
|
559
|
+
*/
|
|
560
|
+
declare function hasParticle(world: World, eid: Entity): boolean;
|
|
561
|
+
/**
|
|
562
|
+
* Removes the Particle component from an entity.
|
|
563
|
+
*/
|
|
564
|
+
declare function removeParticle(world: World, eid: Entity): Entity;
|
|
565
|
+
/**
|
|
566
|
+
* Checks if a particle has exceeded its lifetime.
|
|
567
|
+
*/
|
|
568
|
+
declare function isParticleDead(world: World, eid: Entity): boolean;
|
|
569
|
+
/**
|
|
570
|
+
* Gets the normalized age of a particle (0-1).
|
|
571
|
+
*/
|
|
572
|
+
declare function getParticleProgress(world: World, eid: Entity): number;
|
|
573
|
+
/**
|
|
574
|
+
* Interpolates between two packed RGBA colors based on a 0-1 parameter.
|
|
575
|
+
*
|
|
576
|
+
* @param startColor - Start color (packed RGBA)
|
|
577
|
+
* @param endColor - End color (packed RGBA)
|
|
578
|
+
* @param t - Interpolation factor (0 = start, 1 = end)
|
|
579
|
+
* @returns Interpolated packed RGBA color
|
|
580
|
+
*
|
|
581
|
+
* @example
|
|
582
|
+
* ```typescript
|
|
583
|
+
* import { interpolateColor, packColor } from 'blecsd';
|
|
584
|
+
*
|
|
585
|
+
* const red = packColor(255, 0, 0);
|
|
586
|
+
* const blue = packColor(0, 0, 255);
|
|
587
|
+
* const purple = interpolateColor(red, blue, 0.5);
|
|
588
|
+
* ```
|
|
589
|
+
*/
|
|
590
|
+
declare function interpolateColor(startColor: number, endColor: number, t: number): number;
|
|
591
|
+
/**
|
|
592
|
+
* Gets the current interpolated color of a particle based on its age.
|
|
593
|
+
*/
|
|
594
|
+
declare function getParticleColor(world: World, eid: Entity): number;
|
|
595
|
+
/**
|
|
596
|
+
* Sets emitter data on an entity.
|
|
597
|
+
*
|
|
598
|
+
* @param world - The ECS world
|
|
599
|
+
* @param eid - The entity ID
|
|
600
|
+
* @param options - Emitter configuration
|
|
601
|
+
* @returns The entity ID for chaining
|
|
602
|
+
*
|
|
603
|
+
* @example
|
|
604
|
+
* ```typescript
|
|
605
|
+
* import { setEmitter } from 'blecsd';
|
|
606
|
+
*
|
|
607
|
+
* setEmitter(world, entity, {
|
|
608
|
+
* rate: 20,
|
|
609
|
+
* lifetime: 1,
|
|
610
|
+
* speed: 5,
|
|
611
|
+
* spread: Math.PI / 3,
|
|
612
|
+
* gravity: 9.8,
|
|
613
|
+
* });
|
|
614
|
+
* ```
|
|
615
|
+
*/
|
|
616
|
+
declare function setEmitter(world: World, eid: Entity, options: EmitterOptions): Entity;
|
|
617
|
+
/**
|
|
618
|
+
* Gets emitter data for an entity.
|
|
619
|
+
*/
|
|
620
|
+
declare function getEmitter(world: World, eid: Entity): EmitterData | undefined;
|
|
621
|
+
/**
|
|
622
|
+
* Checks if an entity has a ParticleEmitter component.
|
|
623
|
+
*/
|
|
624
|
+
declare function hasEmitter(world: World, eid: Entity): boolean;
|
|
625
|
+
/**
|
|
626
|
+
* Removes the ParticleEmitter component from an entity.
|
|
627
|
+
*/
|
|
628
|
+
declare function removeEmitter(world: World, eid: Entity): Entity;
|
|
629
|
+
/**
|
|
630
|
+
* Sets the visual appearance config for particles spawned by this emitter.
|
|
631
|
+
*
|
|
632
|
+
* @param eid - The emitter entity ID
|
|
633
|
+
* @param appearance - Appearance configuration
|
|
634
|
+
*/
|
|
635
|
+
declare function setEmitterAppearance(eid: Entity, appearance: EmitterAppearance): void;
|
|
636
|
+
/**
|
|
637
|
+
* Gets the appearance config for an emitter.
|
|
638
|
+
*/
|
|
639
|
+
declare function getEmitterAppearance(eid: Entity): EmitterAppearance | undefined;
|
|
640
|
+
/**
|
|
641
|
+
* Gets the set of particle entity IDs spawned by an emitter.
|
|
642
|
+
*/
|
|
643
|
+
declare function getEmitterParticles(eid: Entity): ReadonlySet<number>;
|
|
644
|
+
/**
|
|
645
|
+
* Tracks a particle as belonging to an emitter.
|
|
646
|
+
*/
|
|
647
|
+
declare function trackParticle(emitterId: Entity, particleId: Entity): void;
|
|
648
|
+
/**
|
|
649
|
+
* Untracks a particle from its emitter.
|
|
650
|
+
*/
|
|
651
|
+
declare function untrackParticle(emitterId: Entity, particleId: Entity): void;
|
|
652
|
+
/**
|
|
653
|
+
* Activates an emitter.
|
|
654
|
+
*/
|
|
655
|
+
declare function activateEmitter(world: World, eid: Entity): void;
|
|
656
|
+
/**
|
|
657
|
+
* Pauses an emitter.
|
|
658
|
+
*/
|
|
659
|
+
declare function pauseEmitter(world: World, eid: Entity): void;
|
|
660
|
+
/**
|
|
661
|
+
* Checks if an emitter is active.
|
|
662
|
+
*/
|
|
663
|
+
declare function isEmitterActive(world: World, eid: Entity): boolean;
|
|
664
|
+
/**
|
|
665
|
+
* Sets the emission rate (particles per second).
|
|
666
|
+
*/
|
|
667
|
+
declare function setEmitterRate(world: World, eid: Entity, rate: number): void;
|
|
668
|
+
/**
|
|
669
|
+
* Sets the emitter speed.
|
|
670
|
+
*/
|
|
671
|
+
declare function setEmitterSpeed(world: World, eid: Entity, speed: number): void;
|
|
672
|
+
/**
|
|
673
|
+
* Sets the emitter gravity.
|
|
674
|
+
*/
|
|
675
|
+
declare function setEmitterGravity(world: World, eid: Entity, gravity: number): void;
|
|
676
|
+
/**
|
|
677
|
+
* Resets all particle/emitter side stores. Useful for testing.
|
|
678
|
+
*/
|
|
679
|
+
declare function resetParticleStore(): void;
|
|
680
|
+
|
|
681
|
+
/**
|
|
682
|
+
* TileMap component for 2D tile-based game maps.
|
|
683
|
+
*
|
|
684
|
+
* Provides a tile map data structure with multiple layers,
|
|
685
|
+
* tileset management, and per-entity SoA storage for tile map
|
|
686
|
+
* metadata. Tile data is stored in an external side store
|
|
687
|
+
* (Map-based) for variable-sized arrays.
|
|
688
|
+
*
|
|
689
|
+
* @module components/tilemap
|
|
690
|
+
*/
|
|
691
|
+
|
|
692
|
+
/** Empty tile index (no tile rendered) */
|
|
693
|
+
declare const EMPTY_TILE = 0;
|
|
694
|
+
/**
|
|
695
|
+
* A single tile definition in a tileset.
|
|
696
|
+
*
|
|
697
|
+
* @example
|
|
698
|
+
* ```typescript
|
|
699
|
+
* import type { TileDefinition } from 'blecsd';
|
|
700
|
+
*
|
|
701
|
+
* const grass: TileDefinition = { char: '.', fg: 0x00ff00ff, bg: 0x003300ff };
|
|
702
|
+
* const wall: TileDefinition = { char: '#', fg: 0xaaaaaaff, bg: 0x444444ff };
|
|
703
|
+
* ```
|
|
704
|
+
*/
|
|
705
|
+
interface TileDefinition {
|
|
706
|
+
/** Character to render for this tile */
|
|
707
|
+
readonly char: string;
|
|
708
|
+
/** Foreground color (packed RGBA) */
|
|
709
|
+
readonly fg: number;
|
|
710
|
+
/** Background color (packed RGBA) */
|
|
711
|
+
readonly bg: number;
|
|
712
|
+
}
|
|
713
|
+
/**
|
|
714
|
+
* Tileset data stored in the tileset store.
|
|
715
|
+
*/
|
|
716
|
+
interface TilesetData {
|
|
717
|
+
/** Unique tileset ID */
|
|
718
|
+
readonly id: number;
|
|
719
|
+
/** Human-readable name */
|
|
720
|
+
readonly name: string;
|
|
721
|
+
/** Array of tile definitions (index 0 = empty/transparent) */
|
|
722
|
+
readonly tiles: readonly TileDefinition[];
|
|
723
|
+
}
|
|
724
|
+
/**
|
|
725
|
+
* Options for registering a new tileset.
|
|
726
|
+
*/
|
|
727
|
+
interface TilesetOptions {
|
|
728
|
+
/** Human-readable name for the tileset */
|
|
729
|
+
name: string;
|
|
730
|
+
/** Array of tile definitions. Index 0 is conventionally empty/transparent. */
|
|
731
|
+
tiles: TileDefinition[];
|
|
732
|
+
}
|
|
733
|
+
/**
|
|
734
|
+
* Storage for tileset data.
|
|
735
|
+
*
|
|
736
|
+
* @example
|
|
737
|
+
* ```typescript
|
|
738
|
+
* import { registerTileset, getTileset } from 'blecsd';
|
|
739
|
+
*
|
|
740
|
+
* const tilesetId = registerTileset({
|
|
741
|
+
* name: 'dungeon',
|
|
742
|
+
* tiles: [
|
|
743
|
+
* { char: ' ', fg: 0, bg: 0 }, // 0: empty
|
|
744
|
+
* { char: '.', fg: 0x888888ff, bg: 0 }, // 1: floor
|
|
745
|
+
* { char: '#', fg: 0xaaaaaaff, bg: 0x444444ff }, // 2: wall
|
|
746
|
+
* ],
|
|
747
|
+
* });
|
|
748
|
+
* ```
|
|
749
|
+
*/
|
|
750
|
+
declare const tilesetStore: {
|
|
751
|
+
/** Map of tileset ID to data */
|
|
752
|
+
tilesets: Map<number, TilesetData>;
|
|
753
|
+
/** Map of tileset name to ID */
|
|
754
|
+
nameToId: Map<string, number>;
|
|
755
|
+
};
|
|
756
|
+
/**
|
|
757
|
+
* Resets the tileset store to initial state. Useful for testing.
|
|
758
|
+
*
|
|
759
|
+
* @example
|
|
760
|
+
* ```typescript
|
|
761
|
+
* import { resetTilesetStore } from 'blecsd';
|
|
762
|
+
*
|
|
763
|
+
* resetTilesetStore();
|
|
764
|
+
* ```
|
|
765
|
+
*/
|
|
766
|
+
declare function resetTilesetStore(): void;
|
|
767
|
+
/**
|
|
768
|
+
* Registers a new tileset and returns its ID.
|
|
769
|
+
*
|
|
770
|
+
* @param options - Tileset configuration
|
|
771
|
+
* @returns The tileset ID
|
|
772
|
+
*
|
|
773
|
+
* @example
|
|
774
|
+
* ```typescript
|
|
775
|
+
* import { registerTileset } from 'blecsd';
|
|
776
|
+
*
|
|
777
|
+
* const tilesetId = registerTileset({
|
|
778
|
+
* name: 'overworld',
|
|
779
|
+
* tiles: [
|
|
780
|
+
* { char: ' ', fg: 0, bg: 0 },
|
|
781
|
+
* { char: '.', fg: 0x00ff00ff, bg: 0x003300ff },
|
|
782
|
+
* { char: '~', fg: 0x0000ffff, bg: 0x000066ff },
|
|
783
|
+
* ],
|
|
784
|
+
* });
|
|
785
|
+
* ```
|
|
786
|
+
*/
|
|
787
|
+
declare function registerTileset(options: TilesetOptions): number;
|
|
788
|
+
/**
|
|
789
|
+
* Gets a tileset by ID.
|
|
790
|
+
*
|
|
791
|
+
* @param id - The tileset ID
|
|
792
|
+
* @returns The tileset data or undefined
|
|
793
|
+
*
|
|
794
|
+
* @example
|
|
795
|
+
* ```typescript
|
|
796
|
+
* import { getTileset } from 'blecsd';
|
|
797
|
+
*
|
|
798
|
+
* const tileset = getTileset(tilesetId);
|
|
799
|
+
* if (tileset) {
|
|
800
|
+
* console.log(`Tileset: ${tileset.name}, ${tileset.tiles.length} tiles`);
|
|
801
|
+
* }
|
|
802
|
+
* ```
|
|
803
|
+
*/
|
|
804
|
+
declare function getTileset(id: number): TilesetData | undefined;
|
|
805
|
+
/**
|
|
806
|
+
* Gets a tileset by name.
|
|
807
|
+
*
|
|
808
|
+
* @param name - The tileset name
|
|
809
|
+
* @returns The tileset data or undefined
|
|
810
|
+
*
|
|
811
|
+
* @example
|
|
812
|
+
* ```typescript
|
|
813
|
+
* import { getTilesetByName } from 'blecsd';
|
|
814
|
+
*
|
|
815
|
+
* const tileset = getTilesetByName('dungeon');
|
|
816
|
+
* ```
|
|
817
|
+
*/
|
|
818
|
+
declare function getTilesetByName(name: string): TilesetData | undefined;
|
|
819
|
+
/**
|
|
820
|
+
* Unregisters a tileset.
|
|
821
|
+
*
|
|
822
|
+
* @param id - The tileset ID to remove
|
|
823
|
+
* @returns true if removed, false if not found
|
|
824
|
+
*/
|
|
825
|
+
declare function unregisterTileset(id: number): boolean;
|
|
826
|
+
/**
|
|
827
|
+
* A single layer of tile data.
|
|
828
|
+
*/
|
|
829
|
+
interface TileMapLayer {
|
|
830
|
+
/** Flat array of tile indices (width * height), row-major order */
|
|
831
|
+
readonly tiles: Uint16Array;
|
|
832
|
+
/** Whether this layer is visible */
|
|
833
|
+
visible: boolean;
|
|
834
|
+
}
|
|
835
|
+
/**
|
|
836
|
+
* Tile map data stored in the side store.
|
|
837
|
+
*/
|
|
838
|
+
interface TileMapData {
|
|
839
|
+
/** Map width in tiles */
|
|
840
|
+
readonly width: number;
|
|
841
|
+
/** Map height in tiles */
|
|
842
|
+
readonly height: number;
|
|
843
|
+
/** Array of tile layers (bottom to top) */
|
|
844
|
+
readonly layers: TileMapLayer[];
|
|
845
|
+
}
|
|
846
|
+
/**
|
|
847
|
+
* Storage for tile map layer data.
|
|
848
|
+
* Maps data IDs to their tile data.
|
|
849
|
+
*/
|
|
850
|
+
declare const tileMapStore: {
|
|
851
|
+
/** Map of data ID to tile map data */
|
|
852
|
+
data: Map<number, TileMapData>;
|
|
853
|
+
};
|
|
854
|
+
/**
|
|
855
|
+
* Resets the tile map store to initial state. Useful for testing.
|
|
856
|
+
*
|
|
857
|
+
* @example
|
|
858
|
+
* ```typescript
|
|
859
|
+
* import { resetTileMapStore } from 'blecsd';
|
|
860
|
+
*
|
|
861
|
+
* resetTileMapStore();
|
|
862
|
+
* ```
|
|
863
|
+
*/
|
|
864
|
+
declare function resetTileMapStore(): void;
|
|
865
|
+
/**
|
|
866
|
+
* Creates tile map data with the specified dimensions and number of layers.
|
|
867
|
+
* Returns the data ID for referencing in the TileMap component.
|
|
868
|
+
*
|
|
869
|
+
* @param width - Map width in tiles
|
|
870
|
+
* @param height - Map height in tiles
|
|
871
|
+
* @param layerCount - Number of layers (default: 1)
|
|
872
|
+
* @returns The data ID
|
|
873
|
+
*
|
|
874
|
+
* @example
|
|
875
|
+
* ```typescript
|
|
876
|
+
* import { createTileData } from 'blecsd';
|
|
877
|
+
*
|
|
878
|
+
* const dataId = createTileData(32, 32, 2); // 32x32 map, 2 layers
|
|
879
|
+
* ```
|
|
880
|
+
*/
|
|
881
|
+
declare function createTileData(width: number, height: number, layerCount?: number): number;
|
|
882
|
+
/**
|
|
883
|
+
* Gets tile map data by ID.
|
|
884
|
+
*
|
|
885
|
+
* @param dataId - The data ID
|
|
886
|
+
* @returns The tile map data or undefined
|
|
887
|
+
*/
|
|
888
|
+
declare function getTileData(dataId: number): TileMapData | undefined;
|
|
889
|
+
/**
|
|
890
|
+
* Removes tile map data.
|
|
891
|
+
*
|
|
892
|
+
* @param dataId - The data ID to remove
|
|
893
|
+
* @returns true if removed, false if not found
|
|
894
|
+
*/
|
|
895
|
+
declare function removeTileData(dataId: number): boolean;
|
|
896
|
+
/**
|
|
897
|
+
* Sets a tile at a specific position in a layer.
|
|
898
|
+
*
|
|
899
|
+
* @param dataId - The tile map data ID
|
|
900
|
+
* @param layerIndex - The layer index (0-based)
|
|
901
|
+
* @param x - X coordinate in tiles
|
|
902
|
+
* @param y - Y coordinate in tiles
|
|
903
|
+
* @param tileIndex - The tile index in the tileset
|
|
904
|
+
* @returns true if set successfully, false if out of bounds or invalid
|
|
905
|
+
*
|
|
906
|
+
* @example
|
|
907
|
+
* ```typescript
|
|
908
|
+
* import { createTileData, setTile } from 'blecsd';
|
|
909
|
+
*
|
|
910
|
+
* const dataId = createTileData(10, 10);
|
|
911
|
+
* setTile(dataId, 0, 5, 3, 2); // Set tile at (5,3) on layer 0 to tile index 2
|
|
912
|
+
* ```
|
|
913
|
+
*/
|
|
914
|
+
declare function setTile(dataId: number, layerIndex: number, x: number, y: number, tileIndex: number): boolean;
|
|
915
|
+
/**
|
|
916
|
+
* Gets the tile index at a specific position in a layer.
|
|
917
|
+
*
|
|
918
|
+
* @param dataId - The tile map data ID
|
|
919
|
+
* @param layerIndex - The layer index (0-based)
|
|
920
|
+
* @param x - X coordinate in tiles
|
|
921
|
+
* @param y - Y coordinate in tiles
|
|
922
|
+
* @returns The tile index, or EMPTY_TILE if out of bounds
|
|
923
|
+
*
|
|
924
|
+
* @example
|
|
925
|
+
* ```typescript
|
|
926
|
+
* import { getTile, EMPTY_TILE } from 'blecsd';
|
|
927
|
+
*
|
|
928
|
+
* const tile = getTile(dataId, 0, 5, 3);
|
|
929
|
+
* if (tile !== EMPTY_TILE) {
|
|
930
|
+
* // Tile is not empty
|
|
931
|
+
* }
|
|
932
|
+
* ```
|
|
933
|
+
*/
|
|
934
|
+
declare function getTile(dataId: number, layerIndex: number, x: number, y: number): number;
|
|
935
|
+
/**
|
|
936
|
+
* Fills an entire layer with a tile index.
|
|
937
|
+
*
|
|
938
|
+
* @param dataId - The tile map data ID
|
|
939
|
+
* @param layerIndex - The layer index (0-based)
|
|
940
|
+
* @param tileIndex - The tile index to fill with
|
|
941
|
+
* @returns true if filled, false if invalid
|
|
942
|
+
*
|
|
943
|
+
* @example
|
|
944
|
+
* ```typescript
|
|
945
|
+
* import { createTileData, fillTiles } from 'blecsd';
|
|
946
|
+
*
|
|
947
|
+
* const dataId = createTileData(32, 32);
|
|
948
|
+
* fillTiles(dataId, 0, 1); // Fill entire layer with tile 1 (floor)
|
|
949
|
+
* ```
|
|
950
|
+
*/
|
|
951
|
+
declare function fillTiles(dataId: number, layerIndex: number, tileIndex: number): boolean;
|
|
952
|
+
/**
|
|
953
|
+
* Fills a rectangular region of a layer with a tile index.
|
|
954
|
+
*
|
|
955
|
+
* @param dataId - The tile map data ID
|
|
956
|
+
* @param layerIndex - The layer index
|
|
957
|
+
* @param x - Start X coordinate
|
|
958
|
+
* @param y - Start Y coordinate
|
|
959
|
+
* @param width - Rectangle width in tiles
|
|
960
|
+
* @param height - Rectangle height in tiles
|
|
961
|
+
* @param tileIndex - The tile index to fill with
|
|
962
|
+
* @returns true if filled, false if invalid
|
|
963
|
+
*
|
|
964
|
+
* @example
|
|
965
|
+
* ```typescript
|
|
966
|
+
* import { fillTileRect } from 'blecsd';
|
|
967
|
+
*
|
|
968
|
+
* // Create a 5x3 wall region at (2, 4)
|
|
969
|
+
* fillTileRect(dataId, 0, 2, 4, 5, 3, 2);
|
|
970
|
+
* ```
|
|
971
|
+
*/
|
|
972
|
+
declare function fillTileRect(dataId: number, layerIndex: number, x: number, y: number, width: number, height: number, tileIndex: number): boolean;
|
|
973
|
+
/**
|
|
974
|
+
* Gets the number of layers in a tile map.
|
|
975
|
+
*
|
|
976
|
+
* @param dataId - The tile map data ID
|
|
977
|
+
* @returns The number of layers, or 0 if invalid
|
|
978
|
+
*/
|
|
979
|
+
declare function getLayerCount(dataId: number): number;
|
|
980
|
+
/**
|
|
981
|
+
* Adds a new empty layer to the tile map.
|
|
982
|
+
*
|
|
983
|
+
* @param dataId - The tile map data ID
|
|
984
|
+
* @returns The new layer index, or -1 if invalid
|
|
985
|
+
*
|
|
986
|
+
* @example
|
|
987
|
+
* ```typescript
|
|
988
|
+
* import { addLayer } from 'blecsd';
|
|
989
|
+
*
|
|
990
|
+
* const layerIdx = addLayer(dataId);
|
|
991
|
+
* // Now you can set tiles on the new layer
|
|
992
|
+
* ```
|
|
993
|
+
*/
|
|
994
|
+
declare function addLayer(dataId: number): number;
|
|
995
|
+
/**
|
|
996
|
+
* Sets the visibility of a layer.
|
|
997
|
+
*
|
|
998
|
+
* @param dataId - The tile map data ID
|
|
999
|
+
* @param layerIndex - The layer index
|
|
1000
|
+
* @param visible - Whether the layer should be visible
|
|
1001
|
+
* @returns true if set, false if invalid
|
|
1002
|
+
*
|
|
1003
|
+
* @example
|
|
1004
|
+
* ```typescript
|
|
1005
|
+
* import { setLayerVisible } from 'blecsd';
|
|
1006
|
+
*
|
|
1007
|
+
* setLayerVisible(dataId, 1, false); // Hide layer 1
|
|
1008
|
+
* ```
|
|
1009
|
+
*/
|
|
1010
|
+
declare function setLayerVisible(dataId: number, layerIndex: number, visible: boolean): boolean;
|
|
1011
|
+
/**
|
|
1012
|
+
* Gets the visibility of a layer.
|
|
1013
|
+
*
|
|
1014
|
+
* @param dataId - The tile map data ID
|
|
1015
|
+
* @param layerIndex - The layer index
|
|
1016
|
+
* @returns true if visible, false if hidden or invalid
|
|
1017
|
+
*/
|
|
1018
|
+
declare function isLayerVisible(dataId: number, layerIndex: number): boolean;
|
|
1019
|
+
/**
|
|
1020
|
+
* TileMap component store using SoA (Structure of Arrays) for performance.
|
|
1021
|
+
*
|
|
1022
|
+
* - `width`: Map width in tiles
|
|
1023
|
+
* - `height`: Map height in tiles
|
|
1024
|
+
* - `tileWidth`: Tile width in terminal cells (for rendering)
|
|
1025
|
+
* - `tileHeight`: Tile height in terminal cells (for rendering)
|
|
1026
|
+
* - `dataId`: Reference to tile data in tileMapStore
|
|
1027
|
+
* - `tilesetId`: Reference to tileset in tilesetStore
|
|
1028
|
+
*
|
|
1029
|
+
* @example
|
|
1030
|
+
* ```typescript
|
|
1031
|
+
* import { TileMap, setTileMap, getTileMap } from 'blecsd';
|
|
1032
|
+
*
|
|
1033
|
+
* setTileMap(world, entity, {
|
|
1034
|
+
* width: 32,
|
|
1035
|
+
* height: 32,
|
|
1036
|
+
* tileWidth: 1,
|
|
1037
|
+
* tileHeight: 1,
|
|
1038
|
+
* tilesetId: myTilesetId,
|
|
1039
|
+
* });
|
|
1040
|
+
* ```
|
|
1041
|
+
*/
|
|
1042
|
+
declare const TileMap: {
|
|
1043
|
+
/** Map width in tiles */
|
|
1044
|
+
width: Uint16Array<ArrayBuffer>;
|
|
1045
|
+
/** Map height in tiles */
|
|
1046
|
+
height: Uint16Array<ArrayBuffer>;
|
|
1047
|
+
/** Tile width in terminal cells */
|
|
1048
|
+
tileWidth: Uint8Array<ArrayBuffer>;
|
|
1049
|
+
/** Tile height in terminal cells */
|
|
1050
|
+
tileHeight: Uint8Array<ArrayBuffer>;
|
|
1051
|
+
/** Reference to tile data in tileMapStore */
|
|
1052
|
+
dataId: Uint32Array<ArrayBuffer>;
|
|
1053
|
+
/** Reference to tileset in tilesetStore */
|
|
1054
|
+
tilesetId: Uint32Array<ArrayBuffer>;
|
|
1055
|
+
};
|
|
1056
|
+
/**
|
|
1057
|
+
* TileMap data returned by getTileMap.
|
|
1058
|
+
*/
|
|
1059
|
+
interface TileMapComponentData {
|
|
1060
|
+
readonly width: number;
|
|
1061
|
+
readonly height: number;
|
|
1062
|
+
readonly tileWidth: number;
|
|
1063
|
+
readonly tileHeight: number;
|
|
1064
|
+
readonly dataId: number;
|
|
1065
|
+
readonly tilesetId: number;
|
|
1066
|
+
}
|
|
1067
|
+
/**
|
|
1068
|
+
* Options for creating a tile map on an entity.
|
|
1069
|
+
*/
|
|
1070
|
+
interface TileMapOptions {
|
|
1071
|
+
/** Map width in tiles */
|
|
1072
|
+
width: number;
|
|
1073
|
+
/** Map height in tiles */
|
|
1074
|
+
height: number;
|
|
1075
|
+
/** Tile width in terminal cells (default: 1) */
|
|
1076
|
+
tileWidth?: number;
|
|
1077
|
+
/** Tile height in terminal cells (default: 1) */
|
|
1078
|
+
tileHeight?: number;
|
|
1079
|
+
/** Tileset ID to use for rendering */
|
|
1080
|
+
tilesetId: number;
|
|
1081
|
+
/** Number of layers (default: 1) */
|
|
1082
|
+
layerCount?: number;
|
|
1083
|
+
/** Existing data ID to use (skips creating new tile data) */
|
|
1084
|
+
dataId?: number;
|
|
1085
|
+
}
|
|
1086
|
+
/**
|
|
1087
|
+
* Sets a tile map on an entity. Creates tile data if not provided.
|
|
1088
|
+
* Adds the TileMap component if not already present.
|
|
1089
|
+
*
|
|
1090
|
+
* @param world - The ECS world
|
|
1091
|
+
* @param eid - The entity ID
|
|
1092
|
+
* @param options - Tile map options
|
|
1093
|
+
* @returns The entity ID for chaining
|
|
1094
|
+
*
|
|
1095
|
+
* @example
|
|
1096
|
+
* ```typescript
|
|
1097
|
+
* import { createWorld, addEntity } from '../core/ecs';
|
|
1098
|
+
* import { setTileMap, registerTileset } from 'blecsd';
|
|
1099
|
+
*
|
|
1100
|
+
* const world = createWorld();
|
|
1101
|
+
* const entity = addEntity(world);
|
|
1102
|
+
*
|
|
1103
|
+
* const tilesetId = registerTileset({
|
|
1104
|
+
* name: 'dungeon',
|
|
1105
|
+
* tiles: [
|
|
1106
|
+
* { char: ' ', fg: 0, bg: 0 },
|
|
1107
|
+
* { char: '.', fg: 0x888888ff, bg: 0 },
|
|
1108
|
+
* { char: '#', fg: 0xaaaaaaff, bg: 0x444444ff },
|
|
1109
|
+
* ],
|
|
1110
|
+
* });
|
|
1111
|
+
*
|
|
1112
|
+
* setTileMap(world, entity, {
|
|
1113
|
+
* width: 20,
|
|
1114
|
+
* height: 15,
|
|
1115
|
+
* tilesetId,
|
|
1116
|
+
* });
|
|
1117
|
+
* ```
|
|
1118
|
+
*/
|
|
1119
|
+
declare function setTileMap(world: World, eid: Entity, options: TileMapOptions): Entity;
|
|
1120
|
+
/**
|
|
1121
|
+
* Gets the tile map data of an entity.
|
|
1122
|
+
*
|
|
1123
|
+
* @param world - The ECS world
|
|
1124
|
+
* @param eid - The entity ID
|
|
1125
|
+
* @returns TileMap component data or undefined
|
|
1126
|
+
*
|
|
1127
|
+
* @example
|
|
1128
|
+
* ```typescript
|
|
1129
|
+
* import { getTileMap } from 'blecsd';
|
|
1130
|
+
*
|
|
1131
|
+
* const tileMap = getTileMap(world, entity);
|
|
1132
|
+
* if (tileMap) {
|
|
1133
|
+
* console.log(`Map: ${tileMap.width}x${tileMap.height}`);
|
|
1134
|
+
* }
|
|
1135
|
+
* ```
|
|
1136
|
+
*/
|
|
1137
|
+
declare function getTileMap(world: World, eid: Entity): TileMapComponentData | undefined;
|
|
1138
|
+
/**
|
|
1139
|
+
* Checks if an entity has a TileMap component.
|
|
1140
|
+
*
|
|
1141
|
+
* @param world - The ECS world
|
|
1142
|
+
* @param eid - The entity ID
|
|
1143
|
+
* @returns true if entity has TileMap component
|
|
1144
|
+
*/
|
|
1145
|
+
declare function hasTileMap(world: World, eid: Entity): boolean;
|
|
1146
|
+
/**
|
|
1147
|
+
* Removes the tile map from an entity.
|
|
1148
|
+
* Also removes the associated tile data from the store.
|
|
1149
|
+
*
|
|
1150
|
+
* @param world - The ECS world
|
|
1151
|
+
* @param eid - The entity ID
|
|
1152
|
+
* @param keepData - If true, does not remove tile data from store (default: false)
|
|
1153
|
+
* @returns The entity ID for chaining
|
|
1154
|
+
*
|
|
1155
|
+
* @example
|
|
1156
|
+
* ```typescript
|
|
1157
|
+
* import { removeTileMap } from 'blecsd';
|
|
1158
|
+
*
|
|
1159
|
+
* removeTileMap(world, entity);
|
|
1160
|
+
* ```
|
|
1161
|
+
*/
|
|
1162
|
+
declare function removeTileMap(world: World, eid: Entity, keepData?: boolean): Entity;
|
|
1163
|
+
/**
|
|
1164
|
+
* Gets the data ID for an entity's tile map.
|
|
1165
|
+
*
|
|
1166
|
+
* @param world - The ECS world
|
|
1167
|
+
* @param eid - The entity ID
|
|
1168
|
+
* @returns The data ID or 0 if not found
|
|
1169
|
+
*/
|
|
1170
|
+
declare function getTileMapDataId(world: World, eid: Entity): number;
|
|
1171
|
+
/**
|
|
1172
|
+
* A single rendered cell from the tile map.
|
|
1173
|
+
*/
|
|
1174
|
+
interface RenderedTileCell {
|
|
1175
|
+
/** Character to display */
|
|
1176
|
+
readonly char: string;
|
|
1177
|
+
/** Foreground color (packed RGBA) */
|
|
1178
|
+
readonly fg: number;
|
|
1179
|
+
/** Background color (packed RGBA) */
|
|
1180
|
+
readonly bg: number;
|
|
1181
|
+
}
|
|
1182
|
+
/**
|
|
1183
|
+
* Renders a rectangular viewport of the tile map to an array of cells.
|
|
1184
|
+
* Composites all visible layers from bottom to top.
|
|
1185
|
+
* Non-empty tiles on upper layers overwrite lower layers.
|
|
1186
|
+
*
|
|
1187
|
+
* @param dataId - The tile map data ID
|
|
1188
|
+
* @param tilesetId - The tileset ID to use for rendering
|
|
1189
|
+
* @param viewX - Viewport X offset in tiles
|
|
1190
|
+
* @param viewY - Viewport Y offset in tiles
|
|
1191
|
+
* @param viewWidth - Viewport width in tiles
|
|
1192
|
+
* @param viewHeight - Viewport height in tiles
|
|
1193
|
+
* @returns 2D array of rendered cells (row-major: [y][x])
|
|
1194
|
+
*
|
|
1195
|
+
* @example
|
|
1196
|
+
* ```typescript
|
|
1197
|
+
* import { renderTileMapArea } from 'blecsd';
|
|
1198
|
+
*
|
|
1199
|
+
* // Render a 10x8 viewport starting at tile (5, 3)
|
|
1200
|
+
* const cells = renderTileMapArea(dataId, tilesetId, 5, 3, 10, 8);
|
|
1201
|
+
* for (let y = 0; y < cells.length; y++) {
|
|
1202
|
+
* for (let x = 0; x < cells[y].length; x++) {
|
|
1203
|
+
* const cell = cells[y][x];
|
|
1204
|
+
* // Render cell.char with cell.fg and cell.bg
|
|
1205
|
+
* }
|
|
1206
|
+
* }
|
|
1207
|
+
* ```
|
|
1208
|
+
*/
|
|
1209
|
+
declare function renderTileMapArea(dataId: number, tilesetId: number, viewX: number, viewY: number, viewWidth: number, viewHeight: number): RenderedTileCell[][];
|
|
1210
|
+
|
|
1211
|
+
export { isEmitterActive as $, type AABB as A, getCollider as B, Collider as C, DEFAULT_LAYER as D, EMPTY_TILE as E, getColliderAABB as F, getEmitter as G, getEmitterAppearance as H, getEmitterParticles as I, getLayerCount as J, getParticle as K, getParticleColor as L, getParticleProgress as M, getTile as N, getTileData as O, Particle as P, getTileMap as Q, type RenderedTileCell as R, getTileMapDataId as S, type TileDefinition as T, getTileset as U, getTilesetByName as V, hasCollider as W, hasEmitter as X, hasParticle as Y, hasTileMap as Z, interpolateColor as _, type ColliderData as a, isLayerVisible as a0, isParticleDead as a1, isTrigger as a2, pauseEmitter as a3, registerTileset as a4, removeCollider as a5, removeEmitter as a6, removeParticle as a7, removeTileData as a8, removeTileMap as a9, renderTileMapArea as aa, resetParticleStore as ab, resetTileMapStore as ac, resetTilesetStore as ad, setCollider as ae, setCollisionLayer as af, setCollisionMask as ag, setEmitter as ah, setEmitterAppearance as ai, setEmitterGravity as aj, setEmitterRate as ak, setEmitterSpeed as al, setLayerVisible as am, setParticle as an, setTile as ao, setTileMap as ap, setTrigger as aq, testAABBOverlap as ar, testCircleAABBOverlap as as, testCircleOverlap as at, testCollision as au, tileMapStore as av, tilesetStore as aw, trackParticle as ax, unregisterTileset as ay, untrackParticle as az, type ColliderOptions as b, ColliderType as c, type CollisionPair as d, DEFAULT_MASK as e, type EmitterAppearance as f, type EmitterData as g, type EmitterOptions as h, type ParticleData as i, ParticleEmitter as j, type ParticleOptions as k, TileMap as l, type TileMapComponentData as m, type TileMapData as n, type TileMapLayer as o, type TileMapOptions as p, type TilesetData as q, type TilesetOptions as r, activateEmitter as s, addLayer as t, canLayersCollide as u, collisionPairKey as v, createCollisionPair as w, createTileData as x, fillTileRect as y, fillTiles as z };
|