@babylonjsmarket/arcade 0.3.7 → 0.3.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/dist/Components/PinballBuilderInput/PinballBuilderInput.d.ts.map +1 -1
  2. package/dist/Components/PinballBuilderInput/PinballBuilderInput.js +1 -2
  3. package/dist/Components/PinballBuilderInput/PinballBuilderInput.js.map +1 -1
  4. package/package.json +2 -2
  5. package/src/Components/ArcCamera/meta.json +4 -0
  6. package/src/Components/Bullet/meta.json +15 -3
  7. package/src/Components/BulletPool/meta.json +15 -3
  8. package/src/Components/Bumper/meta.json +14 -3
  9. package/src/Components/CameraFollow/CameraFollow.contract.test.ts +2 -1
  10. package/src/Components/CameraFollow/CameraFollow.test.ts +4 -3
  11. package/src/Components/Enemy/meta.json +21 -3
  12. package/src/Components/EnemySpawner/meta.json +15 -3
  13. package/src/Components/EntityPool/meta.json +4 -0
  14. package/src/Components/Flipper/Flipper.viz.tsx +34 -55
  15. package/src/Components/Flipper/meta.json +17 -3
  16. package/src/Components/Health/meta.json +4 -0
  17. package/src/Components/KeyboardMover/KeyboardMover.test.ts +4 -3
  18. package/src/Components/LineOfSight/meta.json +4 -0
  19. package/src/Components/Mesh/meta.json +4 -0
  20. package/src/Components/MeshPrimitive/meta.json +5 -1
  21. package/src/Components/MouseHole/meta.json +13 -3
  22. package/src/Components/Obstacle/meta.json +4 -0
  23. package/src/Components/Physics/meta.json +4 -0
  24. package/src/Components/PinballBuilder/meta.json +19 -3
  25. package/src/Components/PinballBuilderInput/PinballBuilderInput.test.ts +5 -7
  26. package/src/Components/PinballBuilderInput/PinballBuilderInput.ts +1 -11
  27. package/src/Components/PinballBuilderInput/meta.json +14 -3
  28. package/src/Components/PinballCamera/PinballCamera.test.ts +7 -0
  29. package/src/Components/PinballCamera/meta.json +14 -3
  30. package/src/Components/PinballLayout/meta.json +14 -3
  31. package/src/Components/PinballTable/meta.json +13 -3
  32. package/src/Components/Plunger/meta.json +15 -3
  33. package/src/Components/Score/meta.json +5 -1
  34. package/src/Components/ShooterCamera/ShooterCamera.test.ts +7 -0
  35. package/src/Components/ShooterCamera/meta.json +14 -3
  36. package/src/Components/SkeletonAnimator/meta.json +4 -0
  37. package/src/Components/Spinner/meta.json +14 -3
  38. package/src/Components/TwinStickShooter/TwinStickShooter.test.ts +7 -0
  39. package/src/Components/TwinStickShooter/meta.json +17 -3
