@caperjs/plugin-crunch 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.
@@ -0,0 +1,718 @@
1
+ import { IApplication, IPlugin, isDev, Logger, Plugin, version } from '@caperjs/core';
2
+ import { Container as PIXIContainer, Rectangle, Ticker } from 'pixi.js';
3
+ import { Actor } from './Actor';
4
+ import { Group } from './Group';
5
+ import { AABBLike, CrunchPhysicsOptions } from './interfaces';
6
+ import { Sensor } from './Sensor';
7
+ import { Solid } from './Solid';
8
+ import { System } from './System';
9
+ import {
10
+ ActorCollision,
11
+ Collision,
12
+ CollisionLayer,
13
+ CollisionLayers,
14
+ PhysicsEntityConfig,
15
+ RegisteredCollisionLayer,
16
+ SensorOverlap,
17
+ } from './types';
18
+
19
+ /**
20
+ * Interface for the Crunch physics plugin, providing a simple yet powerful 2D physics system
21
+ * inspired by Towerfall's physics mechanics. Supports dynamic actors, static solids, and trigger sensors.
22
+ *
23
+ * @example
24
+ * ```typescript
25
+ * // Initialize the physics system
26
+ * const physics = this.app.getPlugin('crunch') as ICrunchPhysicsPlugin;
27
+ *
28
+ * const physics = await this.physics.initialize({
29
+ * gravity: 900,
30
+ * debug: true,
31
+ * gridSize: 32
32
+ * });
33
+ *
34
+ * // Create a player character
35
+ * const playerSprite = this.add.sprite({asset:Texture.WHITE, width: 32, height: 64});
36
+ *
37
+ * const player = physics.createActor({
38
+ * type: 'Player',
39
+ * position: [100, 100],
40
+ * size: [32, 64],
41
+ * view: playerSprite
42
+ * });
43
+ *
44
+ * // Create a platform
45
+ * const platformSprite = this.add.sprite({asset:Texture.WHITE, width: 800, height: 32, tint: 0x00FF00});
46
+ * const platform = physics.createSolid({
47
+ * type: 'Platform',
48
+ * position: [0, 500],
49
+ * size: [800, 32],
50
+ * view: platformSprite
51
+ * });
52
+ *
53
+ * // Create a coin pickup sensor
54
+ * const coinSprite = this.add.sprite({asset:Texture.WHITE, width: 32, height: 32, tint: 0x00FF00});
55
+ * const coin = physics.createSensor({
56
+ * type: 'Coin',
57
+ * position: [400, 400],
58
+ * size: [32, 32],
59
+ * view: coinSprite
60
+ * });
61
+ * ```
62
+ */
63
+ export interface ICrunchPhysicsPlugin extends IPlugin<CrunchPhysicsOptions> {
64
+ system: System;
65
+ container: PIXIContainer;
66
+ enabled: boolean;
67
+
68
+ /**
69
+ * Initializes the physics system with the specified options.
70
+ */
71
+ initialize(options?: Partial<CrunchPhysicsOptions>, app?: IApplication): Promise<void>;
72
+
73
+ /**
74
+ * Sets a custom collision resolver function that will be called when collisions occur.
75
+ *
76
+ * @param resolver - Function to handle collisions
77
+ *
78
+ * @example
79
+ * ```typescript
80
+ * physics.setCollisionResolver((collisions) => {
81
+ * collisions.forEach(collision => {
82
+ * if (collision.actor.type === 'Player' && collision.solid.type === 'Spike') {
83
+ * player.damage(10);
84
+ * }
85
+ * });
86
+ * });
87
+ * ```
88
+ */
89
+ setCollisionResolver(resolver: (collisions: Collision[]) => void): void;
90
+
91
+ /**
92
+ * Sets a custom resolver for actor-to-actor collisions.
93
+ *
94
+ * @param resolver - Function to handle actor-to-actor collisions
95
+ *
96
+ * @example
97
+ * ```typescript
98
+ * physics.setActorCollisionResolver((collisions) => {
99
+ * collisions.forEach(collision => {
100
+ * if (collision.actor1.type === 'Player' && collision.actor2.type === 'Enemy') {
101
+ * player.takeDamage(10);
102
+ * }
103
+ * });
104
+ * });
105
+ * ```
106
+ */
107
+ setActorCollisionResolver(resolver: (collisions: ActorCollision[]) => void): void;
108
+
109
+ /**
110
+ * Enables or disables actor-to-actor collision detection.
111
+ *
112
+ * @param enabled - Whether to enable actor-to-actor collisions
113
+ *
114
+ * @example
115
+ * ```typescript
116
+ * // Enable actor-to-actor collisions
117
+ * physics.setActorCollisionsEnabled(true);
118
+ *
119
+ * // Disable actor-to-actor collisions for performance
120
+ * physics.setActorCollisionsEnabled(false);
121
+ * ```
122
+ */
123
+ setActorCollisionsEnabled(enabled: boolean): void;
124
+
125
+ /**
126
+ * Creates a generic physics entity based on the provided configuration.
127
+ * Use this when you need to create an entity without knowing its specific type at compile time.
128
+ *
129
+ * @param config - Configuration for the physics entity
130
+ * @returns The created physics entity
131
+ *
132
+ * @example
133
+ * ```typescript
134
+ * const entityConfig = {
135
+ * type: 'Platform',
136
+ * position: [100, 100],
137
+ * size: [200, 32],
138
+ * view: sprite
139
+ * };
140
+ * const entity = physics.createEntity(entityConfig);
141
+ * ```
142
+ */
143
+ createEntity(config: PhysicsEntityConfig): Actor | Solid | Sensor | Group;
144
+
145
+ /**
146
+ * Adds an existing physics entity to the system.
147
+ * Useful when you want to manage entity creation yourself.
148
+ *
149
+ * @param entity - The physics entity to add
150
+ * @returns The added entity
151
+ *
152
+ * @example
153
+ * ```typescript
154
+ * class CustomActor extends Actor {
155
+ * constructor() {
156
+ * super({ type: 'Custom', position: [0, 0], size: [32, 32] });
157
+ * }
158
+ * }
159
+ *
160
+ * const customActor = new CustomActor();
161
+ * physics.addEntity(customActor);
162
+ * ```
163
+ */
164
+ addEntity(entity: Actor | Solid | Sensor | Group): Actor | Solid | Sensor | Group;
165
+
166
+ /**
167
+ * Creates a dynamic physics actor that can move and collide with other entities.
168
+ * Actors are typically used for players, enemies, or any moving game objects.
169
+ *
170
+ * @param config - Configuration for the actor
171
+ * @returns The created actor
172
+ *
173
+ * @example
174
+ * ```typescript
175
+ * // Create a player character
176
+ * const player = physics.createActor({
177
+ * type: 'Player',
178
+ * position: [100, 100],
179
+ * size: [32, 64],
180
+ * view: playerSprite
181
+ * });
182
+ *
183
+ * // Update player in game loop
184
+ * player.velocity.x = 300; // Move right
185
+ * player.velocity.y = -600; // Jump
186
+ * ```
187
+ */
188
+ createActor(config: PhysicsEntityConfig): Actor;
189
+
190
+ /**
191
+ * Creates a static solid object that other entities can collide with.
192
+ * Solids are typically used for platforms, walls, and other immovable objects.
193
+ *
194
+ * @param config - Configuration for the solid
195
+ * @returns The created solid
196
+ *
197
+ * @example
198
+ * ```typescript
199
+ * // Create a static platform
200
+ * const platform = physics.createSolid({
201
+ * type: 'Platform',
202
+ * position: [0, 500],
203
+ * size: [800, 32],
204
+ * view: platformSprite
205
+ * });
206
+ *
207
+ * // Create a moving platform
208
+ * const movingPlatform = physics.createSolid({
209
+ * type: 'Platform',
210
+ * position: [100, 300],
211
+ * size: [200, 32],
212
+ * view: platformSprite
213
+ * });
214
+ *
215
+ * // Update platform position
216
+ * gsap.to(movingPlatform, {
217
+ * x: 500,
218
+ * duration: 2,
219
+ * yoyo: true,
220
+ * repeat: -1
221
+ * });
222
+ * ```
223
+ */
224
+ createSolid(config: PhysicsEntityConfig): Solid;
225
+
226
+ /**
227
+ * Creates a sensor zone that can detect overlaps with other entities.
228
+ * Sensors are typically used for triggers, collectibles, or detection zones.
229
+ *
230
+ * @param config - Configuration for the sensor
231
+ * @returns The created sensor
232
+ *
233
+ * @example
234
+ * ```typescript
235
+ * // Create a coin pickup
236
+ * const coin = physics.createSensor({
237
+ * type: 'Coin',
238
+ * position: [400, 300],
239
+ * size: [32, 32],
240
+ * view: coinSprite
241
+ * });
242
+ *
243
+ * // Handle coin collection
244
+ * coin.onActorEnter = (actor) => {
245
+ * if (actor.type === 'Player') {
246
+ * increaseScore(10);
247
+ * physics.removeSensor(coin);
248
+ * }
249
+ * };
250
+ * ```
251
+ */
252
+ createSensor(config: PhysicsEntityConfig): Sensor;
253
+
254
+ createGroup(config: PhysicsEntityConfig): Group;
255
+
256
+ addActor(actor: Actor): Actor;
257
+
258
+ addSolid(solid: Solid): Solid;
259
+
260
+ addSensor(sensor: Sensor): Sensor;
261
+
262
+ addGroup(group: Group): Group;
263
+
264
+ /**
265
+ * Removes an actor from the physics system.
266
+ *
267
+ * @param actor - The actor to remove
268
+ *
269
+ * @example
270
+ * ```typescript
271
+ * // Remove player when they die
272
+ * function killPlayer(player: Actor) {
273
+ * playDeathAnimation();
274
+ * physics.removeActor(player);
275
+ * }
276
+ * ```
277
+ */
278
+ removeActor(actor: Actor): void;
279
+
280
+ /**
281
+ * Removes a solid from the physics system.
282
+ *
283
+ * @param solid - The solid to remove
284
+ *
285
+ * @example
286
+ * ```typescript
287
+ * // Remove a platform when it's destroyed
288
+ * function destroyPlatform(platform: Solid) {
289
+ * playBreakAnimation();
290
+ * physics.removeSolid(platform);
291
+ * }
292
+ * ```
293
+ */
294
+ removeSolid(solid: Solid): void;
295
+
296
+ /**
297
+ * Removes a sensor from the physics system.
298
+ *
299
+ * @param sensor - The sensor to remove
300
+ *
301
+ * @example
302
+ * ```typescript
303
+ * // Remove a coin when it's collected
304
+ * function collectCoin(coin: Sensor) {
305
+ * playCollectSound();
306
+ * physics.removeSensor(coin);
307
+ * }
308
+ * ```
309
+ */
310
+ removeSensor(sensor: Sensor): void;
311
+
312
+ /**
313
+ * Cleans up the physics system and removes all entities.
314
+ * Call this when transitioning between scenes or shutting down the game.
315
+ *
316
+ * @example
317
+ * ```typescript
318
+ * class GameScene extends Scene {
319
+ * destroy() {
320
+ * this.physics.destroy();
321
+ * super.destroy();
322
+ * }
323
+ * }
324
+ * ```
325
+ */
326
+ destroy(): void;
327
+
328
+ /**
329
+ * Creates a custom collision layer.
330
+ *
331
+ * @param index Index from 0-15 representing which user bit to use (gets shifted to bits 16-31)
332
+ * @returns A unique collision layer value
333
+ *
334
+ * @example
335
+ * ```typescript
336
+ * // Create custom collision layers
337
+ * const WATER_LAYER = physics.createCollisionLayer(0);
338
+ * const LAVA_LAYER = physics.createCollisionLayer(1);
339
+ *
340
+ * // Use in entity creation
341
+ * const waterEntity = physics.createActor({
342
+ * type: 'Water',
343
+ * position: [100, 400],
344
+ * size: [800, 100],
345
+ * collisionLayer: WATER_LAYER,
346
+ * collisionMask: CollisionLayer.PLAYER | CollisionLayer.ENEMY
347
+ * });
348
+ * ```
349
+ */
350
+ createCollisionLayer(index: number): number;
351
+
352
+ /**
353
+ * Creates a collision mask from multiple layers.
354
+ *
355
+ * @param layers Array of collision layers to combine
356
+ * @returns A combined collision mask
357
+ *
358
+ * @example
359
+ * ```typescript
360
+ * // Create a mask that collides with players, enemies and projectiles
361
+ * const mask = physics.createCollisionMask([
362
+ * CollisionLayer.PLAYER,
363
+ * CollisionLayer.ENEMY,
364
+ * CollisionLayer.PROJECTILE
365
+ * ]);
366
+ * ```
367
+ */
368
+ createCollisionMask(...layers: number[]): number;
369
+
370
+ /**
371
+ * Registers a named collision layer for better intellisense support.
372
+ *
373
+ * @param name Name of the collision layer (used for intellisense)
374
+ * @param indexOrDescription Index or description of the layer
375
+ * @param description Optional description of the layer
376
+ * @returns The numeric value of the registered collision layer
377
+ *
378
+ * @example
379
+ * ```typescript
380
+ * // Register named collision layers
381
+ * const WATER = physics.registerCollisionLayer('WATER', 0, 'Water surfaces');
382
+ * const LAVA = physics.registerCollisionLayer('LAVA', 1, 'Lava surfaces that damage players');
383
+ *
384
+ * // Use in entity creation
385
+ * const waterEntity = physics.createActor({
386
+ * type: 'Water',
387
+ * position: [100, 400],
388
+ * size: [800, 100],
389
+ * collisionLayer: WATER,
390
+ * collisionMask: CollisionLayer.PLAYER | CollisionLayer.ENEMY
391
+ * });
392
+ * ```
393
+ */
394
+ registerCollisionLayer(name: string, indexOrDescription?: number | string, description?: string): number;
395
+
396
+ /**
397
+ * Gets a registered collision layer by name.
398
+ *
399
+ * @param name Name of the collision layer
400
+ * @returns The numeric value of the registered collision layer or undefined if not found
401
+ *
402
+ * @example
403
+ * ```typescript
404
+ * // Get a registered collision layer
405
+ * const waterLayer = physics.getCollisionLayer('WATER');
406
+ * if (waterLayer !== undefined) {
407
+ * // Use the layer
408
+ * entity.setCollisionLayer(waterLayer);
409
+ * }
410
+ * ```
411
+ */
412
+ getCollisionLayer(name: string): number | undefined;
413
+
414
+ /**
415
+ * Gets all registered collision layers.
416
+ *
417
+ * @returns Array of all registered collision layers
418
+ *
419
+ * @example
420
+ * ```typescript
421
+ * // Get all registered collision layers
422
+ * const layers = physics.getCollisionLayers();
423
+ * console.log(`Registered layers: ${layers.map(l => l.name).join(', ')}`);
424
+ * ```
425
+ */
426
+ getCollisionLayers(): RegisteredCollisionLayer[];
427
+
428
+ /**
429
+ * Removes a registered collision layer.
430
+ *
431
+ * @param name Name of the collision layer to remove
432
+ * @returns True if the layer was removed, false if it didn't exist
433
+ *
434
+ * @example
435
+ * ```typescript
436
+ * // Remove a registered collision layer
437
+ * physics.removeCollisionLayer('WATER');
438
+ * ```
439
+ */
440
+ removeCollisionLayer(name: string): boolean;
441
+
442
+ /**
443
+ * Clears all registered collision layers.
444
+ *
445
+ * @example
446
+ * ```typescript
447
+ * // Clear all registered collision layers
448
+ * physics.clearCollisionLayers();
449
+ * ```
450
+ */
451
+ clearCollisionLayers(): void;
452
+ }
453
+
454
+ const defaultOptions: Partial<CrunchPhysicsOptions> = {
455
+ gridSize: 128,
456
+ gravity: 900,
457
+ maxVelocity: 400,
458
+ debug: false,
459
+ culling: true,
460
+ boundary: new Rectangle(0, 0, 800, 600),
461
+ };
462
+
463
+ /**
464
+ * Implementation of the Crunch physics plugin.
465
+ * See {@link ICrunchPhysicsPlugin} for detailed API documentation and examples.
466
+ */
467
+ export default class CrunchPhysicsPlugin extends Plugin<CrunchPhysicsOptions> implements ICrunchPhysicsPlugin {
468
+ public system: System;
469
+ public container: PIXIContainer;
470
+ public enabled = false;
471
+ private collisionResolver?: (collisions: Collision[]) => void;
472
+ private overlapResolver?: (overlaps: SensorOverlap[]) => void;
473
+ private actorCollisionResolver?: (collisions: ActorCollision[]) => void;
474
+
475
+ constructor() {
476
+ super('crunch');
477
+ }
478
+
479
+ private hello() {
480
+ const hello = `%c Caper Crunch Physics Plugin v${version}`;
481
+ console.log(hello, 'background: rgba(31, 41, 55, 1);color: #74b64c');
482
+ }
483
+
484
+ public async initialize(options?: Partial<CrunchPhysicsOptions>, _app: IApplication): Promise<void> {
485
+ this.hello();
486
+ if (!options) {
487
+ return;
488
+ }
489
+
490
+ this._options = { ...defaultOptions, ...options } as CrunchPhysicsOptions;
491
+
492
+ this.enabled = true;
493
+ this.container = options.container || this.app.stage;
494
+
495
+ if (isDev) {
496
+ Logger.log(this._options);
497
+ }
498
+
499
+ // Create the physics system
500
+ const gridSize = options.gridSize ?? 32;
501
+ const gravity = options.gravity ?? 900;
502
+ const maxVelocity = options.maxVelocity ?? 400;
503
+ const debug = options.debug ?? false;
504
+ const enableActorCollisions = options.enableActorCollisions ?? false;
505
+
506
+ // Create the system with default collision layers set to NONE for better performance
507
+ this.system = new System({
508
+ gridSize,
509
+ gravity,
510
+ maxVelocity,
511
+ boundary: options.boundary,
512
+ culling: options.culling,
513
+ plugin: this,
514
+ collisionResolver: this.collisionResolver,
515
+ overlapResolver: this.overlapResolver,
516
+ actorCollisionResolver: this.actorCollisionResolver,
517
+ enableActorCollisions,
518
+ defaultCollisionLayer: CollisionLayer.NONE,
519
+ defaultCollisionMask: CollisionLayer.NONE,
520
+ });
521
+
522
+ if (debug) {
523
+ this.system.debug = true;
524
+ }
525
+
526
+ // Register update loop
527
+ this.app.ticker.add(this.update);
528
+ }
529
+
530
+ public setCollisionResolver(resolver: (collisions: Collision[]) => void): void {
531
+ this.collisionResolver = resolver;
532
+ this.system.setCollisionResolver(resolver);
533
+ }
534
+
535
+ public setActorCollisionResolver(resolver: (collisions: ActorCollision[]) => void): void {
536
+ this.actorCollisionResolver = resolver;
537
+ this.system.setActorCollisionResolver(resolver);
538
+ }
539
+
540
+ public setActorCollisionsEnabled(enabled: boolean): void {
541
+ this.system.setActorCollisionsEnabled(enabled);
542
+ }
543
+
544
+ public createEntity(config: PhysicsEntityConfig): Actor | Solid | Sensor | Group {
545
+ return this.system.createEntity(config);
546
+ }
547
+
548
+ public addEntity(entity: Actor | Solid | Sensor | Group): Actor | Solid | Sensor | Group {
549
+ return this.system.addEntity(entity);
550
+ }
551
+
552
+ public createActor(config: PhysicsEntityConfig): Actor {
553
+ return this.system.createActor(config);
554
+ }
555
+
556
+ public createSolid(config: PhysicsEntityConfig): Solid {
557
+ return this.system.createSolid(config);
558
+ }
559
+
560
+ public createSensor(config: PhysicsEntityConfig): Sensor {
561
+ return this.system.createSensor(config);
562
+ }
563
+
564
+ public createGroup(config: PhysicsEntityConfig): Group {
565
+ return this.system.createGroup(config);
566
+ }
567
+
568
+ public addActor(actor: Actor): Actor {
569
+ return this.system.addActor(actor);
570
+ }
571
+
572
+ public addSolid(solid: Solid): Solid {
573
+ return this.system.addSolid(solid);
574
+ }
575
+
576
+ public addSensor(sensor: Sensor): Sensor {
577
+ return this.system.addSensor(sensor);
578
+ }
579
+
580
+ public addGroup(group: Group): Group {
581
+ return this.system.addGroup(group);
582
+ }
583
+
584
+ public removeActor(actor: Actor): void {
585
+ this.system.removeActor(actor);
586
+ }
587
+
588
+ public removeSolid(solid: Solid): void {
589
+ this.system.removeSolid(solid);
590
+ }
591
+
592
+ public removeSensor(sensor: Sensor): void {
593
+ this.system.removeSensor(sensor);
594
+ }
595
+
596
+ public removeGroup(group: Group): void {
597
+ this.system.removeGroup(group);
598
+ }
599
+
600
+ public destroy(): void {
601
+ this.enabled = false;
602
+ this.app.ticker.remove(this.update);
603
+ if (this.system) {
604
+ this.system.destroy();
605
+ // @ts-expect-error system can't be null
606
+ this.system = null;
607
+ }
608
+ super.destroy();
609
+ }
610
+
611
+ private update(_ticker: Ticker) {
612
+ if (!this.enabled) return;
613
+ this.system.update(_ticker.deltaTime);
614
+ }
615
+
616
+ /**
617
+ * Creates a custom collision layer.
618
+ *
619
+ * @param index Index from 0-15 representing which user bit to use (gets shifted to bits 16-31)
620
+ * @returns A unique collision layer value
621
+ */
622
+ public createCollisionLayer(index: number): number {
623
+ return CollisionLayers.createLayer(index);
624
+ }
625
+
626
+ /**
627
+ * Creates a collision mask from multiple layers.
628
+ *
629
+ * @param layers Array of collision layers to combine
630
+ * @returns A combined collision mask
631
+ */
632
+ public createCollisionMask(...layers: number[]): number {
633
+ return CollisionLayers.createMask(layers);
634
+ }
635
+
636
+ /**
637
+ * Registers a named collision layer for better intellisense support.
638
+ *
639
+ * @param name Name of the collision layer (used for intellisense)
640
+ * @param indexOrDescription Index or description of the layer
641
+ * @param description Optional description of the layer
642
+ * @returns The numeric value of the registered collision layer
643
+ */
644
+ public registerCollisionLayer(name: string, indexOrDescription?: number | string, description?: string): number {
645
+ const registry = CollisionLayers.getRegistry();
646
+
647
+ // Handle overloaded method signature
648
+ if (typeof indexOrDescription === 'number') {
649
+ // First overload: registerCollisionLayer(name, index, description?)
650
+ const index = indexOrDescription;
651
+ const layer = registry.register(name, index, description);
652
+ return layer.value;
653
+ } else {
654
+ // Second overload: registerCollisionLayer(name, description?)
655
+ const layerDescription = indexOrDescription;
656
+ const nextIndex = registry.getNextAvailableIndex();
657
+
658
+ if (nextIndex === -1) {
659
+ throw new Error('No more collision layer indices available (maximum 16)');
660
+ }
661
+
662
+ const layer = registry.register(name, nextIndex, layerDescription);
663
+ return layer.value;
664
+ }
665
+ }
666
+
667
+ /**
668
+ * Gets a registered collision layer by name.
669
+ *
670
+ * @param name Name of the collision layer
671
+ * @returns The numeric value of the registered collision layer or undefined if not found
672
+ */
673
+ public getCollisionLayer(name: string): number | undefined {
674
+ const registry = CollisionLayers.getRegistry();
675
+ const layer = registry.get(name);
676
+ return layer?.value;
677
+ }
678
+
679
+ /**
680
+ * Gets all registered collision layers.
681
+ *
682
+ * @returns Array of all registered collision layers
683
+ */
684
+ public getCollisionLayers(): RegisteredCollisionLayer[] {
685
+ const registry = CollisionLayers.getRegistry();
686
+ return registry.getAll();
687
+ }
688
+
689
+ /**
690
+ * Removes a registered collision layer.
691
+ *
692
+ * @param name Name of the collision layer to remove
693
+ * @returns True if the layer was removed, false if it didn't exist
694
+ */
695
+ public removeCollisionLayer(name: string): boolean {
696
+ const registry = CollisionLayers.getRegistry();
697
+ return registry.remove(name);
698
+ }
699
+
700
+ /**
701
+ * Clears all registered collision layers.
702
+ */
703
+ public clearCollisionLayers(): void {
704
+ const registry = CollisionLayers.getRegistry();
705
+ registry.clear();
706
+ }
707
+
708
+ /**
709
+ * Checks if two AABB rectangles overlap.
710
+ *
711
+ * @param a - The first AABB rectangle
712
+ * @param b - The second AABB rectangle
713
+ * @returns True if the rectangles overlap, false otherwise
714
+ */
715
+ public aabbOverlap(a: AABBLike, b: AABBLike): boolean {
716
+ return this.system.aabbOverlap(a, b);
717
+ }
718
+ }