@combos-fun/plugin-cannon 0.0.6 → 0.0.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1 +1,27 @@
1
1
  # @combos-fun/plugin-cannon
2
+
3
+ @combos-fun/plugin-cannon — part of the Combos Fun engine monorepo.
4
+
5
+ Keywords: `cannon-es`, `3d`, `physics`, `collision`, `rigid-body`, `gravity`.
6
+
7
+ ## Documentation
8
+
9
+ - Per-package agent / developer notes: [`agent-skill.md`](./agent-skill.md)
10
+ - Machine-readable manifest: [`combos-plugin.json`](./combos-plugin.json)
11
+ (validated against `schemas/combos-plugin.schema.json` in the repo
12
+ root)
13
+ - Entry skill (single source of truth for AI agents working with this
14
+ monorepo): `skills/combos-engine-development/SKILL.md`
15
+
16
+ When consumed from npm, the manifest and agent notes are exposed as
17
+ stable subpaths:
18
+
19
+ ```ts
20
+ import manifest from '@combos-fun/plugin-cannon/plugin-manifest';
21
+ // or fetch the markdown directly:
22
+ // require.resolve('@combos-fun/plugin-cannon/agent-skill')
23
+ ```
24
+
25
+ ## License
26
+
27
+ Internal workspace package, part of the Combos Fun engine monorepo.
package/agent-skill.md ADDED
@@ -0,0 +1,136 @@
1
+ # `@combos-fun/plugin-cannon` — Agent notes
2
+
3
+ 3D physics for Combos Fun. Wraps `cannon-es` ^0.20 and exposes a `Physics3DSystem` plus a `Physics3D` Component that auto-syncs `positionX/Y/Z` and `rotationX/Y/Z` to sibling 3D render components every frame.
4
+
5
+ Pattern mirrors `plugin-matterjs` (2D): Component stores params, System observes + delegates to engine, engine manages `CANNON.World`.
6
+
7
+ ## When to read
8
+
9
+ Read for any 3D physics task: gravity, collisions, rigid bodies, ground planes, cylinders / spheres, body-mesh sync.
10
+
11
+ ## Public API
12
+
13
+ ```ts
14
+ import {
15
+ Physics3DSystem,
16
+ Physics3D,
17
+ Physics3DType,
18
+ type Physics3DParams,
19
+ type Physics3DSystemParams,
20
+ } from '@combos-fun/plugin-cannon';
21
+ ```
22
+
23
+ ### `Physics3DType`
24
+
25
+ | Value | Shape | Notes |
26
+ |-------|-------|-------|
27
+ | `BOX` | `CANNON.Box` | Half-extents from `width`/`height`/`depth` |
28
+ | `SPHERE` | `CANNON.Sphere` | `radius` |
29
+ | `CYLINDER` | `CANNON.Cylinder` | `radiusTop`, `radiusBottom`, `height`, `segments` |
30
+ | `PLANE` | `CANNON.Plane` | Infinite ground; always `mass = 0` |
31
+
32
+ ### `Physics3DParams`
33
+
34
+ | Field | Type | Default | Notes |
35
+ |-------|------|---------|-------|
36
+ | `type` | `Physics3DType` | `BOX` | |
37
+ | `mass` | `number` | `1` | `0` = static; `PLANE` always static |
38
+ | `bodyOptions` | `object` | `{}` | `friction`, `restitution`, `linearDamping`, `angularDamping`, `fixedRotation` |
39
+ | `position` | `{x?, y?, z?}` | `0,0,0` | |
40
+ | `rotation` | `{x?, y?, z?}` | `0,0,0` | Euler → quaternion |
41
+ | `width`/`height`/`depth` | `number` | `1` | Box dimensions |
42
+ | `radius` | `number` | `0.5` | Sphere / cylinder radius |
43
+ | `radiusTop`/`radiusBottom` | `number` | `radius` | Cylinder top/bottom |
44
+ | `segments` | `number` | `16` | Cylinder radial segments |
45
+ | `stopRotation` | `boolean` | `false` | Lock rotation sync |
46
+
47
+ Synced public fields (read each `update`):
48
+
49
+ `positionX`, `positionY`, `positionZ`, `rotationX`, `rotationY`, `rotationZ`. The system writes these back to **all sibling components** on the same `GameObject` that have those fields (duck-type check). So `Physics3D` + `Graphics3D` on the same node stay in sync without custom glue code.
50
+
51
+ `body: CANNON.Body` is injected by the engine after the body is created.
52
+
53
+ ### `Physics3DSystemParams`
54
+
55
+ | Field | Type | Default |
56
+ |-------|------|---------|
57
+ | `gravity` | `{x, y, z}` | `{ x: 0, y: -9.82, z: 0 }` |
58
+ | `fixedTimeStep` | `number` | `1/60` |
59
+ | `maxSubSteps` | `number` | `3` |
60
+ | `allowSleep` | `boolean` | `false` |
61
+ | `solver` | `{ iterations?, tolerance? }` | — |
62
+
63
+ ### Collision events
64
+
65
+ Listen on the `Physics3D` instance:
66
+
67
+ ```ts
68
+ physics3d.on('collisionStart', (otherGameObject, selfGameObject) => { ... });
69
+ physics3d.on('collisionEnd', (otherGameObject, selfGameObject) => { ... });
70
+ ```
71
+
72
+ ## Required setup
73
+
74
+ - Add `Renderer3DSystem` (from `plugin-renderer-3d`) **before**
75
+ `Physics3DSystem`.
76
+ - Body creation is **lazy**: it happens only when `Physics3D` is added
77
+ AND the `GameObject` has a parent (is in the scene hierarchy).
78
+
79
+ ## Runtime behaviour
80
+
81
+ - Each frame, `Physics3DSystem` steps the `CANNON.World` and writes back
82
+ position/rotation into the component.
83
+ - The `update()` of `Physics3D` then propagates these fields to siblings
84
+ automatically.
85
+ - `onDestroy` removes the body from `CANNON.World`.
86
+
87
+ ## Common pitfalls
88
+
89
+ | Symptom | Fix |
90
+ |---------|-----|
91
+ | Bodies fall forever | `PLANE` rotated and mass 0 acts as ground; verify `rotation: { x: -Math.PI/2 }` and that it's at the right Y |
92
+ | Mesh not following body | Make sure `Physics3D` and the visual (e.g. `Graphics3D`) are on the **same** `GameObject` |
93
+ | Body exists but no collision | Check `Physics3DSystem` is registered after `Renderer3DSystem` and `GameObject` is actually in the scene hierarchy |
94
+ | Continuous low-amplitude jitter on a stack | Increase `solver.iterations` or set `allowSleep: true` |
95
+ | Want axis-aligned visual on rotating body | `stopRotation: true` |
96
+
97
+ ## Minimal example
98
+
99
+ ```ts
100
+ import { Game, Scene, GameObject } from '@combos-fun/engine';
101
+ import { Renderer3DSystem } from '@combos-fun/plugin-renderer-3d';
102
+ import { Graphics3DSystem, Graphics3D } from '@combos-fun/plugin-renderer-3d-graphics';
103
+ import { Physics3DSystem, Physics3D, Physics3DType } from '@combos-fun/plugin-cannon';
104
+
105
+ const game = new Game({
106
+ systems: [
107
+ new Renderer3DSystem({ canvas, width: 750, height: 1000 }),
108
+ new Graphics3DSystem(),
109
+ new Physics3DSystem({ gravity: { x: 0, y: -9.82, z: 0 } }),
110
+ ],
111
+ onSystemsBootstrapComplete: (g) => {
112
+ const scene = g.getScene();
113
+
114
+ const box = new GameObject('box');
115
+ box.addComponent(new Graphics3D({ shape: 'box', width: 1, height: 1, depth: 1, color: 0xff0000 }));
116
+ box.addComponent(new Physics3D({
117
+ type: Physics3DType.BOX, mass: 1, width: 1, height: 1, depth: 1,
118
+ position: { x: 0, y: 5, z: 0 },
119
+ }));
120
+ scene.addChild(box);
121
+
122
+ const ground = new GameObject('ground');
123
+ ground.addComponent(new Graphics3D({ shape: 'plane', width: 10, height: 10, color: 0x888888 }));
124
+ ground.addComponent(new Physics3D({
125
+ type: Physics3DType.PLANE,
126
+ rotation: { x: -Math.PI / 2, y: 0, z: 0 },
127
+ }));
128
+ scene.addChild(ground);
129
+ },
130
+ });
131
+ ```
132
+
133
+ ## Verification
134
+
135
+ - `pnpm --filter @combos-fun/plugin-cannon run build`
136
+ - Run a 3D physics example; box should fall and rest on the plane.
@@ -0,0 +1,11 @@
1
+ {
2
+ "name": "@combos-fun/plugin-cannon",
3
+ "pluginId": "cannon",
4
+ "category": "physics",
5
+ "dimension": "3d",
6
+ "isCore": false,
7
+ "keywords": ["cannon-es", "3d", "physics", "collision", "rigid-body", "gravity"],
8
+ "agentSkill": "./agent-skill.md",
9
+ "requires": ["@combos-fun/engine", "@combos-fun/plugin-renderer-3d"],
10
+ "exports": ["Physics3DSystem", "Physics3D", "Physics3DType"]
11
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@combos-fun/plugin-cannon",
3
- "version": "0.0.6",
3
+ "version": "0.0.8",
4
4
  "description": "@combos-fun/plugin-cannon",
5
5
  "main": "index.js",
6
6
  "module": "dist/plugin-cannon.esm.js",
@@ -8,8 +8,22 @@
8
8
  "unpkg": "dist/CombosFun.plugin.cannon.min.js",
9
9
  "files": [
10
10
  "index.js",
11
- "dist"
11
+ "dist",
12
+ "agent-skill.md",
13
+ "combos-plugin.json"
12
14
  ],
15
+ "exports": {
16
+ ".": {
17
+ "import": "./dist/plugin-cannon.esm.js",
18
+ "require": "./index.js",
19
+ "types": "./dist/plugin-cannon.d.ts"
20
+ },
21
+ "./plugin-manifest": "./combos-plugin.json",
22
+ "./agent-skill": "./agent-skill.md"
23
+ },
24
+ "combos": {
25
+ "pluginManifest": "./combos-plugin.json"
26
+ },
13
27
  "types": "dist/plugin-cannon.d.ts",
14
28
  "keywords": [
15
29
  "combos-fun",
@@ -21,7 +35,7 @@
21
35
  "author": "sun668 <q947692259@gmail.com>",
22
36
  "dependencies": {
23
37
  "cannon-es": "^0.20.0",
24
- "@combos-fun/engine": "0.0.6"
38
+ "@combos-fun/engine": "0.0.8"
25
39
  },
26
40
  "scripts": {
27
41
  "build": "node ../../scripts/build-package.mjs"