@combos-fun/plugin-cannon 0.0.6 → 0.0.7
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 +26 -0
- package/agent-skill.md +145 -0
- package/combos-plugin.json +11 -0
- package/package.json +17 -3
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,145 @@
|
|
|
1
|
+
# `@combos-fun/plugin-cannon` — Agent notes
|
|
2
|
+
|
|
3
|
+
3D physics for Combos Fun. Wraps `cannon-es` ^0.20 and exposes a
|
|
4
|
+
`Physics3DSystem` plus a `Physics3D` Component that auto-syncs
|
|
5
|
+
`positionX/Y/Z` and `rotationX/Y/Z` to sibling 3D render components every
|
|
6
|
+
frame.
|
|
7
|
+
|
|
8
|
+
Pattern mirrors `plugin-matterjs` (2D): Component stores params, System
|
|
9
|
+
observes + delegates to engine, engine manages `CANNON.World`.
|
|
10
|
+
|
|
11
|
+
## When to read
|
|
12
|
+
|
|
13
|
+
Read for any 3D physics task: gravity, collisions, rigid bodies, ground
|
|
14
|
+
planes, cylinders / spheres, body-mesh sync.
|
|
15
|
+
|
|
16
|
+
## Public API
|
|
17
|
+
|
|
18
|
+
```ts
|
|
19
|
+
import {
|
|
20
|
+
Physics3DSystem,
|
|
21
|
+
Physics3D,
|
|
22
|
+
Physics3DType,
|
|
23
|
+
type Physics3DParams,
|
|
24
|
+
type Physics3DSystemParams,
|
|
25
|
+
} from '@combos-fun/plugin-cannon';
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
### `Physics3DType`
|
|
29
|
+
|
|
30
|
+
| Value | Shape | Notes |
|
|
31
|
+
|-------|-------|-------|
|
|
32
|
+
| `BOX` | `CANNON.Box` | Half-extents from `width`/`height`/`depth` |
|
|
33
|
+
| `SPHERE` | `CANNON.Sphere` | `radius` |
|
|
34
|
+
| `CYLINDER` | `CANNON.Cylinder` | `radiusTop`, `radiusBottom`, `height`, `segments` |
|
|
35
|
+
| `PLANE` | `CANNON.Plane` | Infinite ground; always `mass = 0` |
|
|
36
|
+
|
|
37
|
+
### `Physics3DParams`
|
|
38
|
+
|
|
39
|
+
| Field | Type | Default | Notes |
|
|
40
|
+
|-------|------|---------|-------|
|
|
41
|
+
| `type` | `Physics3DType` | `BOX` | |
|
|
42
|
+
| `mass` | `number` | `1` | `0` = static; `PLANE` always static |
|
|
43
|
+
| `bodyOptions` | `object` | `{}` | `friction`, `restitution`, `linearDamping`, `angularDamping`, `fixedRotation` |
|
|
44
|
+
| `position` | `{x?, y?, z?}` | `0,0,0` | |
|
|
45
|
+
| `rotation` | `{x?, y?, z?}` | `0,0,0` | Euler → quaternion |
|
|
46
|
+
| `width`/`height`/`depth` | `number` | `1` | Box dimensions |
|
|
47
|
+
| `radius` | `number` | `0.5` | Sphere / cylinder radius |
|
|
48
|
+
| `radiusTop`/`radiusBottom` | `number` | `radius` | Cylinder top/bottom |
|
|
49
|
+
| `segments` | `number` | `16` | Cylinder radial segments |
|
|
50
|
+
| `stopRotation` | `boolean` | `false` | Lock rotation sync |
|
|
51
|
+
|
|
52
|
+
Synced public fields (read each `update`):
|
|
53
|
+
|
|
54
|
+
`positionX`, `positionY`, `positionZ`, `rotationX`, `rotationY`,
|
|
55
|
+
`rotationZ`. The system writes these back to **all sibling components**
|
|
56
|
+
on the same `GameObject` that have those fields (duck-type check). So
|
|
57
|
+
`Physics3D` + `Graphics3D` on the same node stay in sync without custom
|
|
58
|
+
glue code.
|
|
59
|
+
|
|
60
|
+
`body: CANNON.Body` is injected by the engine after the body is created.
|
|
61
|
+
|
|
62
|
+
### `Physics3DSystemParams`
|
|
63
|
+
|
|
64
|
+
| Field | Type | Default |
|
|
65
|
+
|-------|------|---------|
|
|
66
|
+
| `gravity` | `{x, y, z}` | `{ x: 0, y: -9.82, z: 0 }` |
|
|
67
|
+
| `fixedTimeStep` | `number` | `1/60` |
|
|
68
|
+
| `maxSubSteps` | `number` | `3` |
|
|
69
|
+
| `allowSleep` | `boolean` | `false` |
|
|
70
|
+
| `solver` | `{ iterations?, tolerance? }` | — |
|
|
71
|
+
|
|
72
|
+
### Collision events
|
|
73
|
+
|
|
74
|
+
Listen on the `Physics3D` instance:
|
|
75
|
+
|
|
76
|
+
```ts
|
|
77
|
+
physics3d.on('collisionStart', (otherGameObject, selfGameObject) => { ... });
|
|
78
|
+
physics3d.on('collisionEnd', (otherGameObject, selfGameObject) => { ... });
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
## Required setup
|
|
82
|
+
|
|
83
|
+
- Add `Renderer3DSystem` (from `plugin-renderer-3d`) **before**
|
|
84
|
+
`Physics3DSystem`.
|
|
85
|
+
- Body creation is **lazy**: it happens only when `Physics3D` is added
|
|
86
|
+
AND the `GameObject` has a parent (is in the scene hierarchy).
|
|
87
|
+
|
|
88
|
+
## Runtime behaviour
|
|
89
|
+
|
|
90
|
+
- Each frame, `Physics3DSystem` steps the `CANNON.World` and writes back
|
|
91
|
+
position/rotation into the component.
|
|
92
|
+
- The `update()` of `Physics3D` then propagates these fields to siblings
|
|
93
|
+
automatically.
|
|
94
|
+
- `onDestroy` removes the body from `CANNON.World`.
|
|
95
|
+
|
|
96
|
+
## Common pitfalls
|
|
97
|
+
|
|
98
|
+
| Symptom | Fix |
|
|
99
|
+
|---------|-----|
|
|
100
|
+
| 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 |
|
|
101
|
+
| Mesh not following body | Make sure `Physics3D` and the visual (e.g. `Graphics3D`) are on the **same** `GameObject` |
|
|
102
|
+
| Body exists but no collision | Check `Physics3DSystem` is registered after `Renderer3DSystem` and `GameObject` is actually in the scene hierarchy |
|
|
103
|
+
| Continuous low-amplitude jitter on a stack | Increase `solver.iterations` or set `allowSleep: true` |
|
|
104
|
+
| Want axis-aligned visual on rotating body | `stopRotation: true` |
|
|
105
|
+
|
|
106
|
+
## Minimal example
|
|
107
|
+
|
|
108
|
+
```ts
|
|
109
|
+
import { Game, Scene, GameObject } from '@combos-fun/engine';
|
|
110
|
+
import { Renderer3DSystem } from '@combos-fun/plugin-renderer-3d';
|
|
111
|
+
import { Graphics3DSystem, Graphics3D } from '@combos-fun/plugin-renderer-3d-graphics';
|
|
112
|
+
import { Physics3DSystem, Physics3D, Physics3DType } from '@combos-fun/plugin-cannon';
|
|
113
|
+
|
|
114
|
+
const game = new Game({
|
|
115
|
+
systems: [
|
|
116
|
+
new Renderer3DSystem({ canvas, width: 750, height: 1000 }),
|
|
117
|
+
new Graphics3DSystem(),
|
|
118
|
+
new Physics3DSystem({ gravity: { x: 0, y: -9.82, z: 0 } }),
|
|
119
|
+
],
|
|
120
|
+
onSystemsBootstrapComplete: (g) => {
|
|
121
|
+
const scene = g.getScene();
|
|
122
|
+
|
|
123
|
+
const box = new GameObject('box');
|
|
124
|
+
box.addComponent(new Graphics3D({ shape: 'box', width: 1, height: 1, depth: 1, color: 0xff0000 }));
|
|
125
|
+
box.addComponent(new Physics3D({
|
|
126
|
+
type: Physics3DType.BOX, mass: 1, width: 1, height: 1, depth: 1,
|
|
127
|
+
position: { x: 0, y: 5, z: 0 },
|
|
128
|
+
}));
|
|
129
|
+
scene.addChild(box);
|
|
130
|
+
|
|
131
|
+
const ground = new GameObject('ground');
|
|
132
|
+
ground.addComponent(new Graphics3D({ shape: 'plane', width: 10, height: 10, color: 0x888888 }));
|
|
133
|
+
ground.addComponent(new Physics3D({
|
|
134
|
+
type: Physics3DType.PLANE,
|
|
135
|
+
rotation: { x: -Math.PI / 2, y: 0, z: 0 },
|
|
136
|
+
}));
|
|
137
|
+
scene.addChild(ground);
|
|
138
|
+
},
|
|
139
|
+
});
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
## Verification
|
|
143
|
+
|
|
144
|
+
- `pnpm --filter @combos-fun/plugin-cannon run build`
|
|
145
|
+
- 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.
|
|
3
|
+
"version": "0.0.7",
|
|
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.
|
|
38
|
+
"@combos-fun/engine": "0.0.7"
|
|
25
39
|
},
|
|
26
40
|
"scripts": {
|
|
27
41
|
"build": "node ../../scripts/build-package.mjs"
|