@@ -1 +1 @@
1
- {"version":3,"file":"PinballBuilderInput.d.ts","sourceRoot":"","sources":["../../../src/Components/PinballBuilderInput/PinballBuilderInput.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAA;AAC7C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAA;AAMpD,OAAO,EAAE,4BAA4B,EAAE,MAAM,4BAA4B,CAAA;AAazE,qBAAa,yBAA0B,SAAQ,MAAM;IACnD,SAAS,CAAC,KAAK;;MAA+C;IAC9D,OAAO,CAAC,MAAM,CAAiC;IAC/C,OAAO,CAAC,iBAAiB,CAAQ;IAEjC,OAAO,CAAC,OAAO,CAAQ;IACvB,OAAO,CAAC,UAAU,CAAoB;IACtC,OAAO,CAAC,QAAQ,CAAuB;IAEvC,OAAO,CAAC,aAAa,CAA2C;IAChE,OAAO,CAAC,aAAa,CAA2C;IAChE,OAAO,CAAC,WAAW,CAA2C;gBAElD,QAAQ,EAAE,QAAQ;IAK9B,SAAS,CAAC,YAAY,IAAI,IAAI;IAW9B,SAAS,CAAC,UAAU,IAAI,IAAI;IAI5B,SAAS,CAAC,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAIrC,OAAO,CAAC,WAAW;IAQnB,OAAO,CAAC,SAAS;IAQjB,OAAO,CAAC,MAAM;IA0Cd,OAAO,CAAC,MAAM;IAiBd,OAAO,CAAC,OAAO;CAgBhB;AAED,OAAO,EACL,4BAA4B,EAC5B,KAAK,wBAAwB,GAC9B,MAAM,4BAA4B,CAAA"}
1
+ {"version":3,"file":"PinballBuilderInput.d.ts","sourceRoot":"","sources":["../../../src/Components/PinballBuilderInput/PinballBuilderInput.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAA;AAC7C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAA;AAMpD,OAAO,EAAE,4BAA4B,EAAE,MAAM,4BAA4B,CAAA;AAIzE,qBAAa,yBAA0B,SAAQ,MAAM;IACnD,SAAS,CAAC,KAAK;;MAA+C;IAC9D,OAAO,CAAC,MAAM,CAAiC;IAC/C,OAAO,CAAC,iBAAiB,CAAQ;IAEjC,OAAO,CAAC,OAAO,CAAQ;IACvB,OAAO,CAAC,UAAU,CAAoB;IACtC,OAAO,CAAC,QAAQ,CAAuB;IAEvC,OAAO,CAAC,aAAa,CAA2C;IAChE,OAAO,CAAC,aAAa,CAA2C;IAChE,OAAO,CAAC,WAAW,CAA2C;gBAElD,QAAQ,EAAE,QAAQ;IAK9B,SAAS,CAAC,YAAY,IAAI,IAAI;IAW9B,SAAS,CAAC,UAAU,IAAI,IAAI;IAI5B,SAAS,CAAC,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAIrC,OAAO,CAAC,WAAW;IAQnB,OAAO,CAAC,SAAS;IAOjB,OAAO,CAAC,MAAM;IA0Cd,OAAO,CAAC,MAAM;IAiBd,OAAO,CAAC,OAAO;CAgBhB;AAED,OAAO,EACL,4BAA4B,EAC5B,KAAK,wBAAwB,GAC9B,MAAM,4BAA4B,CAAA"}
@@ -55,8 +55,7 @@ export class PinballBuilderInputSystem extends System {
55
55
  getCanvas() {
56
56
  if (this.canvas)
57
57
  return this.canvas;
58
- const adapter = this.world?.renderer;
59
- const c = adapter?.scene?.getEngine().getRenderingCanvas() ?? null;
58
+ const c = this.world?.renderer?.getRenderingCanvas() ?? null;
60
59
  this.canvas = c;
61
60
  return c;
62
61
  }
@@ -1 +1 @@
1
- {"version":3,"file":"PinballBuilderInput.js","sourceRoot":"","sources":["../../../src/Components/PinballBuilderInput/PinballBuilderInput.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"PinballBuilderInput.js","sourceRoot":"","sources":["../../../src/Components/PinballBuilderInput/PinballBuilderInput.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@babylonjsmarket/arcade",
3
- "version": "0.3.7",
3
+ "version": "0.3.9",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "description": "Reusable arcade-style components (mesh, camera, lights, input, physics, scoring, animation) for the @babylonjsmarket/ecs framework",
@@ -89,7 +89,7 @@
89
89
  "prepublishOnly": "npm run build && npm run test"
90
90
  },
91
91
  "dependencies": {
92
- "@babylonjsmarket/ecs": "*",
92
+ "@babylonjsmarket/ecs": "^0.5.3",
93
93
  "@clack/prompts": "^0.10.0",
94
94
  "mri": "^1.2.0",
95
95
  "picocolors": "^1.1.1"
@@ -10,5 +10,9 @@
10
10
  ],
11
11
  "dependencies": [
12
12
  "MeshPrimitive"
13
+ ],
14
+ "tags": [
15
+ "core",
16
+ "camera"
13
17
  ]
14
18
  }
@@ -2,7 +2,19 @@
2
2
  "name": "Bullet",
3
3
  "description": "Drives pooled bullet entities (MeshPrimitive + Bullet). Each frame the system advances every live bullet along its direction, expires it on lifetime, on leaving the arena, or when its travel segment crosses a bullet-blocking Obstacle wall, and tests it against live enemies. On a hit it emits `bullet.hit` (for observers like SFX/flashes, carrying the shot direction) then routes damage through HealthSystem via `health.damage`, and releases the bullet back to its pool with `world.removeEntity` rather than destroying it.",
4
4
  "category": "shooter",
5
- "components": ["BulletComponent"],
6
- "systems": ["BulletSystem"],
7
- "dependencies": ["MeshPrimitive", "Health", "Obstacle"]
5
+ "components": [
6
+ "BulletComponent"
7
+ ],
8
+ "systems": [
9
+ "BulletSystem"
10
+ ],
11
+ "dependencies": [
12
+ "MeshPrimitive",
13
+ "Health",
14
+ "Obstacle"
15
+ ],
16
+ "tags": [
17
+ "core",
18
+ "combat"
19
+ ]
8
20
  }
@@ -2,7 +2,19 @@
2
2
  "name": "BulletPool",
3
3
  "description": "Registers a framework entity pool of reusable bullet entities (MeshPrimitive + Bullet) so firing never allocates an entity or mesh. On `bulletPool.fire` it acquires a parked slot and resets its direction/speed/lifetime/damage + muzzle position (with an optional per-shot color), then BulletSystem flies it and parks it again on expiry or hit. Emits `bulletPool.ready` once the pool is pre-built. Parking is the World `active` flag; the park-aware MeshPrimitiveSystem keeps each bullet mesh alive (hidden) for reuse.",
4
4
  "category": "shooter",
5
- "components": ["BulletPoolComponent"],
6
- "systems": ["BulletPoolSystem"],
7
- "dependencies": ["MeshPrimitive", "Bullet"]
5
+ "components": [
6
+ "BulletPoolComponent"
7
+ ],
8
+ "systems": [
9
+ "BulletPoolSystem"
10
+ ],
11
+ "dependencies": [
12
+ "MeshPrimitive",
13
+ "Bullet"
14
+ ],
15
+ "tags": [
16
+ "core",
17
+ "combat",
18
+ "spawning"
19
+ ]
8
20
  }
@@ -2,7 +2,18 @@
2
2
  "name": "Bumper",
3
3
  "description": "Proximity-based scoring trigger. Each bumper owns a hitRadius and a point value; the system runs an XZ distance check against every ball-tagged entity and, on entry, emits bumper.hit plus score.add to award points to ownerEntity. A per-bumper-per-ball debounce keeps a slow rolling ball from re-triggering every frame — the flag only clears once the ball moves beyond releaseRadius. Renderer-agnostic: it reads MeshPrimitive positions only and never touches Babylon or Havok, leaving the physical deflection to a Physics component on the same entity.",
4
4
  "category": "pinball",
5
- "components": ["BumperComponent"],
6
- "systems": ["BumperSystem"],
7
- "dependencies": ["MeshPrimitive", "Score"]
5
+ "components": [
6
+ "BumperComponent"
7
+ ],
8
+ "systems": [
9
+ "BumperSystem"
10
+ ],
11
+ "dependencies": [
12
+ "MeshPrimitive",
13
+ "Score"
14
+ ],
15
+ "tags": [
16
+ "pinball",
17
+ "physics"
18
+ ]
8
19
  }
@@ -5,6 +5,7 @@ import {
5
5
  CameraFollowEvents,
6
6
  } from './CameraFollow';
7
7
  import { ArcCameraComponent } from '../ArcCamera/ArcCamera';
8
+ import { getArcCameraRuntime } from '../ArcCamera/ArcCamera.core';
8
9
 
9
10
  runMechanicContract({
10
11
  name: 'CameraFollow',
@@ -30,7 +31,7 @@ runMechanicContract({
30
31
  const arcEntity = world.createEntity();
31
32
  const arc = new ArcCameraComponent();
32
33
  arc.handle = renderer.createArcCamera(arcEntity.id, arc.toSpec());
33
- arc.initialized = true;
34
+ getArcCameraRuntime(arc).initialized = true;
34
35
  arcEntity.add(arc);
35
36
 
36
37
  // Stub a world position the mesh handle reports through the adapter.
@@ -1,6 +1,7 @@
1
1
  import { describe, it, expect, beforeEach } from 'vitest';
2
2
  import { CameraFollowComponent, CameraFollowSystem } from './CameraFollow';
3
3
  import { ArcCameraComponent } from '../ArcCamera/ArcCamera';
4
+ import { getArcCameraRuntime } from '../ArcCamera/ArcCamera.core';
4
5
  import { EventBus, World } from '@babylonjsmarket/ecs';
5
6
  import { MockRendererAdapter } from '@babylonjsmarket/ecs';
6
7
  import type { MeshHandle } from '@babylonjsmarket/ecs/renderer-types';
@@ -60,7 +61,7 @@ describe('CameraFollowSystem', () => {
60
61
  const arcEntity = world.createEntity('Camera');
61
62
  const arcComp = new ArcCameraComponent();
62
63
  arcComp.handle = renderer.createArcCamera(arcEntity.id, arcComp.toSpec());
63
- arcComp.initialized = true;
64
+ getArcCameraRuntime(arcComp).initialized = true;
64
65
  arcEntity.add(arcComp);
65
66
 
66
67
  const followEntity = world.createEntity('Follow');
@@ -76,7 +77,7 @@ describe('CameraFollowSystem', () => {
76
77
  const arcEntity = world.createEntity('Camera');
77
78
  const arcComp = new ArcCameraComponent();
78
79
  arcComp.handle = renderer.createArcCamera(arcEntity.id, arcComp.toSpec());
79
- arcComp.initialized = true;
80
+ getArcCameraRuntime(arcComp).initialized = true;
80
81
  arcEntity.add(arcComp);
81
82
 
82
83
  // Fake a Player mesh and emit the creation event the system listens for.
@@ -106,7 +107,7 @@ describe('CameraFollowSystem', () => {
106
107
  const arcEntity = world.createEntity('Camera');
107
108
  const arcComp = new ArcCameraComponent();
108
109
  arcComp.handle = renderer.createArcCamera(arcEntity.id, arcComp.toSpec());
109
- arcComp.initialized = true;
110
+ getArcCameraRuntime(arcComp).initialized = true;
110
111
  arcEntity.add(arcComp);
111
112
 
112
113
  const fakeHandle = renderer.createMesh('Player', { kind: 'capsule' });
@@ -2,7 +2,25 @@
2
2
  "name": "Enemy",
3
3
  "description": "Chases the entity tagged `player`, separates from other enemies so they don't stack, and deals contact damage via `health.damage`. Takes bullet hits as `bullet.hit`; on death (HealthSystem's `health.died`) it emits `enemy.killed` and `score.add`. Pooled — instead of being destroyed it asks EntityPool to re-park its slot (`entityPool.release`). Optional SkeletonAnimator support drives walk/attack/death clips, directional fall animations, and a knockback slide that barrels the corpse into the swarm; chase vs wander is driven by LineOfSight's acquired/lost events.",
4
4
  "category": "shooter",
5
- "components": ["EnemyComponent"],
6
- "systems": ["EnemySystem"],
7
- "dependencies": ["MeshPrimitive", "EntityPool", "SkeletonAnimator", "Health", "Score", "Bullet", "Obstacle", "LineOfSight"]
5
+ "components": [
6
+ "EnemyComponent"
7
+ ],
8
+ "systems": [
9
+ "EnemySystem"
10
+ ],
11
+ "dependencies": [
12
+ "MeshPrimitive",
13
+ "EntityPool",
14
+ "SkeletonAnimator",
15
+ "Health",
16
+ "Score",
17
+ "Bullet",
18
+ "Obstacle",
19
+ "LineOfSight"
20
+ ],
21
+ "tags": [
22
+ "core",
23
+ "ai",
24
+ "combat"
25
+ ]
8
26
  }
@@ -2,7 +2,19 @@
2
2
  "name": "EnemySpawner",
3
3
  "description": "Pulses enemies out from its own world position on a timer, up to a per-spawner live cap. It never creates entities itself — it emits `entityPool.spawn` naming its pool, and EntityPool hands out a reused enemy. The cap stays a true live count by tracking the pool's `entityPool.spawned` / `entityPool.released` events (a release covers both a kill and the pool recycling under pressure). Per-spawn hp/speed/color ride along for games that apply overrides on acquire.",
4
4
  "category": "shooter",
5
- "components": ["EnemySpawnerComponent"],
6
- "systems": ["EnemySpawnerSystem"],
7
- "dependencies": ["MeshPrimitive", "EntityPool"]
5
+ "components": [
6
+ "EnemySpawnerComponent"
7
+ ],
8
+ "systems": [
9
+ "EnemySpawnerSystem"
10
+ ],
11
+ "dependencies": [
12
+ "MeshPrimitive",
13
+ "EntityPool"
14
+ ],
15
+ "tags": [
16
+ "core",
17
+ "spawning",
18
+ "ai"
19
+ ]
8
20
  }
@@ -10,5 +10,9 @@
10
10
  ],
11
11
  "dependencies": [
12
12
  "MeshPrimitive"
13
+ ],
14
+ "tags": [
15
+ "core",
16
+ "spawning"
13
17
  ]
14
18
  }
@@ -1,19 +1,19 @@
1
1
  /**
2
2
  * Flipper.viz.tsx — collider-vs-visible-geometry overlay.
3
3
  *
4
- * For every flipper we create a unit-cube wireframe child mesh once, then
5
- * each frame we read the flipper's CURRENT `colliderInflate` values and
6
- * scale + position the wire to match the inflated bounds. No mesh
7
- * recreation; tuning sliders update the wire live as they drag.
4
+ * For every flipper we create a unit-cube wireframe child mesh once (via the
5
+ * adapter's `createDebugBox`, parented to the flipper mesh), then each frame we
6
+ * read the flipper's CURRENT `colliderInflate` values and scale + position the
7
+ * wire to match the inflated bounds. No mesh recreation; tuning sliders update
8
+ * the wire live as they drag.
8
9
  *
9
- * Babylon-only: imports `MeshBuilder` + `StandardMaterial` directly and
10
- * casts the renderer to BabylonAdapterLike, matching the existing approach
11
- * in Flipper.ts itself. The pinball game runs under Babylon.
10
+ * Renderer-agnostic: everything goes through `this.world.renderer`
11
+ * (createDebugBox / setMeshScale / setMeshPosition / disposeMesh) no engine
12
+ * import, no adapter cast.
12
13
  */
13
14
  import { Component, System } from '@babylonjsmarket/ecs'
14
15
  import type { EventBus, Entity } from '@babylonjsmarket/ecs'
15
16
  import type { MeshHandle } from '@babylonjsmarket/ecs/renderer-types'
16
- import { MeshBuilder, StandardMaterial, Color3, type Mesh, type Scene } from '@babylonjs/core'
17
17
  import { FlipperComponent, computeTaperedBounds, inflateBounds } from './Flipper'
18
18
  import { MeshPrimitiveComponent } from '../MeshPrimitive/MeshPrimitive'
19
19
 
@@ -34,9 +34,9 @@ export class FlipperColliderDebuggerComponent extends Component {
34
34
  constructor(data: FlipperColliderDebuggerInput = {}) {
35
35
  super()
36
36
  this.visible = data.visible ?? false
37
- // This debugger is NOT a vizStore panel (it draws a Babylon wireframe
38
- // overlay), so the central viz keyboard handler doesn't manage it — it
39
- // owns its own toggle key. Default Digit5.
37
+ // This debugger is NOT a vizStore panel (it draws a wireframe overlay), so
38
+ // the central viz keyboard handler doesn't manage it — it owns its own
39
+ // toggle key. Default Digit5.
40
40
  this.activationKey = data.activationKey ?? 'Digit5'
41
41
  this.color = data.color ?? [1, 0.2, 0.9]
42
42
  }
@@ -50,24 +50,17 @@ export class FlipperColliderDebuggerComponent extends Component {
50
50
  }
51
51
  }
52
52
 
53
- // Minimum surface the FlipperColliderDebugger needs to grab the Babylon Mesh
54
- // object from the adapter so it can parent a wireframe child to it.
55
- type BabylonAdapterLike = {
56
- getMeshObject: (handle: MeshHandle) => Mesh | undefined
57
- }
58
-
59
53
  interface Overlay {
60
54
  entityId: string
61
55
  flipper: FlipperComponent
62
- parent: Mesh
63
- wire: Mesh
56
+ /** Handle of the wireframe box, parented to the flipper mesh by the adapter. */
57
+ wire: MeshHandle
64
58
  }
65
59
 
66
60
  export class FlipperColliderDebuggerSystem extends System {
67
61
  protected query = { required: [FlipperColliderDebuggerComponent] }
68
62
  private component: FlipperColliderDebuggerComponent | null = null
69
63
  private overlays = new Map<string, Overlay>()
70
- private wireMaterial: StandardMaterial | null = null
71
64
  private keydownHandler: ((e: KeyboardEvent) => void) | null = null
72
65
 
73
66
  constructor(eventBus: EventBus) {
@@ -93,8 +86,6 @@ export class FlipperColliderDebuggerSystem extends System {
93
86
 
94
87
  protected onShutdown(): void {
95
88
  this.clearOverlays()
96
- this.wireMaterial?.dispose()
97
- this.wireMaterial = null
98
89
  if (this.keydownHandler) {
99
90
  window.removeEventListener('keydown', this.keydownHandler)
100
91
  this.keydownHandler = null
@@ -129,12 +120,13 @@ export class FlipperColliderDebuggerSystem extends System {
129
120
 
130
121
  /**
131
122
  * Resize + reposition the wire each frame from the flipper's CURRENT
132
- * `colliderInflate` values. No mesh recreation — Babylon scaling +
133
- * position update is cheap.
123
+ * `colliderInflate` values. No mesh recreation — a scale + position update is
124
+ * cheap. The box is parented to the flipper mesh, so these are LOCAL.
134
125
  */
135
126
  private layoutOverlay(entityId: string, flipper: FlipperComponent): void {
136
127
  const o = this.overlays.get(entityId)
137
- if (!o) return
128
+ const renderer = this.world?.renderer
129
+ if (!o || !renderer) return
138
130
  const dir = flipper.direction === 'left' ? 1 : -1
139
131
  const base = computeTaperedBounds(dir, flipper.length)
140
132
  const inflated = inflateBounds(base, flipper.colliderInflate)
@@ -144,8 +136,8 @@ export class FlipperColliderDebuggerSystem extends System {
144
136
  const cx = (inflated.max[0] + inflated.min[0]) / 2
145
137
  const cy = (inflated.max[1] + inflated.min[1]) / 2
146
138
  const cz = (inflated.max[2] + inflated.min[2]) / 2
147
- o.wire.scaling.set(sx, sy, sz)
148
- o.wire.position.set(cx, cy, cz)
139
+ renderer.setMeshScale(o.wire, sx, sy, sz)
140
+ renderer.setMeshPosition(o.wire, cx, cy, cz)
149
141
  }
150
142
 
151
143
  private buildOverlays(): void {
@@ -160,43 +152,30 @@ export class FlipperColliderDebuggerSystem extends System {
160
152
 
161
153
  private createOverlay(entityId: string, flipper: FlipperComponent): void {
162
154
  if (this.overlays.has(entityId)) return
163
- if (!this.world?.renderer) return
164
- const entity = this.world.getEntity(entityId)
155
+ const renderer = this.world?.renderer
156
+ if (!renderer) return
157
+ const entity = this.world?.getEntity(entityId)
165
158
  const mp = entity?.get(MeshPrimitiveComponent)
166
159
  if (!mp?.handle) return
167
160
 
168
- const adapter = this.world.renderer as unknown as BabylonAdapterLike
169
- const parent = adapter.getMeshObject(mp.handle)
170
- if (!parent) return
171
-
172
- // Unit cube — `layoutOverlay` will scale + position it each frame from
173
- // the current colliderInflate values. Recreating the geometry per slider
174
- // tick would be wasteful; scaling is a single transform update.
175
- const wire = MeshBuilder.CreateBox(
161
+ // Unit cube parented to the flipper mesh — `layoutOverlay` scales +
162
+ // positions it each frame from the current colliderInflate values.
163
+ // Recreating the geometry per slider tick would be wasteful.
164
+ const wire = renderer.createDebugBox(
176
165
  `flipper-collider-wire-${entityId}`,
177
- { width: 1, height: 1, depth: 1 },
178
- parent.getScene(),
166
+ mp.handle,
167
+ this.component?.color ?? [1, 0.2, 0.9],
179
168
  )
180
- wire.parent = parent
181
- wire.isPickable = false
182
- wire.material = this.ensureMaterial(parent.getScene())
169
+ if (!wire) return
183
170
 
184
- this.overlays.set(entityId, { entityId, flipper, parent, wire })
185
- }
186
-
187
- private ensureMaterial(scene: Scene): StandardMaterial {
188
- if (this.wireMaterial) return this.wireMaterial
189
- const color = this.component?.color ?? [1, 0.2, 0.9]
190
- const mat = new StandardMaterial('flipper-collider-wire', scene)
191
- mat.wireframe = true
192
- mat.emissiveColor = new Color3(color[0], color[1], color[2])
193
- mat.disableLighting = true
194
- this.wireMaterial = mat
195
- return mat
171
+ this.overlays.set(entityId, { entityId, flipper, wire })
196
172
  }
197
173
 
198
174
  private clearOverlays(): void {
199
- for (const o of this.overlays.values()) o.wire.dispose()
175
+ const renderer = this.world?.renderer
176
+ if (renderer) {
177
+ for (const o of this.overlays.values()) renderer.disposeMesh(o.wire)
178
+ }
200
179
  this.overlays.clear()
201
180
  }
202
181
  }
@@ -2,7 +2,21 @@
2
2
  "name": "Flipper",
3
3
  "description": "Keyboard-driven kinematic flipper bat. Holding the trigger key (default KeyZ) ramps the bat's Y rotation toward flipAngle at flipSpeed and releasing returns it to restAngle, driving the MeshPrimitive's pose each frame so Havok computes the contact impulse that pings the ball. Opt into taperedGeometry to rebuild the mesh as a trapezoidal prism hinged at the pivot end and inflate the collider against tunneling; pair with Physics autoCreate:false. Emits flipper.colliderRebuilt and listens for flipper.rebuildColliders so debug panels can refit collider extents live. Ships with FlipperColliderDebugger, a Babylon wireframe overlay of the inflated collider toggled by a hotkey.",
4
4
  "category": "pinball",
5
- "components": ["FlipperComponent", "FlipperColliderDebuggerComponent"],
6
- "systems": ["FlipperSystem", "FlipperColliderDebuggerSystem"],
7
- "dependencies": ["MeshPrimitive", "Physics"]
5
+ "components": [
6
+ "FlipperComponent",
7
+ "FlipperColliderDebuggerComponent"
8
+ ],
9
+ "systems": [
10
+ "FlipperSystem",
11
+ "FlipperColliderDebuggerSystem"
12
+ ],
13
+ "dependencies": [
14
+ "MeshPrimitive",
15
+ "Physics"
16
+ ],
17
+ "tags": [
18
+ "pinball",
19
+ "controller",
20
+ "input"
21
+ ]
8
22
  }
@@ -10,5 +10,9 @@
10
10
  ],
11
11
  "dependencies": [
12
12
  "MeshPrimitive"
13
+ ],
14
+ "tags": [
15
+ "core",
16
+ "combat"
13
17
  ]
14
18
  }
@@ -2,6 +2,7 @@ import { describe, it, expect, beforeEach } from 'vitest';
2
2
  import { KeyboardMoverComponent, KeyboardMoverSystem } from './KeyboardMover';
3
3
  import { MeshPrimitiveComponent } from '../MeshPrimitive/MeshPrimitive.core';
4
4
  import { ArcCameraComponent } from '../ArcCamera/ArcCamera';
5
+ import { getArcCameraRuntime } from '../ArcCamera/ArcCamera.core';
5
6
  import { EventBus, World } from '@babylonjsmarket/ecs';
6
7
  import { MockRendererAdapter } from '@babylonjsmarket/ecs';
7
8
 
@@ -29,7 +30,7 @@ describe('KeyboardMover', () => {
29
30
  const camEntity = world.createEntity('Camera');
30
31
  const arc = new ArcCameraComponent({ alpha: 0 });
31
32
  arc.handle = renderer.createArcCamera(camEntity.id, arc.toSpec());
32
- arc.initialized = true;
33
+ getArcCameraRuntime(arc).initialized = true;
33
34
  camEntity.add(arc);
34
35
 
35
36
  const playerEntity = world.createEntity('Player');
@@ -54,7 +55,7 @@ describe('KeyboardMover', () => {
54
55
  const camEntity = world.createEntity('Camera');
55
56
  const arc = new ArcCameraComponent({ alpha: 0 });
56
57
  arc.handle = renderer.createArcCamera(camEntity.id, arc.toSpec());
57
- arc.initialized = true;
58
+ getArcCameraRuntime(arc).initialized = true;
58
59
  camEntity.add(arc);
59
60
 
60
61
  const playerEntity = world.createEntity('Player');
@@ -79,7 +80,7 @@ describe('KeyboardMover', () => {
79
80
  const camEntity = world.createEntity('Camera');
80
81
  const arc = new ArcCameraComponent({ alpha: 0 });
81
82
  arc.handle = renderer.createArcCamera(camEntity.id, arc.toSpec());
82
- arc.initialized = true;
83
+ getArcCameraRuntime(arc).initialized = true;
83
84
  camEntity.add(arc);
84
85
 
85
86
  const playerEntity = world.createEntity('Player');
@@ -11,5 +11,9 @@
11
11
  "dependencies": [
12
12
  "MeshPrimitive",
13
13
  "Obstacle"
14
+ ],
15
+ "tags": [
16
+ "core",
17
+ "ai"
14
18
  ]
15
19
  }
@@ -10,5 +10,9 @@
10
10
  ],
11
11
  "dependencies": [
12
12
  "MeshPrimitive"
13
+ ],
14
+ "tags": [
15
+ "core",
16
+ "rendering"
13
17
  ]
14
18
  }
@@ -8,5 +8,9 @@
8
8
  "systems": [
9
9
  "MeshPrimitiveSystem"
10
10
  ],
11
- "dependencies": []
11
+ "dependencies": [],
12
+ "tags": [
13
+ "core",
14
+ "rendering"
15
+ ]
12
16
  }
@@ -2,7 +2,17 @@
2
2
  "name": "MouseHole",
3
3
  "description": "Saucer / scoop that captures the ball, holds it briefly, then kicks it back into play. A proximity check against the ball's XZ position triggers capture: the system emits mouseHole.captured and score.add (points to ownerEntity), pins the ball to the hole with its velocity zeroed for holdSeconds, then on release applies kickoutVelocity via the physics body and emits mouseHole.released. A short post-kickout cooldown stops the hole from immediately re-capturing the ball it just launched.",
4
4
  "category": "pinball",
5
- "components": ["MouseHoleComponent"],
6
- "systems": ["MouseHoleSystem"],
7
- "dependencies": ["MeshPrimitive", "Score"]
5
+ "components": [
6
+ "MouseHoleComponent"
7
+ ],
8
+ "systems": [
9
+ "MouseHoleSystem"
10
+ ],
11
+ "dependencies": [
12
+ "MeshPrimitive",
13
+ "Score"
14
+ ],
15
+ "tags": [
16
+ "pinball"
17
+ ]
8
18
  }
@@ -8,5 +8,9 @@
8
8
  "systems": [],
9
9
  "dependencies": [
10
10
  "MeshPrimitive"
11
+ ],
12
+ "tags": [
13
+ "core",
14
+ "physics"
11
15
  ]
12
16
  }
@@ -10,5 +10,9 @@
10
10
  ],
11
11
  "dependencies": [
12
12
  "MeshPrimitive"
13
+ ],
14
+ "tags": [
15
+ "core",
16
+ "physics"
13
17
  ]
14
18
  }
@@ -2,7 +2,23 @@
2
2
  "name": "PinballBuilder",
3
3
  "description": "Data-driven, in-game placer for pinball elements. Listens for `pinballBuilder.addBumper`/`addWall`/`addRail`/`addRamp`/`addSpinner`/`addMouseHole` and spawns a fully-wired entity (MeshPrimitive + Shadow + Physics, plus the matching Bumper/Spinner/MouseHole behavior) at the requested table coordinates, emitting `pinballBuilder.entityAdded`. Also handles freehand draw mode: `pinballBuilder.setDrawMode` toggles drawing (echoed via `pinballBuilder.drawModeChanged`) and `pinballBuilder.drawPath` smooths a raw pointer polyline with a Catmull-Rom spline, resamples it at uniform arc-length, and chains one rail/wall segment per interval to turn a freehand line into a clean curved track.",
4
4
  "category": "pinball",
5
- "components": ["PinballBuilderComponent", "PinballBuilderDebuggerComponent"],
6
- "systems": ["PinballBuilderSystem", "PinballBuilderDebuggerSystem"],
7
- "dependencies": ["MeshPrimitive", "Bumper", "Spinner", "MouseHole", "PinballTable"]
5
+ "components": [
6
+ "PinballBuilderComponent",
7
+ "PinballBuilderDebuggerComponent"
8
+ ],
9
+ "systems": [
10
+ "PinballBuilderSystem",
11
+ "PinballBuilderDebuggerSystem"
12
+ ],
13
+ "dependencies": [
14
+ "MeshPrimitive",
15
+ "Bumper",
16
+ "Spinner",
17
+ "MouseHole",
18
+ "PinballTable"
19
+ ],
20
+ "tags": [
21
+ "pinball",
22
+ "builder"
23
+ ]
8
24
  }
@@ -10,15 +10,13 @@ const SET_DRAW_MODE = 'pinballBuilder.setDrawMode';
10
10
  const DRAW_PATH = 'pinballBuilder.drawPath';
11
11
 
12
12
  /**
13
- * Renderer with a Babylon-scene shim that hands back a real jsdom canvas and a
13
+ * Renderer that hands back a real jsdom canvas via `getRenderingCanvas()` and a
14
14
  * pickAtScreenPoint that maps screen X→world (x,z). The system reads the canvas
15
- * via `renderer.scene.getEngine().getRenderingCanvas()`.
15
+ * through the adapter (`renderer.getRenderingCanvas()`) — no engine coupling.
16
16
  */
17
17
  function makeRenderer(canvas: HTMLCanvasElement, pick: (x: number, y: number) => PickResult | null) {
18
- const r = new MockRendererAdapter() as MockRendererAdapter & {
19
- scene: { getEngine: () => { getRenderingCanvas: () => HTMLCanvasElement } };
20
- };
21
- r.scene = { getEngine: () => ({ getRenderingCanvas: () => canvas }) };
18
+ const r = new MockRendererAdapter();
19
+ r.getRenderingCanvas = vi.fn(() => canvas) as never;
22
20
  r.pickAtScreenPoint = vi.fn((x: number, y: number) => pick(x, y)) as never;
23
21
  return r;
24
22
  }
@@ -42,7 +40,7 @@ describe('PinballBuilderInputSystem', () => {
42
40
  const defaultPick = (x: number, y: number): PickResult =>
43
41
  ({ x: x / 10, y: 0, z: y / 10, meshId: 'mesh_Playfield' }) as unknown as PickResult;
44
42
 
45
- function setup(pick = defaultPick) {
43
+ function setup(pick: (x: number, y: number) => PickResult | null = defaultPick) {
46
44
  eventBus = new EventBus();
47
45
  canvas = document.createElement('canvas');
48
46
  canvas.getBoundingClientRect = () => ({ left: 0, top: 0, width: 800, height: 600 }) as DOMRect;
@@ -22,15 +22,6 @@ import { PinballBuilderInputComponent } from './PinballBuilderInput.core'
22
22
 
23
23
  type PickedPoint = { x: number; z: number }
24
24
 
25
- // One remaining renderer coupling: the rendering canvas. Fully abstracting
26
- // it would require a `renderer.getRenderingCanvas()` method on the adapter
27
- // interface, which we haven't added yet. Everything else (picks, camera
28
- // controls, etc.) goes through the RendererAdapter API.
29
- type BabylonSceneLike = {
30
- getEngine: () => { getRenderingCanvas: () => HTMLCanvasElement | null }
31
- }
32
- type BabylonAdapterLike = { scene?: BabylonSceneLike | null }
33
-
34
25
  export class PinballBuilderInputSystem extends System {
35
26
  protected query = { required: [PinballBuilderInputComponent] }
36
27
  private canvas: HTMLCanvasElement | null = null
@@ -78,8 +69,7 @@ export class PinballBuilderInputSystem extends System {
78
69
 
79
70
  private getCanvas(): HTMLCanvasElement | null {
80
71
  if (this.canvas) return this.canvas
81
- const adapter = this.world?.renderer as unknown as BabylonAdapterLike | undefined
82
- const c = adapter?.scene?.getEngine().getRenderingCanvas() ?? null
72
+ const c = this.world?.renderer?.getRenderingCanvas() ?? null
83
73
  this.canvas = c
84
74
  return c
85
75
  }
@@ -2,7 +2,18 @@
2
2
  "name": "PinballBuilderInput",
3
3
  "description": "Canvas-side counterpart to PinballBuilder's freehand drawing. On `pinballBuilder.setDrawMode` { enabled, kind } it attaches (or detaches) pointer listeners to the rendering canvas, projects each sample onto the playfield mesh via the renderer's screen-point pick (filtered by pickMeshPrefix), accumulates a jitter-filtered XZ polyline, and emits `pinballBuilder.drawPath` on pointer release for PinballBuilder to turn into a chained rail or wall. Parameter-free singleton; declare one on any entity to activate the system.",
4
4
  "category": "pinball",
5
- "components": ["PinballBuilderInputComponent"],
6
- "systems": ["PinballBuilderInputSystem"],
7
- "dependencies": ["PinballBuilder"]
5
+ "components": [
6
+ "PinballBuilderInputComponent"
7
+ ],
8
+ "systems": [
9
+ "PinballBuilderInputSystem"
10
+ ],
11
+ "dependencies": [
12
+ "PinballBuilder"
13
+ ],
14
+ "tags": [
15
+ "pinball",
16
+ "builder",
17
+ "input"
18
+ ]
8
19
  }
@@ -33,7 +33,14 @@ describe('PinballCameraSystem', () => {
33
33
  alpha: Math.PI / 2,
34
34
  beta: Math.PI / 3,
35
35
  radius: 15,
36
+ minRadius: 5,
37
+ maxRadius: 50,
38
+ minBeta: 0.1,
39
+ maxBeta: Math.PI / 2 - 0.1,
36
40
  target: [0, 0, 0],
41
+ inertia: 0.9,
42
+ wheelPrecision: 50,
43
+ angularSensibility: 1000,
37
44
  });
38
45
  e.add(arc);
39
46
  return { entity: e, arc };
@@ -2,7 +2,18 @@
2
2
  "name": "PinballCamera",
3
3
  "description": "Locks a fixed top-down pinball view on top of a sibling ArcCamera. Detaches the ArcRotateCamera's pointer controls and overrides its FOV (retrying each frame until the camera handle exists), then listens for `pinballTable.resized` and recomputes the fit distance so the whole table frames neatly at any dimensions, padded by marginFactor. Drives ArcCamera's `distance` (not the raw radius) so a tuning panel can still override zoom. Attach next to ArcCamera on the same entity.",
4
4
  "category": "pinball",
5
- "components": ["PinballCameraComponent"],
6
- "systems": ["PinballCameraSystem"],
7
- "dependencies": ["ArcCamera", "PinballTable"]
5
+ "components": [
6
+ "PinballCameraComponent"
7
+ ],
8
+ "systems": [
9
+ "PinballCameraSystem"
10
+ ],
11
+ "dependencies": [
12
+ "ArcCamera",
13
+ "PinballTable"
14
+ ],
15
+ "tags": [
16
+ "pinball",
17
+ "camera"
18
+ ]
8
19
  }
@@ -2,7 +2,18 @@
2
2
  "name": "PinballLayout",
3
3
  "description": "Declarative proportional placement for table elements. Each entity expresses its position as `x = xCoeff * tableWidth + xOffset` and `z = zCoeff * tableDepth + zOffset`, plus optional X/Z mesh scaling tied to the same dims (scaleWith: both/width/depth/none). The system listens for `pinballTable.resized` and, in one pass, rewrites every layout entity's MeshPrimitive position and scale through the renderer — so resizing the table from the viz panel keeps walls, bumpers, flippers and the playfield correctly arranged.",
4
4
  "category": "pinball",
5
- "components": ["PinballLayoutComponent"],
6
- "systems": ["PinballLayoutSystem"],
7
- "dependencies": ["MeshPrimitive", "PinballTable"]
5
+ "components": [
6
+ "PinballLayoutComponent"
7
+ ],
8
+ "systems": [
9
+ "PinballLayoutSystem"
10
+ ],
11
+ "dependencies": [
12
+ "MeshPrimitive",
13
+ "PinballTable"
14
+ ],
15
+ "tags": [
16
+ "pinball",
17
+ "builder"
18
+ ]
8
19
  }
@@ -2,7 +2,17 @@
2
2
  "name": "PinballTable",
3
3
  "description": "Single source of truth for the playfield's width (X) and depth (Z). One PinballTable entity per scene; the system broadcasts the seed dimensions once as `pinballTable.resized` on init, and on every `pinballTable.resize` request (from the viz panel) it updates the dims and re-broadcasts `pinballTable.resized` so dependent entities (walls, slingshots, flippers, inlanes) reposition and the camera reframes. Defaults match a regulation 20.25\"×42\" Williams/Bally playfield.",
4
4
  "category": "pinball",
5
- "components": ["PinballTableComponent", "PinballTableDebuggerComponent"],
6
- "systems": ["PinballTableSystem", "PinballTableDebuggerSystem"],
7
- "dependencies": []
5
+ "components": [
6
+ "PinballTableComponent",
7
+ "PinballTableDebuggerComponent"
8
+ ],
9
+ "systems": [
10
+ "PinballTableSystem",
11
+ "PinballTableDebuggerSystem"
12
+ ],
13
+ "dependencies": [],
14
+ "tags": [
15
+ "pinball",
16
+ "builder"
17
+ ]
8
18
  }
@@ -2,7 +2,19 @@
2
2
  "name": "Plunger",
3
3
  "description": "Owns the pinball's ball lifecycle. Auto-launches the ball the moment its Havok body appears, re-launches on drain (when the ball falls below drainY or rolls past the bottom-edge drain Z), and fires on a trigger key (default Space) for a manual re-plunge — each launch teleports the ball to spawnPosition and kicks it down-table with launchVelocityZ plus sideways jitter. Also installs the table's tilted scene gravity and Havok's 240 Hz sub-time-step once physics is alive, and listens to pinballTable.resized to keep the drain threshold lined up with the table's bottom edge. Optionally swaps the ball's material for a chrome-mirror PBR.",
4
4
  "category": "pinball",
5
- "components": ["PlungerComponent"],
6
- "systems": ["PlungerSystem"],
7
- "dependencies": ["MeshPrimitive", "PinballTable"]
5
+ "components": [
6
+ "PlungerComponent"
7
+ ],
8
+ "systems": [
9
+ "PlungerSystem"
10
+ ],
11
+ "dependencies": [
12
+ "MeshPrimitive",
13
+ "PinballTable"
14
+ ],
15
+ "tags": [
16
+ "pinball",
17
+ "controller",
18
+ "input"
19
+ ]
8
20
  }
@@ -8,5 +8,9 @@
8
8
  "systems": [
9
9
  "ScoreSystem"
10
10
  ],
11
- "dependencies": []
11
+ "dependencies": [],
12
+ "tags": [
13
+ "core",
14
+ "ui"
15
+ ]
12
16
  }
@@ -61,7 +61,14 @@ describe('ShooterCameraSystem', () => {
61
61
  alpha: Math.PI / 2,
62
62
  beta: Math.PI / 3,
63
63
  radius: 15,
64
+ minRadius: 5,
65
+ maxRadius: 50,
66
+ minBeta: 0.1,
67
+ maxBeta: Math.PI / 2 - 0.1,
64
68
  target: [0, 0, 0],
69
+ inertia: 0.9,
70
+ wheelPrecision: 50,
71
+ angularSensibility: 1000,
65
72
  });
66
73
  e.add(arc);
67
74
  return { entity: e, arc };
@@ -2,7 +2,18 @@
2
2
  "name": "ShooterCamera",
3
3
  "description": "Top-down follow camera companion for twin-stick / top-down shooters. Configures a sibling ArcCamera rather than creating its own: it resolves the live ArcCameraComponent and writes its data — a steep look-down beta + fixed distance, the follow target (so ArcCameraSystem, the single target writer, tracks the player) — then once detaches the orbit controls so the player can't unhinge the framing and overrides the FOV. It no longer reads the player mesh or writes the camera target itself, so it never races ArcCameraSystem. Attach it next to ArcCamera on the same entity.",
4
4
  "category": "shooter",
5
- "components": ["ShooterCameraComponent"],
6
- "systems": ["ShooterCameraSystem"],
7
- "dependencies": ["ArcCamera"]
5
+ "components": [
6
+ "ShooterCameraComponent"
7
+ ],
8
+ "systems": [
9
+ "ShooterCameraSystem"
10
+ ],
11
+ "dependencies": [
12
+ "ArcCamera"
13
+ ],
14
+ "tags": [
15
+ "shooter",
16
+ "twin-stick-shooter",
17
+ "camera"
18
+ ]
8
19
  }
@@ -10,5 +10,9 @@
10
10
  ],
11
11
  "dependencies": [
12
12
  "Mesh"
13
+ ],
14
+ "tags": [
15
+ "core",
16
+ "animation"
13
17
  ]
14
18
  }
@@ -2,7 +2,18 @@
2
2
  "name": "Spinner",
3
3
  "description": "A freely-spinning bar mounted to the playfield. When a ball passes within hitRadius the system imparts angular velocity to the bar (direction set by which side the ball crossed), then integrates that spin each frame with drag decaying it toward zero. Purely kinematic — it rotates the MeshPrimitive directly rather than using a Havok hinge. Every completed revolution emits spinner.spun and score.add for pointsPerSpin to ownerEntity, so one strong hit rewards multiple points as the bar coasts.",
4
4
  "category": "pinball",
5
- "components": ["SpinnerComponent"],
6
- "systems": ["SpinnerSystem"],
7
- "dependencies": ["MeshPrimitive", "Score"]
5
+ "components": [
6
+ "SpinnerComponent"
7
+ ],
8
+ "systems": [
9
+ "SpinnerSystem"
10
+ ],
11
+ "dependencies": [
12
+ "MeshPrimitive",
13
+ "Score"
14
+ ],
15
+ "tags": [
16
+ "pinball",
17
+ "physics"
18
+ ]
8
19
  }
@@ -45,7 +45,14 @@ describe('TwinStickShooterSystem', () => {
45
45
  alpha: -Math.PI / 2,
46
46
  beta: Math.PI / 3,
47
47
  radius: 15,
48
+ minRadius: 5,
49
+ maxRadius: 50,
50
+ minBeta: 0.1,
51
+ maxBeta: Math.PI / 2 - 0.1,
48
52
  target: [0, 0, 0],
53
+ inertia: 0.9,
54
+ wheelPrecision: 50,
55
+ angularSensibility: 1000,
49
56
  });
50
57
  e.add(arc);
51
58
  return e;
@@ -3,7 +3,21 @@
3
3
  "description": "SmashTV-style player controller: WASD moves, the arrow keys fire in 8 directions, both camera-relative (W is always up the screen). The body eases to face where it shoots or heads, and movement is clamped to the arena and pushed out of Obstacle barriers. Firing is pooled — instead of spawning entities it emits `bulletPool.fire` at the muzzle, and reuses a single muzzle-flash mesh per shooter (no per-shot mesh churn).",
4
4
  "category": "shooter",
5
5
  "subgenre": "twin-stick-shooter",
6
- "components": ["TwinStickShooterComponent"],
7
- "systems": ["TwinStickShooterSystem"],
8
- "dependencies": ["MeshPrimitive", "BulletPool", "Obstacle", "ArcCamera"]
6
+ "components": [
7
+ "TwinStickShooterComponent"
8
+ ],
9
+ "systems": [
10
+ "TwinStickShooterSystem"
11
+ ],
12
+ "dependencies": [
13
+ "MeshPrimitive",
14
+ "BulletPool",
15
+ "Obstacle",
16
+ "ArcCamera"
17
+ ],
18
+ "tags": [
19
+ "shooter",
20
+ "twin-stick-shooter",
21
+ "controller"
22
+ ]
9
23
  }