@combos-fun/plugin-cannon 0.0.6
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 +1 -0
- package/dist/plugin-cannon.cjs.js +338 -0
- package/dist/plugin-cannon.cjs.js.map +1 -0
- package/dist/plugin-cannon.cjs.prod.js +1 -0
- package/dist/plugin-cannon.d.ts +87 -0
- package/dist/plugin-cannon.esm.js +315 -0
- package/dist/plugin-cannon.esm.js.map +1 -0
- package/index.js +7 -0
- package/package.json +29 -0
package/README.md
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# @combos-fun/plugin-cannon
|
|
@@ -0,0 +1,338 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var tslib = require('tslib');
|
|
4
|
+
var engine = require('@combos-fun/engine');
|
|
5
|
+
var CANNON = require('cannon-es');
|
|
6
|
+
|
|
7
|
+
function _interopNamespace(e) {
|
|
8
|
+
if (e && e.__esModule) return e;
|
|
9
|
+
var n = Object.create(null);
|
|
10
|
+
if (e) {
|
|
11
|
+
Object.keys(e).forEach(function (k) {
|
|
12
|
+
if (k !== 'default') {
|
|
13
|
+
var d = Object.getOwnPropertyDescriptor(e, k);
|
|
14
|
+
Object.defineProperty(n, k, d.get ? d : {
|
|
15
|
+
enumerable: true,
|
|
16
|
+
get: function () { return e[k]; }
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
n.default = e;
|
|
22
|
+
return Object.freeze(n);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
var CANNON__namespace = /*#__PURE__*/_interopNamespace(CANNON);
|
|
26
|
+
|
|
27
|
+
exports.Physics3DType = void 0;
|
|
28
|
+
(function (Physics3DType) {
|
|
29
|
+
Physics3DType["BOX"] = "box";
|
|
30
|
+
Physics3DType["SPHERE"] = "sphere";
|
|
31
|
+
Physics3DType["CYLINDER"] = "cylinder";
|
|
32
|
+
Physics3DType["PLANE"] = "plane";
|
|
33
|
+
})(exports.Physics3DType || (exports.Physics3DType = {}));
|
|
34
|
+
class Physics3D extends engine.Component {
|
|
35
|
+
constructor() {
|
|
36
|
+
super(...arguments);
|
|
37
|
+
// Readable position/rotation synced from body each frame
|
|
38
|
+
this.positionX = 0;
|
|
39
|
+
this.positionY = 0;
|
|
40
|
+
this.positionZ = 0;
|
|
41
|
+
this.rotationX = 0;
|
|
42
|
+
this.rotationY = 0;
|
|
43
|
+
this.rotationZ = 0;
|
|
44
|
+
this._euler = new CANNON__namespace.Vec3();
|
|
45
|
+
}
|
|
46
|
+
static { this.componentName = 'Physics3D'; }
|
|
47
|
+
init(params) {
|
|
48
|
+
this.bodyParams = params;
|
|
49
|
+
}
|
|
50
|
+
update() {
|
|
51
|
+
if (this.body && this.gameObject) {
|
|
52
|
+
// Sync position from Cannon body
|
|
53
|
+
this.positionX = this.body.position.x;
|
|
54
|
+
this.positionY = this.body.position.y;
|
|
55
|
+
this.positionZ = this.body.position.z;
|
|
56
|
+
// Convert quaternion to Euler and sync rotation
|
|
57
|
+
if (!this.bodyParams.stopRotation) {
|
|
58
|
+
this.body.quaternion.toEuler(this._euler);
|
|
59
|
+
this.rotationX = this._euler.x;
|
|
60
|
+
this.rotationY = this._euler.y;
|
|
61
|
+
this.rotationZ = this._euler.z;
|
|
62
|
+
}
|
|
63
|
+
// Auto-sync to sibling 3D render components on the same GameObject
|
|
64
|
+
this._syncToSiblings();
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
onDestroy() {
|
|
68
|
+
if (this.world && this.body) {
|
|
69
|
+
this.world.removeBody(this.body);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
_syncToSiblings() {
|
|
73
|
+
const components = this.gameObject.components;
|
|
74
|
+
if (!components)
|
|
75
|
+
return;
|
|
76
|
+
for (let i = 0; i < components.length; i++) {
|
|
77
|
+
const comp = components[i];
|
|
78
|
+
if (comp === this)
|
|
79
|
+
continue;
|
|
80
|
+
if ('positionX' in comp && 'positionY' in comp && 'positionZ' in comp) {
|
|
81
|
+
comp.positionX = this.positionX;
|
|
82
|
+
comp.positionY = this.positionY;
|
|
83
|
+
comp.positionZ = this.positionZ;
|
|
84
|
+
}
|
|
85
|
+
if (!this.bodyParams.stopRotation && 'rotationX' in comp && 'rotationY' in comp && 'rotationZ' in comp) {
|
|
86
|
+
comp.rotationX = this.rotationX;
|
|
87
|
+
comp.rotationY = this.rotationY;
|
|
88
|
+
comp.rotationZ = this.rotationZ;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
class BodiesFactory {
|
|
95
|
+
create(component) {
|
|
96
|
+
const { bodyParams } = component;
|
|
97
|
+
const type = bodyParams.type ?? exports.Physics3DType.BOX;
|
|
98
|
+
const mass = bodyParams.mass ?? 1;
|
|
99
|
+
const options = bodyParams.bodyOptions ?? {};
|
|
100
|
+
// Create shape
|
|
101
|
+
let shape;
|
|
102
|
+
switch (type) {
|
|
103
|
+
case exports.Physics3DType.SPHERE: {
|
|
104
|
+
const radius = bodyParams.radius ?? 0.5;
|
|
105
|
+
shape = new CANNON__namespace.Sphere(radius);
|
|
106
|
+
break;
|
|
107
|
+
}
|
|
108
|
+
case exports.Physics3DType.CYLINDER: {
|
|
109
|
+
const radiusTop = bodyParams.radiusTop ?? bodyParams.radius ?? 0.5;
|
|
110
|
+
const radiusBottom = bodyParams.radiusBottom ?? bodyParams.radius ?? 0.5;
|
|
111
|
+
const height = bodyParams.height ?? 1;
|
|
112
|
+
const segments = bodyParams.segments ?? 16;
|
|
113
|
+
shape = new CANNON__namespace.Cylinder(radiusTop, radiusBottom, height, segments);
|
|
114
|
+
break;
|
|
115
|
+
}
|
|
116
|
+
case exports.Physics3DType.PLANE: {
|
|
117
|
+
shape = new CANNON__namespace.Plane();
|
|
118
|
+
break;
|
|
119
|
+
}
|
|
120
|
+
case exports.Physics3DType.BOX:
|
|
121
|
+
default: {
|
|
122
|
+
const w = bodyParams.width ?? 1;
|
|
123
|
+
const h = bodyParams.height ?? 1;
|
|
124
|
+
const d = bodyParams.depth ?? 1;
|
|
125
|
+
shape = new CANNON__namespace.Box(new CANNON__namespace.Vec3(w / 2, h / 2, d / 2));
|
|
126
|
+
break;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
// Create body
|
|
130
|
+
const body = new CANNON__namespace.Body({
|
|
131
|
+
mass: type === exports.Physics3DType.PLANE ? 0 : mass,
|
|
132
|
+
shape,
|
|
133
|
+
});
|
|
134
|
+
// Set position
|
|
135
|
+
const pos = bodyParams.position;
|
|
136
|
+
if (pos) {
|
|
137
|
+
body.position.set(pos.x ?? 0, pos.y ?? 0, pos.z ?? 0);
|
|
138
|
+
}
|
|
139
|
+
// Set rotation (Euler to quaternion)
|
|
140
|
+
const rot = bodyParams.rotation;
|
|
141
|
+
if (rot) {
|
|
142
|
+
body.quaternion.setFromEuler(rot.x ?? 0, rot.y ?? 0, rot.z ?? 0);
|
|
143
|
+
}
|
|
144
|
+
// Apply body options
|
|
145
|
+
if (options.friction !== undefined)
|
|
146
|
+
body.material = new CANNON__namespace.Material({ friction: options.friction, restitution: options.restitution ?? 0.3 });
|
|
147
|
+
if (options.restitution !== undefined && !body.material)
|
|
148
|
+
body.material = new CANNON__namespace.Material({ friction: 0.3, restitution: options.restitution });
|
|
149
|
+
if (options.linearDamping !== undefined)
|
|
150
|
+
body.linearDamping = options.linearDamping;
|
|
151
|
+
if (options.angularDamping !== undefined)
|
|
152
|
+
body.angularDamping = options.angularDamping;
|
|
153
|
+
if (options.fixedRotation !== undefined)
|
|
154
|
+
body.fixedRotation = options.fixedRotation;
|
|
155
|
+
body.updateMassProperties();
|
|
156
|
+
return body;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
class Physics3DEngine {
|
|
161
|
+
constructor(game, options) {
|
|
162
|
+
this.enabled = false;
|
|
163
|
+
this.game = game;
|
|
164
|
+
this.options = options;
|
|
165
|
+
this.bodiesFactory = new BodiesFactory();
|
|
166
|
+
}
|
|
167
|
+
start() {
|
|
168
|
+
this.world = new CANNON__namespace.World();
|
|
169
|
+
// Set gravity
|
|
170
|
+
const gravity = this.options.gravity ?? { x: 0, y: -9.82, z: 0 };
|
|
171
|
+
this.world.gravity.set(gravity.x, gravity.y, gravity.z);
|
|
172
|
+
// Configure solver
|
|
173
|
+
if (this.options.solver) {
|
|
174
|
+
const solver = this.world.solver;
|
|
175
|
+
if (this.options.solver.iterations !== undefined) {
|
|
176
|
+
solver.iterations = this.options.solver.iterations;
|
|
177
|
+
}
|
|
178
|
+
if (this.options.solver.tolerance !== undefined) {
|
|
179
|
+
solver.tolerance = this.options.solver.tolerance;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
this.world.broadphase = new CANNON__namespace.NaiveBroadphase();
|
|
183
|
+
this.world.allowSleep = this.options.allowSleep ?? false;
|
|
184
|
+
this.enabled = true;
|
|
185
|
+
this.initCollisionEvents();
|
|
186
|
+
}
|
|
187
|
+
update(e) {
|
|
188
|
+
if (!this.world || !this.enabled)
|
|
189
|
+
return;
|
|
190
|
+
const fixedTimeStep = this.options.fixedTimeStep ?? 1 / 60;
|
|
191
|
+
const maxSubSteps = this.options.maxSubSteps ?? 3;
|
|
192
|
+
const dt = (e.deltaTime || 16.67) / 1000;
|
|
193
|
+
this.world.step(fixedTimeStep, dt, maxSubSteps);
|
|
194
|
+
}
|
|
195
|
+
stop() {
|
|
196
|
+
this.enabled = false;
|
|
197
|
+
}
|
|
198
|
+
awake() {
|
|
199
|
+
this.enabled = true;
|
|
200
|
+
}
|
|
201
|
+
destroy() {
|
|
202
|
+
if (this.world) {
|
|
203
|
+
// Remove all bodies
|
|
204
|
+
while (this.world.bodies.length > 0) {
|
|
205
|
+
this.world.removeBody(this.world.bodies[0]);
|
|
206
|
+
}
|
|
207
|
+
this.world = null;
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
add(component) {
|
|
211
|
+
const body = this.bodiesFactory.create(component);
|
|
212
|
+
this.world.addBody(body);
|
|
213
|
+
// Inject references into component
|
|
214
|
+
component.body = body;
|
|
215
|
+
component.world = this.world;
|
|
216
|
+
// Back-link for collision event lookup
|
|
217
|
+
body.component = component;
|
|
218
|
+
}
|
|
219
|
+
change(component) {
|
|
220
|
+
// Remove old body, create and add new one
|
|
221
|
+
if (component.body) {
|
|
222
|
+
this.world.removeBody(component.body);
|
|
223
|
+
}
|
|
224
|
+
const newBody = this.bodiesFactory.create(component);
|
|
225
|
+
this.world.addBody(newBody);
|
|
226
|
+
component.body = newBody;
|
|
227
|
+
newBody.component = component;
|
|
228
|
+
}
|
|
229
|
+
remove(component) {
|
|
230
|
+
if (component.body) {
|
|
231
|
+
this.world.removeBody(component.body);
|
|
232
|
+
component.body = undefined;
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
initCollisionEvents() {
|
|
236
|
+
// beginContact: emitted when two bodies start touching
|
|
237
|
+
this.world.addEventListener('beginContact', (event) => {
|
|
238
|
+
const bodyA = event.bodyA;
|
|
239
|
+
const bodyB = event.bodyB;
|
|
240
|
+
const componentA = bodyA.component;
|
|
241
|
+
const componentB = bodyB.component;
|
|
242
|
+
if (componentA && componentB) {
|
|
243
|
+
componentA.emit('collisionStart', componentB.gameObject, componentA.gameObject);
|
|
244
|
+
componentB.emit('collisionStart', componentA.gameObject, componentB.gameObject);
|
|
245
|
+
}
|
|
246
|
+
});
|
|
247
|
+
// endContact: emitted when two bodies stop touching
|
|
248
|
+
this.world.addEventListener('endContact', (event) => {
|
|
249
|
+
const bodyA = event.bodyA;
|
|
250
|
+
const bodyB = event.bodyB;
|
|
251
|
+
const componentA = bodyA.component;
|
|
252
|
+
const componentB = bodyB.component;
|
|
253
|
+
if (componentA && componentB) {
|
|
254
|
+
componentA.emit('collisionEnd', componentB.gameObject, componentA.gameObject);
|
|
255
|
+
componentB.emit('collisionEnd', componentA.gameObject, componentB.gameObject);
|
|
256
|
+
}
|
|
257
|
+
});
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
let Physics3DSystem = class Physics3DSystem extends engine.System {
|
|
262
|
+
static { this.systemName = 'Physics3DSystem'; }
|
|
263
|
+
init(param) {
|
|
264
|
+
this.engine = new Physics3DEngine(this.game, param);
|
|
265
|
+
}
|
|
266
|
+
awake() { }
|
|
267
|
+
start() {
|
|
268
|
+
this.engine.start();
|
|
269
|
+
}
|
|
270
|
+
update(e) {
|
|
271
|
+
const changes = this.componentObserver.clear();
|
|
272
|
+
for (const changed of changes) {
|
|
273
|
+
if (changed) {
|
|
274
|
+
this.componentChanged(changed);
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
this.engine.update(e);
|
|
278
|
+
}
|
|
279
|
+
componentChanged(changed) {
|
|
280
|
+
if (changed.component instanceof Physics3D) {
|
|
281
|
+
switch (changed.type) {
|
|
282
|
+
case engine.OBSERVER_TYPE.ADD: {
|
|
283
|
+
if (changed.gameObject.transform.parent && !changed.gameObject.getComponent(Physics3D).body) {
|
|
284
|
+
this.engine.add(changed.component);
|
|
285
|
+
}
|
|
286
|
+
break;
|
|
287
|
+
}
|
|
288
|
+
case engine.OBSERVER_TYPE.CHANGE: {
|
|
289
|
+
this.engine.change(changed.component);
|
|
290
|
+
break;
|
|
291
|
+
}
|
|
292
|
+
case engine.OBSERVER_TYPE.REMOVE: {
|
|
293
|
+
break;
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
else {
|
|
298
|
+
// Transform._parent change
|
|
299
|
+
switch (changed.type) {
|
|
300
|
+
case engine.OBSERVER_TYPE.CHANGE: {
|
|
301
|
+
if (changed.component.parent) {
|
|
302
|
+
let physics = changed.gameObject.getComponent(Physics3D);
|
|
303
|
+
if (physics && !physics.body) {
|
|
304
|
+
this.engine.add(physics);
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
else {
|
|
308
|
+
let physics = changed.gameObject.getComponent(Physics3D);
|
|
309
|
+
physics && this.engine.remove(physics);
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
lateUpdate() { }
|
|
316
|
+
onResume() {
|
|
317
|
+
if (!this.engine.enabled) {
|
|
318
|
+
this.engine.awake();
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
onPause() {
|
|
322
|
+
this.engine.stop();
|
|
323
|
+
}
|
|
324
|
+
onDestroy() {
|
|
325
|
+
this.engine?.destroy();
|
|
326
|
+
}
|
|
327
|
+
};
|
|
328
|
+
Physics3DSystem = tslib.__decorate([
|
|
329
|
+
engine.decorators.componentObserver({
|
|
330
|
+
Physics3D: [{ prop: ['bodyParams'], deep: true }],
|
|
331
|
+
Transform: ['_parent'],
|
|
332
|
+
})
|
|
333
|
+
], Physics3DSystem);
|
|
334
|
+
var Physics3DSystem_default = Physics3DSystem;
|
|
335
|
+
|
|
336
|
+
exports.Physics3D = Physics3D;
|
|
337
|
+
exports.Physics3DSystem = Physics3DSystem_default;
|
|
338
|
+
//# sourceMappingURL=plugin-cannon.cjs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin-cannon.cjs.js","sources":["../lib/Physics3D.ts","../lib/BodiesFactory.ts","../lib/Physics3DEngine.ts","../lib/Physics3DSystem.ts"],"sourcesContent":["import { Component } from '@combos-fun/engine';\nimport * as CANNON from 'cannon-es';\n\nexport enum Physics3DType {\n BOX = 'box',\n SPHERE = 'sphere',\n CYLINDER = 'cylinder',\n PLANE = 'plane',\n}\n\nexport interface Physics3DParams {\n type?: Physics3DType\n mass?: number\n bodyOptions?: {\n friction?: number\n restitution?: number\n linearDamping?: number\n angularDamping?: number\n fixedRotation?: boolean\n [propName: string]: any\n }\n position?: {\n x?: number\n y?: number\n z?: number\n }\n rotation?: {\n x?: number\n y?: number\n z?: number\n }\n width?: number\n height?: number\n depth?: number\n radius?: number\n radiusTop?: number\n radiusBottom?: number\n segments?: number\n stopRotation?: boolean\n}\n\nexport class Physics3D extends Component<Physics3DParams> {\n static componentName: string = 'Physics3D';\n public bodyParams: Physics3DParams;\n public body: CANNON.Body;\n private world: CANNON.World;\n\n // Readable position/rotation synced from body each frame\n public positionX: number = 0;\n public positionY: number = 0;\n public positionZ: number = 0;\n public rotationX: number = 0;\n public rotationY: number = 0;\n public rotationZ: number = 0;\n\n private _euler: CANNON.Vec3 = new CANNON.Vec3();\n\n init(params: Physics3DParams) {\n this.bodyParams = params;\n }\n\n update() {\n if (this.body && this.gameObject) {\n // Sync position from Cannon body\n this.positionX = this.body.position.x;\n this.positionY = this.body.position.y;\n this.positionZ = this.body.position.z;\n\n // Convert quaternion to Euler and sync rotation\n if (!this.bodyParams.stopRotation) {\n this.body.quaternion.toEuler(this._euler);\n this.rotationX = this._euler.x;\n this.rotationY = this._euler.y;\n this.rotationZ = this._euler.z;\n }\n\n // Auto-sync to sibling 3D render components on the same GameObject\n this._syncToSiblings();\n }\n }\n\n onDestroy() {\n if (this.world && this.body) {\n this.world.removeBody(this.body);\n }\n }\n\n private _syncToSiblings() {\n const components = this.gameObject.components;\n if (!components) return;\n for (let i = 0; i < components.length; i++) {\n const comp = components[i] as any;\n if (comp === this) continue;\n if ('positionX' in comp && 'positionY' in comp && 'positionZ' in comp) {\n comp.positionX = this.positionX;\n comp.positionY = this.positionY;\n comp.positionZ = this.positionZ;\n }\n if (!this.bodyParams.stopRotation && 'rotationX' in comp && 'rotationY' in comp && 'rotationZ' in comp) {\n comp.rotationX = this.rotationX;\n comp.rotationY = this.rotationY;\n comp.rotationZ = this.rotationZ;\n }\n }\n }\n}\n","import * as CANNON from 'cannon-es';\nimport { Physics3DType } from './Physics3D';\nimport type { Physics3D } from './Physics3D';\n\nexport default class BodiesFactory {\n public create(component: Physics3D): CANNON.Body {\n const { bodyParams } = component;\n const type = bodyParams.type ?? Physics3DType.BOX;\n const mass = bodyParams.mass ?? 1;\n const options = bodyParams.bodyOptions ?? {};\n\n // Create shape\n let shape: CANNON.Shape;\n switch (type) {\n case Physics3DType.SPHERE: {\n const radius = bodyParams.radius ?? 0.5;\n shape = new CANNON.Sphere(radius);\n break;\n }\n case Physics3DType.CYLINDER: {\n const radiusTop = bodyParams.radiusTop ?? bodyParams.radius ?? 0.5;\n const radiusBottom = bodyParams.radiusBottom ?? bodyParams.radius ?? 0.5;\n const height = bodyParams.height ?? 1;\n const segments = bodyParams.segments ?? 16;\n shape = new CANNON.Cylinder(radiusTop, radiusBottom, height, segments);\n break;\n }\n case Physics3DType.PLANE: {\n shape = new CANNON.Plane();\n break;\n }\n case Physics3DType.BOX:\n default: {\n const w = bodyParams.width ?? 1;\n const h = bodyParams.height ?? 1;\n const d = bodyParams.depth ?? 1;\n shape = new CANNON.Box(new CANNON.Vec3(w / 2, h / 2, d / 2));\n break;\n }\n }\n\n // Create body\n const body = new CANNON.Body({\n mass: type === Physics3DType.PLANE ? 0 : mass,\n shape,\n });\n\n // Set position\n const pos = bodyParams.position;\n if (pos) {\n body.position.set(pos.x ?? 0, pos.y ?? 0, pos.z ?? 0);\n }\n\n // Set rotation (Euler to quaternion)\n const rot = bodyParams.rotation;\n if (rot) {\n body.quaternion.setFromEuler(rot.x ?? 0, rot.y ?? 0, rot.z ?? 0);\n }\n\n // Apply body options\n if (options.friction !== undefined) body.material = new CANNON.Material({ friction: options.friction, restitution: options.restitution ?? 0.3 });\n if (options.restitution !== undefined && !body.material) body.material = new CANNON.Material({ friction: 0.3, restitution: options.restitution });\n if (options.linearDamping !== undefined) body.linearDamping = options.linearDamping;\n if (options.angularDamping !== undefined) body.angularDamping = options.angularDamping;\n if (options.fixedRotation !== undefined) body.fixedRotation = options.fixedRotation;\n body.updateMassProperties();\n\n return body;\n }\n}\n","import * as CANNON from 'cannon-es';\nimport BodiesFactory from './BodiesFactory';\nimport type { Component, Game } from '@combos-fun/engine';\nimport type { Physics3DSystemParams } from './Physics3DSystem';\nimport type { Physics3D } from './Physics3D';\n\ninterface PhysicsLinkedBody extends CANNON.Body {\n component?: Physics3D;\n}\n\nexport default class Physics3DEngine {\n private world: CANNON.World;\n private bodiesFactory: BodiesFactory;\n private options: Physics3DSystemParams;\n private game: Game;\n public enabled: boolean = false;\n\n constructor(game: Game, options: Physics3DSystemParams) {\n this.game = game;\n this.options = options;\n this.bodiesFactory = new BodiesFactory();\n }\n\n public start() {\n this.world = new CANNON.World();\n\n // Set gravity\n const gravity = this.options.gravity ?? { x: 0, y: -9.82, z: 0 };\n this.world.gravity.set(gravity.x, gravity.y, gravity.z);\n\n // Configure solver\n if (this.options.solver) {\n const solver = this.world.solver as CANNON.GSSolver;\n if (this.options.solver.iterations !== undefined) {\n solver.iterations = this.options.solver.iterations;\n }\n if (this.options.solver.tolerance !== undefined) {\n solver.tolerance = this.options.solver.tolerance;\n }\n }\n\n this.world.broadphase = new CANNON.NaiveBroadphase();\n this.world.allowSleep = this.options.allowSleep ?? false;\n\n this.enabled = true;\n this.initCollisionEvents();\n }\n\n public update(e) {\n if (!this.world || !this.enabled) return;\n const fixedTimeStep = this.options.fixedTimeStep ?? 1 / 60;\n const maxSubSteps = this.options.maxSubSteps ?? 3;\n const dt = (e.deltaTime || 16.67) / 1000;\n this.world.step(fixedTimeStep, dt, maxSubSteps);\n }\n\n public stop() {\n this.enabled = false;\n }\n\n public awake() {\n this.enabled = true;\n }\n\n public destroy() {\n if (this.world) {\n // Remove all bodies\n while (this.world.bodies.length > 0) {\n this.world.removeBody(this.world.bodies[0]);\n }\n this.world = null;\n }\n }\n\n public add(component: Physics3D) {\n const body = this.bodiesFactory.create(component) as PhysicsLinkedBody;\n this.world.addBody(body);\n\n // Inject references into component\n component.body = body;\n (component as any).world = this.world;\n\n // Back-link for collision event lookup\n body.component = component;\n }\n\n public change(component: Physics3D) {\n // Remove old body, create and add new one\n if (component.body) {\n this.world.removeBody(component.body);\n }\n const newBody = this.bodiesFactory.create(component) as PhysicsLinkedBody;\n this.world.addBody(newBody);\n component.body = newBody;\n newBody.component = component;\n }\n\n public remove(component: Physics3D) {\n if (component.body) {\n this.world.removeBody(component.body);\n component.body = undefined;\n }\n }\n\n private initCollisionEvents() {\n // beginContact: emitted when two bodies start touching\n this.world.addEventListener('beginContact', (event: any) => {\n const bodyA = event.bodyA as PhysicsLinkedBody;\n const bodyB = event.bodyB as PhysicsLinkedBody;\n const componentA: Component = bodyA.component;\n const componentB: Component = bodyB.component;\n if (componentA && componentB) {\n componentA.emit('collisionStart', componentB.gameObject, componentA.gameObject);\n componentB.emit('collisionStart', componentA.gameObject, componentB.gameObject);\n }\n });\n\n // endContact: emitted when two bodies stop touching\n this.world.addEventListener('endContact', (event: any) => {\n const bodyA = event.bodyA as PhysicsLinkedBody;\n const bodyB = event.bodyB as PhysicsLinkedBody;\n const componentA: Component = bodyA.component;\n const componentB: Component = bodyB.component;\n if (componentA && componentB) {\n componentA.emit('collisionEnd', componentB.gameObject, componentA.gameObject);\n componentB.emit('collisionEnd', componentA.gameObject, componentB.gameObject);\n }\n });\n }\n}\n","import { System, decorators, OBSERVER_TYPE, Transform } from '@combos-fun/engine';\nimport type { ComponentChanged } from '@combos-fun/engine';\nimport Physics3DEngine from './Physics3DEngine';\nimport { Physics3D } from './Physics3D';\n\nexport interface Physics3DSystemParams {\n gravity?: {\n x: number\n y: number\n z: number\n }\n fixedTimeStep?: number\n maxSubSteps?: number\n allowSleep?: boolean\n solver?: {\n iterations?: number\n tolerance?: number\n }\n}\n\n@decorators.componentObserver({\n Physics3D: [{ prop: ['bodyParams'], deep: true }],\n Transform: ['_parent'],\n})\nexport default class Physics3DSystem extends System<Physics3DSystemParams> {\n static systemName = 'Physics3DSystem';\n private engine: Physics3DEngine;\n\n init(param?: Physics3DSystemParams) {\n this.engine = new Physics3DEngine(this.game, param);\n }\n\n awake() { }\n\n start() {\n this.engine.start();\n }\n\n update(e) {\n const changes = this.componentObserver.clear();\n for (const changed of changes) {\n if (changed) {\n this.componentChanged(changed);\n }\n }\n this.engine.update(e);\n }\n\n componentChanged(changed: ComponentChanged) {\n if (changed.component instanceof Physics3D) {\n switch (changed.type) {\n case OBSERVER_TYPE.ADD: {\n if (changed.gameObject.transform.parent && !changed.gameObject.getComponent(Physics3D).body) {\n this.engine.add(changed.component);\n }\n break;\n }\n case OBSERVER_TYPE.CHANGE: {\n this.engine.change(changed.component);\n break;\n }\n case OBSERVER_TYPE.REMOVE: {\n break;\n }\n }\n } else {\n // Transform._parent change\n switch (changed.type) {\n case OBSERVER_TYPE.CHANGE: {\n if ((changed.component as Transform).parent) {\n let physics = changed.gameObject.getComponent(Physics3D);\n if (physics && !physics.body) {\n this.engine.add(physics);\n }\n } else {\n let physics = changed.gameObject.getComponent(Physics3D);\n physics && this.engine.remove(physics);\n }\n }\n }\n }\n }\n\n lateUpdate() { }\n\n onResume() {\n if (!this.engine.enabled) {\n this.engine.awake();\n }\n }\n\n onPause() {\n this.engine.stop();\n }\n\n onDestroy() {\n this.engine?.destroy();\n }\n}\n"],"names":["Physics3DType","Component","CANNON","System","OBSERVER_TYPE","__decorate","decorators"],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";var t=require("tslib"),e=require("@combos-fun/engine");function o(t){if(t&&t.__esModule)return t;var e=Object.create(null);return t&&Object.keys(t).forEach(function(o){if("default"!==o){var i=Object.getOwnPropertyDescriptor(t,o);Object.defineProperty(e,o,i.get?i:{enumerable:!0,get:function(){return t[o]}})}}),e.default=t,Object.freeze(e)}var i,s=o(require("cannon-es"));exports.Physics3DType=void 0,(i=exports.Physics3DType||(exports.Physics3DType={})).BOX="box",i.SPHERE="sphere",i.CYLINDER="cylinder",i.PLANE="plane";class n extends e.Component{constructor(){super(...arguments),this.positionX=0,this.positionY=0,this.positionZ=0,this.rotationX=0,this.rotationY=0,this.rotationZ=0,this._euler=new s.Vec3}static{this.componentName="Physics3D"}init(t){this.bodyParams=t}update(){this.body&&this.gameObject&&(this.positionX=this.body.position.x,this.positionY=this.body.position.y,this.positionZ=this.body.position.z,this.bodyParams.stopRotation||(this.body.quaternion.toEuler(this._euler),this.rotationX=this._euler.x,this.rotationY=this._euler.y,this.rotationZ=this._euler.z),this._syncToSiblings())}onDestroy(){this.world&&this.body&&this.world.removeBody(this.body)}_syncToSiblings(){const t=this.gameObject.components;if(t)for(let e=0;e<t.length;e++){const o=t[e];o!==this&&("positionX"in o&&"positionY"in o&&"positionZ"in o&&(o.positionX=this.positionX,o.positionY=this.positionY,o.positionZ=this.positionZ),!this.bodyParams.stopRotation&&"rotationX"in o&&"rotationY"in o&&"rotationZ"in o&&(o.rotationX=this.rotationX,o.rotationY=this.rotationY,o.rotationZ=this.rotationZ))}}}class r{create(t){const{bodyParams:e}=t,o=e.type??exports.Physics3DType.BOX,i=e.mass??1,n=e.bodyOptions??{};let r;switch(o){case exports.Physics3DType.SPHERE:{const t=e.radius??.5;r=new s.Sphere(t);break}case exports.Physics3DType.CYLINDER:{const t=e.radiusTop??e.radius??.5,o=e.radiusBottom??e.radius??.5,i=e.height??1,n=e.segments??16;r=new s.Cylinder(t,o,i,n);break}case exports.Physics3DType.PLANE:r=new s.Plane;break;case exports.Physics3DType.BOX:default:{const t=e.width??1,o=e.height??1,i=e.depth??1;r=new s.Box(new s.Vec3(t/2,o/2,i/2));break}}const a=new s.Body({mass:o===exports.Physics3DType.PLANE?0:i,shape:r}),d=e.position;d&&a.position.set(d.x??0,d.y??0,d.z??0);const h=e.rotation;return h&&a.quaternion.setFromEuler(h.x??0,h.y??0,h.z??0),void 0!==n.friction&&(a.material=new s.Material({friction:n.friction,restitution:n.restitution??.3})),void 0===n.restitution||a.material||(a.material=new s.Material({friction:.3,restitution:n.restitution})),void 0!==n.linearDamping&&(a.linearDamping=n.linearDamping),void 0!==n.angularDamping&&(a.angularDamping=n.angularDamping),void 0!==n.fixedRotation&&(a.fixedRotation=n.fixedRotation),a.updateMassProperties(),a}}class a{constructor(t,e){this.enabled=!1,this.game=t,this.options=e,this.bodiesFactory=new r}start(){this.world=new s.World;const t=this.options.gravity??{x:0,y:-9.82,z:0};if(this.world.gravity.set(t.x,t.y,t.z),this.options.solver){const t=this.world.solver;void 0!==this.options.solver.iterations&&(t.iterations=this.options.solver.iterations),void 0!==this.options.solver.tolerance&&(t.tolerance=this.options.solver.tolerance)}this.world.broadphase=new s.NaiveBroadphase,this.world.allowSleep=this.options.allowSleep??!1,this.enabled=!0,this.initCollisionEvents()}update(t){if(!this.world||!this.enabled)return;const e=this.options.fixedTimeStep??1/60,o=this.options.maxSubSteps??3,i=(t.deltaTime||16.67)/1e3;this.world.step(e,i,o)}stop(){this.enabled=!1}awake(){this.enabled=!0}destroy(){if(this.world){for(;this.world.bodies.length>0;)this.world.removeBody(this.world.bodies[0]);this.world=null}}add(t){const e=this.bodiesFactory.create(t);this.world.addBody(e),t.body=e,t.world=this.world,e.component=t}change(t){t.body&&this.world.removeBody(t.body);const e=this.bodiesFactory.create(t);this.world.addBody(e),t.body=e,e.component=t}remove(t){t.body&&(this.world.removeBody(t.body),t.body=void 0)}initCollisionEvents(){this.world.addEventListener("beginContact",t=>{const e=t.bodyA,o=t.bodyB,i=e.component,s=o.component;i&&s&&(i.emit("collisionStart",s.gameObject,i.gameObject),s.emit("collisionStart",i.gameObject,s.gameObject))}),this.world.addEventListener("endContact",t=>{const e=t.bodyA,o=t.bodyB,i=e.component,s=o.component;i&&s&&(i.emit("collisionEnd",s.gameObject,i.gameObject),s.emit("collisionEnd",i.gameObject,s.gameObject))})}}let d=class extends e.System{static{this.systemName="Physics3DSystem"}init(t){this.engine=new a(this.game,t)}awake(){}start(){this.engine.start()}update(t){const e=this.componentObserver.clear();for(const t of e)t&&this.componentChanged(t);this.engine.update(t)}componentChanged(t){if(t.component instanceof n)switch(t.type){case e.OBSERVER_TYPE.ADD:t.gameObject.transform.parent&&!t.gameObject.getComponent(n).body&&this.engine.add(t.component);break;case e.OBSERVER_TYPE.CHANGE:this.engine.change(t.component);case e.OBSERVER_TYPE.REMOVE:}else if(t.type===e.OBSERVER_TYPE.CHANGE)if(t.component.parent){let e=t.gameObject.getComponent(n);e&&!e.body&&this.engine.add(e)}else{let e=t.gameObject.getComponent(n);e&&this.engine.remove(e)}}lateUpdate(){}onResume(){this.engine.enabled||this.engine.awake()}onPause(){this.engine.stop()}onDestroy(){this.engine?.destroy()}};d=t.__decorate([e.decorators.componentObserver({Physics3D:[{prop:["bodyParams"],deep:!0}],Transform:["_parent"]})],d);var h=d;exports.Physics3D=n,exports.Physics3DSystem=h;
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { System, ComponentChanged, Component } from '@combos-fun/engine';
|
|
2
|
+
import * as CANNON from 'cannon-es';
|
|
3
|
+
|
|
4
|
+
interface Physics3DSystemParams {
|
|
5
|
+
gravity?: {
|
|
6
|
+
x: number;
|
|
7
|
+
y: number;
|
|
8
|
+
z: number;
|
|
9
|
+
};
|
|
10
|
+
fixedTimeStep?: number;
|
|
11
|
+
maxSubSteps?: number;
|
|
12
|
+
allowSleep?: boolean;
|
|
13
|
+
solver?: {
|
|
14
|
+
iterations?: number;
|
|
15
|
+
tolerance?: number;
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
declare class Physics3DSystem extends System<Physics3DSystemParams> {
|
|
19
|
+
static systemName: string;
|
|
20
|
+
private engine;
|
|
21
|
+
init(param?: Physics3DSystemParams): void;
|
|
22
|
+
awake(): void;
|
|
23
|
+
start(): void;
|
|
24
|
+
update(e: any): void;
|
|
25
|
+
componentChanged(changed: ComponentChanged): void;
|
|
26
|
+
lateUpdate(): void;
|
|
27
|
+
onResume(): void;
|
|
28
|
+
onPause(): void;
|
|
29
|
+
onDestroy(): void;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
declare enum Physics3DType {
|
|
33
|
+
BOX = "box",
|
|
34
|
+
SPHERE = "sphere",
|
|
35
|
+
CYLINDER = "cylinder",
|
|
36
|
+
PLANE = "plane"
|
|
37
|
+
}
|
|
38
|
+
interface Physics3DParams {
|
|
39
|
+
type?: Physics3DType;
|
|
40
|
+
mass?: number;
|
|
41
|
+
bodyOptions?: {
|
|
42
|
+
friction?: number;
|
|
43
|
+
restitution?: number;
|
|
44
|
+
linearDamping?: number;
|
|
45
|
+
angularDamping?: number;
|
|
46
|
+
fixedRotation?: boolean;
|
|
47
|
+
[propName: string]: any;
|
|
48
|
+
};
|
|
49
|
+
position?: {
|
|
50
|
+
x?: number;
|
|
51
|
+
y?: number;
|
|
52
|
+
z?: number;
|
|
53
|
+
};
|
|
54
|
+
rotation?: {
|
|
55
|
+
x?: number;
|
|
56
|
+
y?: number;
|
|
57
|
+
z?: number;
|
|
58
|
+
};
|
|
59
|
+
width?: number;
|
|
60
|
+
height?: number;
|
|
61
|
+
depth?: number;
|
|
62
|
+
radius?: number;
|
|
63
|
+
radiusTop?: number;
|
|
64
|
+
radiusBottom?: number;
|
|
65
|
+
segments?: number;
|
|
66
|
+
stopRotation?: boolean;
|
|
67
|
+
}
|
|
68
|
+
declare class Physics3D extends Component<Physics3DParams> {
|
|
69
|
+
static componentName: string;
|
|
70
|
+
bodyParams: Physics3DParams;
|
|
71
|
+
body: CANNON.Body;
|
|
72
|
+
private world;
|
|
73
|
+
positionX: number;
|
|
74
|
+
positionY: number;
|
|
75
|
+
positionZ: number;
|
|
76
|
+
rotationX: number;
|
|
77
|
+
rotationY: number;
|
|
78
|
+
rotationZ: number;
|
|
79
|
+
private _euler;
|
|
80
|
+
init(params: Physics3DParams): void;
|
|
81
|
+
update(): void;
|
|
82
|
+
onDestroy(): void;
|
|
83
|
+
private _syncToSiblings;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export { Physics3D, Physics3DSystem, Physics3DType };
|
|
87
|
+
export type { Physics3DParams, Physics3DSystemParams };
|
|
@@ -0,0 +1,315 @@
|
|
|
1
|
+
import { __decorate } from 'tslib';
|
|
2
|
+
import { Component, System, OBSERVER_TYPE, decorators } from '@combos-fun/engine';
|
|
3
|
+
import * as CANNON from 'cannon-es';
|
|
4
|
+
|
|
5
|
+
var Physics3DType;
|
|
6
|
+
(function (Physics3DType) {
|
|
7
|
+
Physics3DType["BOX"] = "box";
|
|
8
|
+
Physics3DType["SPHERE"] = "sphere";
|
|
9
|
+
Physics3DType["CYLINDER"] = "cylinder";
|
|
10
|
+
Physics3DType["PLANE"] = "plane";
|
|
11
|
+
})(Physics3DType || (Physics3DType = {}));
|
|
12
|
+
class Physics3D extends Component {
|
|
13
|
+
constructor() {
|
|
14
|
+
super(...arguments);
|
|
15
|
+
// Readable position/rotation synced from body each frame
|
|
16
|
+
this.positionX = 0;
|
|
17
|
+
this.positionY = 0;
|
|
18
|
+
this.positionZ = 0;
|
|
19
|
+
this.rotationX = 0;
|
|
20
|
+
this.rotationY = 0;
|
|
21
|
+
this.rotationZ = 0;
|
|
22
|
+
this._euler = new CANNON.Vec3();
|
|
23
|
+
}
|
|
24
|
+
static { this.componentName = 'Physics3D'; }
|
|
25
|
+
init(params) {
|
|
26
|
+
this.bodyParams = params;
|
|
27
|
+
}
|
|
28
|
+
update() {
|
|
29
|
+
if (this.body && this.gameObject) {
|
|
30
|
+
// Sync position from Cannon body
|
|
31
|
+
this.positionX = this.body.position.x;
|
|
32
|
+
this.positionY = this.body.position.y;
|
|
33
|
+
this.positionZ = this.body.position.z;
|
|
34
|
+
// Convert quaternion to Euler and sync rotation
|
|
35
|
+
if (!this.bodyParams.stopRotation) {
|
|
36
|
+
this.body.quaternion.toEuler(this._euler);
|
|
37
|
+
this.rotationX = this._euler.x;
|
|
38
|
+
this.rotationY = this._euler.y;
|
|
39
|
+
this.rotationZ = this._euler.z;
|
|
40
|
+
}
|
|
41
|
+
// Auto-sync to sibling 3D render components on the same GameObject
|
|
42
|
+
this._syncToSiblings();
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
onDestroy() {
|
|
46
|
+
if (this.world && this.body) {
|
|
47
|
+
this.world.removeBody(this.body);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
_syncToSiblings() {
|
|
51
|
+
const components = this.gameObject.components;
|
|
52
|
+
if (!components)
|
|
53
|
+
return;
|
|
54
|
+
for (let i = 0; i < components.length; i++) {
|
|
55
|
+
const comp = components[i];
|
|
56
|
+
if (comp === this)
|
|
57
|
+
continue;
|
|
58
|
+
if ('positionX' in comp && 'positionY' in comp && 'positionZ' in comp) {
|
|
59
|
+
comp.positionX = this.positionX;
|
|
60
|
+
comp.positionY = this.positionY;
|
|
61
|
+
comp.positionZ = this.positionZ;
|
|
62
|
+
}
|
|
63
|
+
if (!this.bodyParams.stopRotation && 'rotationX' in comp && 'rotationY' in comp && 'rotationZ' in comp) {
|
|
64
|
+
comp.rotationX = this.rotationX;
|
|
65
|
+
comp.rotationY = this.rotationY;
|
|
66
|
+
comp.rotationZ = this.rotationZ;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
class BodiesFactory {
|
|
73
|
+
create(component) {
|
|
74
|
+
const { bodyParams } = component;
|
|
75
|
+
const type = bodyParams.type ?? Physics3DType.BOX;
|
|
76
|
+
const mass = bodyParams.mass ?? 1;
|
|
77
|
+
const options = bodyParams.bodyOptions ?? {};
|
|
78
|
+
// Create shape
|
|
79
|
+
let shape;
|
|
80
|
+
switch (type) {
|
|
81
|
+
case Physics3DType.SPHERE: {
|
|
82
|
+
const radius = bodyParams.radius ?? 0.5;
|
|
83
|
+
shape = new CANNON.Sphere(radius);
|
|
84
|
+
break;
|
|
85
|
+
}
|
|
86
|
+
case Physics3DType.CYLINDER: {
|
|
87
|
+
const radiusTop = bodyParams.radiusTop ?? bodyParams.radius ?? 0.5;
|
|
88
|
+
const radiusBottom = bodyParams.radiusBottom ?? bodyParams.radius ?? 0.5;
|
|
89
|
+
const height = bodyParams.height ?? 1;
|
|
90
|
+
const segments = bodyParams.segments ?? 16;
|
|
91
|
+
shape = new CANNON.Cylinder(radiusTop, radiusBottom, height, segments);
|
|
92
|
+
break;
|
|
93
|
+
}
|
|
94
|
+
case Physics3DType.PLANE: {
|
|
95
|
+
shape = new CANNON.Plane();
|
|
96
|
+
break;
|
|
97
|
+
}
|
|
98
|
+
case Physics3DType.BOX:
|
|
99
|
+
default: {
|
|
100
|
+
const w = bodyParams.width ?? 1;
|
|
101
|
+
const h = bodyParams.height ?? 1;
|
|
102
|
+
const d = bodyParams.depth ?? 1;
|
|
103
|
+
shape = new CANNON.Box(new CANNON.Vec3(w / 2, h / 2, d / 2));
|
|
104
|
+
break;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
// Create body
|
|
108
|
+
const body = new CANNON.Body({
|
|
109
|
+
mass: type === Physics3DType.PLANE ? 0 : mass,
|
|
110
|
+
shape,
|
|
111
|
+
});
|
|
112
|
+
// Set position
|
|
113
|
+
const pos = bodyParams.position;
|
|
114
|
+
if (pos) {
|
|
115
|
+
body.position.set(pos.x ?? 0, pos.y ?? 0, pos.z ?? 0);
|
|
116
|
+
}
|
|
117
|
+
// Set rotation (Euler to quaternion)
|
|
118
|
+
const rot = bodyParams.rotation;
|
|
119
|
+
if (rot) {
|
|
120
|
+
body.quaternion.setFromEuler(rot.x ?? 0, rot.y ?? 0, rot.z ?? 0);
|
|
121
|
+
}
|
|
122
|
+
// Apply body options
|
|
123
|
+
if (options.friction !== undefined)
|
|
124
|
+
body.material = new CANNON.Material({ friction: options.friction, restitution: options.restitution ?? 0.3 });
|
|
125
|
+
if (options.restitution !== undefined && !body.material)
|
|
126
|
+
body.material = new CANNON.Material({ friction: 0.3, restitution: options.restitution });
|
|
127
|
+
if (options.linearDamping !== undefined)
|
|
128
|
+
body.linearDamping = options.linearDamping;
|
|
129
|
+
if (options.angularDamping !== undefined)
|
|
130
|
+
body.angularDamping = options.angularDamping;
|
|
131
|
+
if (options.fixedRotation !== undefined)
|
|
132
|
+
body.fixedRotation = options.fixedRotation;
|
|
133
|
+
body.updateMassProperties();
|
|
134
|
+
return body;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
class Physics3DEngine {
|
|
139
|
+
constructor(game, options) {
|
|
140
|
+
this.enabled = false;
|
|
141
|
+
this.game = game;
|
|
142
|
+
this.options = options;
|
|
143
|
+
this.bodiesFactory = new BodiesFactory();
|
|
144
|
+
}
|
|
145
|
+
start() {
|
|
146
|
+
this.world = new CANNON.World();
|
|
147
|
+
// Set gravity
|
|
148
|
+
const gravity = this.options.gravity ?? { x: 0, y: -9.82, z: 0 };
|
|
149
|
+
this.world.gravity.set(gravity.x, gravity.y, gravity.z);
|
|
150
|
+
// Configure solver
|
|
151
|
+
if (this.options.solver) {
|
|
152
|
+
const solver = this.world.solver;
|
|
153
|
+
if (this.options.solver.iterations !== undefined) {
|
|
154
|
+
solver.iterations = this.options.solver.iterations;
|
|
155
|
+
}
|
|
156
|
+
if (this.options.solver.tolerance !== undefined) {
|
|
157
|
+
solver.tolerance = this.options.solver.tolerance;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
this.world.broadphase = new CANNON.NaiveBroadphase();
|
|
161
|
+
this.world.allowSleep = this.options.allowSleep ?? false;
|
|
162
|
+
this.enabled = true;
|
|
163
|
+
this.initCollisionEvents();
|
|
164
|
+
}
|
|
165
|
+
update(e) {
|
|
166
|
+
if (!this.world || !this.enabled)
|
|
167
|
+
return;
|
|
168
|
+
const fixedTimeStep = this.options.fixedTimeStep ?? 1 / 60;
|
|
169
|
+
const maxSubSteps = this.options.maxSubSteps ?? 3;
|
|
170
|
+
const dt = (e.deltaTime || 16.67) / 1000;
|
|
171
|
+
this.world.step(fixedTimeStep, dt, maxSubSteps);
|
|
172
|
+
}
|
|
173
|
+
stop() {
|
|
174
|
+
this.enabled = false;
|
|
175
|
+
}
|
|
176
|
+
awake() {
|
|
177
|
+
this.enabled = true;
|
|
178
|
+
}
|
|
179
|
+
destroy() {
|
|
180
|
+
if (this.world) {
|
|
181
|
+
// Remove all bodies
|
|
182
|
+
while (this.world.bodies.length > 0) {
|
|
183
|
+
this.world.removeBody(this.world.bodies[0]);
|
|
184
|
+
}
|
|
185
|
+
this.world = null;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
add(component) {
|
|
189
|
+
const body = this.bodiesFactory.create(component);
|
|
190
|
+
this.world.addBody(body);
|
|
191
|
+
// Inject references into component
|
|
192
|
+
component.body = body;
|
|
193
|
+
component.world = this.world;
|
|
194
|
+
// Back-link for collision event lookup
|
|
195
|
+
body.component = component;
|
|
196
|
+
}
|
|
197
|
+
change(component) {
|
|
198
|
+
// Remove old body, create and add new one
|
|
199
|
+
if (component.body) {
|
|
200
|
+
this.world.removeBody(component.body);
|
|
201
|
+
}
|
|
202
|
+
const newBody = this.bodiesFactory.create(component);
|
|
203
|
+
this.world.addBody(newBody);
|
|
204
|
+
component.body = newBody;
|
|
205
|
+
newBody.component = component;
|
|
206
|
+
}
|
|
207
|
+
remove(component) {
|
|
208
|
+
if (component.body) {
|
|
209
|
+
this.world.removeBody(component.body);
|
|
210
|
+
component.body = undefined;
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
initCollisionEvents() {
|
|
214
|
+
// beginContact: emitted when two bodies start touching
|
|
215
|
+
this.world.addEventListener('beginContact', (event) => {
|
|
216
|
+
const bodyA = event.bodyA;
|
|
217
|
+
const bodyB = event.bodyB;
|
|
218
|
+
const componentA = bodyA.component;
|
|
219
|
+
const componentB = bodyB.component;
|
|
220
|
+
if (componentA && componentB) {
|
|
221
|
+
componentA.emit('collisionStart', componentB.gameObject, componentA.gameObject);
|
|
222
|
+
componentB.emit('collisionStart', componentA.gameObject, componentB.gameObject);
|
|
223
|
+
}
|
|
224
|
+
});
|
|
225
|
+
// endContact: emitted when two bodies stop touching
|
|
226
|
+
this.world.addEventListener('endContact', (event) => {
|
|
227
|
+
const bodyA = event.bodyA;
|
|
228
|
+
const bodyB = event.bodyB;
|
|
229
|
+
const componentA = bodyA.component;
|
|
230
|
+
const componentB = bodyB.component;
|
|
231
|
+
if (componentA && componentB) {
|
|
232
|
+
componentA.emit('collisionEnd', componentB.gameObject, componentA.gameObject);
|
|
233
|
+
componentB.emit('collisionEnd', componentA.gameObject, componentB.gameObject);
|
|
234
|
+
}
|
|
235
|
+
});
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
let Physics3DSystem = class Physics3DSystem extends System {
|
|
240
|
+
static { this.systemName = 'Physics3DSystem'; }
|
|
241
|
+
init(param) {
|
|
242
|
+
this.engine = new Physics3DEngine(this.game, param);
|
|
243
|
+
}
|
|
244
|
+
awake() { }
|
|
245
|
+
start() {
|
|
246
|
+
this.engine.start();
|
|
247
|
+
}
|
|
248
|
+
update(e) {
|
|
249
|
+
const changes = this.componentObserver.clear();
|
|
250
|
+
for (const changed of changes) {
|
|
251
|
+
if (changed) {
|
|
252
|
+
this.componentChanged(changed);
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
this.engine.update(e);
|
|
256
|
+
}
|
|
257
|
+
componentChanged(changed) {
|
|
258
|
+
if (changed.component instanceof Physics3D) {
|
|
259
|
+
switch (changed.type) {
|
|
260
|
+
case OBSERVER_TYPE.ADD: {
|
|
261
|
+
if (changed.gameObject.transform.parent && !changed.gameObject.getComponent(Physics3D).body) {
|
|
262
|
+
this.engine.add(changed.component);
|
|
263
|
+
}
|
|
264
|
+
break;
|
|
265
|
+
}
|
|
266
|
+
case OBSERVER_TYPE.CHANGE: {
|
|
267
|
+
this.engine.change(changed.component);
|
|
268
|
+
break;
|
|
269
|
+
}
|
|
270
|
+
case OBSERVER_TYPE.REMOVE: {
|
|
271
|
+
break;
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
else {
|
|
276
|
+
// Transform._parent change
|
|
277
|
+
switch (changed.type) {
|
|
278
|
+
case OBSERVER_TYPE.CHANGE: {
|
|
279
|
+
if (changed.component.parent) {
|
|
280
|
+
let physics = changed.gameObject.getComponent(Physics3D);
|
|
281
|
+
if (physics && !physics.body) {
|
|
282
|
+
this.engine.add(physics);
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
else {
|
|
286
|
+
let physics = changed.gameObject.getComponent(Physics3D);
|
|
287
|
+
physics && this.engine.remove(physics);
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
lateUpdate() { }
|
|
294
|
+
onResume() {
|
|
295
|
+
if (!this.engine.enabled) {
|
|
296
|
+
this.engine.awake();
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
onPause() {
|
|
300
|
+
this.engine.stop();
|
|
301
|
+
}
|
|
302
|
+
onDestroy() {
|
|
303
|
+
this.engine?.destroy();
|
|
304
|
+
}
|
|
305
|
+
};
|
|
306
|
+
Physics3DSystem = __decorate([
|
|
307
|
+
decorators.componentObserver({
|
|
308
|
+
Physics3D: [{ prop: ['bodyParams'], deep: true }],
|
|
309
|
+
Transform: ['_parent'],
|
|
310
|
+
})
|
|
311
|
+
], Physics3DSystem);
|
|
312
|
+
var Physics3DSystem_default = Physics3DSystem;
|
|
313
|
+
|
|
314
|
+
export { Physics3D, Physics3DSystem_default as Physics3DSystem, Physics3DType };
|
|
315
|
+
//# sourceMappingURL=plugin-cannon.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin-cannon.esm.js","sources":["../lib/Physics3D.ts","../lib/BodiesFactory.ts","../lib/Physics3DEngine.ts","../lib/Physics3DSystem.ts"],"sourcesContent":["import { Component } from '@combos-fun/engine';\nimport * as CANNON from 'cannon-es';\n\nexport enum Physics3DType {\n BOX = 'box',\n SPHERE = 'sphere',\n CYLINDER = 'cylinder',\n PLANE = 'plane',\n}\n\nexport interface Physics3DParams {\n type?: Physics3DType\n mass?: number\n bodyOptions?: {\n friction?: number\n restitution?: number\n linearDamping?: number\n angularDamping?: number\n fixedRotation?: boolean\n [propName: string]: any\n }\n position?: {\n x?: number\n y?: number\n z?: number\n }\n rotation?: {\n x?: number\n y?: number\n z?: number\n }\n width?: number\n height?: number\n depth?: number\n radius?: number\n radiusTop?: number\n radiusBottom?: number\n segments?: number\n stopRotation?: boolean\n}\n\nexport class Physics3D extends Component<Physics3DParams> {\n static componentName: string = 'Physics3D';\n public bodyParams: Physics3DParams;\n public body: CANNON.Body;\n private world: CANNON.World;\n\n // Readable position/rotation synced from body each frame\n public positionX: number = 0;\n public positionY: number = 0;\n public positionZ: number = 0;\n public rotationX: number = 0;\n public rotationY: number = 0;\n public rotationZ: number = 0;\n\n private _euler: CANNON.Vec3 = new CANNON.Vec3();\n\n init(params: Physics3DParams) {\n this.bodyParams = params;\n }\n\n update() {\n if (this.body && this.gameObject) {\n // Sync position from Cannon body\n this.positionX = this.body.position.x;\n this.positionY = this.body.position.y;\n this.positionZ = this.body.position.z;\n\n // Convert quaternion to Euler and sync rotation\n if (!this.bodyParams.stopRotation) {\n this.body.quaternion.toEuler(this._euler);\n this.rotationX = this._euler.x;\n this.rotationY = this._euler.y;\n this.rotationZ = this._euler.z;\n }\n\n // Auto-sync to sibling 3D render components on the same GameObject\n this._syncToSiblings();\n }\n }\n\n onDestroy() {\n if (this.world && this.body) {\n this.world.removeBody(this.body);\n }\n }\n\n private _syncToSiblings() {\n const components = this.gameObject.components;\n if (!components) return;\n for (let i = 0; i < components.length; i++) {\n const comp = components[i] as any;\n if (comp === this) continue;\n if ('positionX' in comp && 'positionY' in comp && 'positionZ' in comp) {\n comp.positionX = this.positionX;\n comp.positionY = this.positionY;\n comp.positionZ = this.positionZ;\n }\n if (!this.bodyParams.stopRotation && 'rotationX' in comp && 'rotationY' in comp && 'rotationZ' in comp) {\n comp.rotationX = this.rotationX;\n comp.rotationY = this.rotationY;\n comp.rotationZ = this.rotationZ;\n }\n }\n }\n}\n","import * as CANNON from 'cannon-es';\nimport { Physics3DType } from './Physics3D';\nimport type { Physics3D } from './Physics3D';\n\nexport default class BodiesFactory {\n public create(component: Physics3D): CANNON.Body {\n const { bodyParams } = component;\n const type = bodyParams.type ?? Physics3DType.BOX;\n const mass = bodyParams.mass ?? 1;\n const options = bodyParams.bodyOptions ?? {};\n\n // Create shape\n let shape: CANNON.Shape;\n switch (type) {\n case Physics3DType.SPHERE: {\n const radius = bodyParams.radius ?? 0.5;\n shape = new CANNON.Sphere(radius);\n break;\n }\n case Physics3DType.CYLINDER: {\n const radiusTop = bodyParams.radiusTop ?? bodyParams.radius ?? 0.5;\n const radiusBottom = bodyParams.radiusBottom ?? bodyParams.radius ?? 0.5;\n const height = bodyParams.height ?? 1;\n const segments = bodyParams.segments ?? 16;\n shape = new CANNON.Cylinder(radiusTop, radiusBottom, height, segments);\n break;\n }\n case Physics3DType.PLANE: {\n shape = new CANNON.Plane();\n break;\n }\n case Physics3DType.BOX:\n default: {\n const w = bodyParams.width ?? 1;\n const h = bodyParams.height ?? 1;\n const d = bodyParams.depth ?? 1;\n shape = new CANNON.Box(new CANNON.Vec3(w / 2, h / 2, d / 2));\n break;\n }\n }\n\n // Create body\n const body = new CANNON.Body({\n mass: type === Physics3DType.PLANE ? 0 : mass,\n shape,\n });\n\n // Set position\n const pos = bodyParams.position;\n if (pos) {\n body.position.set(pos.x ?? 0, pos.y ?? 0, pos.z ?? 0);\n }\n\n // Set rotation (Euler to quaternion)\n const rot = bodyParams.rotation;\n if (rot) {\n body.quaternion.setFromEuler(rot.x ?? 0, rot.y ?? 0, rot.z ?? 0);\n }\n\n // Apply body options\n if (options.friction !== undefined) body.material = new CANNON.Material({ friction: options.friction, restitution: options.restitution ?? 0.3 });\n if (options.restitution !== undefined && !body.material) body.material = new CANNON.Material({ friction: 0.3, restitution: options.restitution });\n if (options.linearDamping !== undefined) body.linearDamping = options.linearDamping;\n if (options.angularDamping !== undefined) body.angularDamping = options.angularDamping;\n if (options.fixedRotation !== undefined) body.fixedRotation = options.fixedRotation;\n body.updateMassProperties();\n\n return body;\n }\n}\n","import * as CANNON from 'cannon-es';\nimport BodiesFactory from './BodiesFactory';\nimport type { Component, Game } from '@combos-fun/engine';\nimport type { Physics3DSystemParams } from './Physics3DSystem';\nimport type { Physics3D } from './Physics3D';\n\ninterface PhysicsLinkedBody extends CANNON.Body {\n component?: Physics3D;\n}\n\nexport default class Physics3DEngine {\n private world: CANNON.World;\n private bodiesFactory: BodiesFactory;\n private options: Physics3DSystemParams;\n private game: Game;\n public enabled: boolean = false;\n\n constructor(game: Game, options: Physics3DSystemParams) {\n this.game = game;\n this.options = options;\n this.bodiesFactory = new BodiesFactory();\n }\n\n public start() {\n this.world = new CANNON.World();\n\n // Set gravity\n const gravity = this.options.gravity ?? { x: 0, y: -9.82, z: 0 };\n this.world.gravity.set(gravity.x, gravity.y, gravity.z);\n\n // Configure solver\n if (this.options.solver) {\n const solver = this.world.solver as CANNON.GSSolver;\n if (this.options.solver.iterations !== undefined) {\n solver.iterations = this.options.solver.iterations;\n }\n if (this.options.solver.tolerance !== undefined) {\n solver.tolerance = this.options.solver.tolerance;\n }\n }\n\n this.world.broadphase = new CANNON.NaiveBroadphase();\n this.world.allowSleep = this.options.allowSleep ?? false;\n\n this.enabled = true;\n this.initCollisionEvents();\n }\n\n public update(e) {\n if (!this.world || !this.enabled) return;\n const fixedTimeStep = this.options.fixedTimeStep ?? 1 / 60;\n const maxSubSteps = this.options.maxSubSteps ?? 3;\n const dt = (e.deltaTime || 16.67) / 1000;\n this.world.step(fixedTimeStep, dt, maxSubSteps);\n }\n\n public stop() {\n this.enabled = false;\n }\n\n public awake() {\n this.enabled = true;\n }\n\n public destroy() {\n if (this.world) {\n // Remove all bodies\n while (this.world.bodies.length > 0) {\n this.world.removeBody(this.world.bodies[0]);\n }\n this.world = null;\n }\n }\n\n public add(component: Physics3D) {\n const body = this.bodiesFactory.create(component) as PhysicsLinkedBody;\n this.world.addBody(body);\n\n // Inject references into component\n component.body = body;\n (component as any).world = this.world;\n\n // Back-link for collision event lookup\n body.component = component;\n }\n\n public change(component: Physics3D) {\n // Remove old body, create and add new one\n if (component.body) {\n this.world.removeBody(component.body);\n }\n const newBody = this.bodiesFactory.create(component) as PhysicsLinkedBody;\n this.world.addBody(newBody);\n component.body = newBody;\n newBody.component = component;\n }\n\n public remove(component: Physics3D) {\n if (component.body) {\n this.world.removeBody(component.body);\n component.body = undefined;\n }\n }\n\n private initCollisionEvents() {\n // beginContact: emitted when two bodies start touching\n this.world.addEventListener('beginContact', (event: any) => {\n const bodyA = event.bodyA as PhysicsLinkedBody;\n const bodyB = event.bodyB as PhysicsLinkedBody;\n const componentA: Component = bodyA.component;\n const componentB: Component = bodyB.component;\n if (componentA && componentB) {\n componentA.emit('collisionStart', componentB.gameObject, componentA.gameObject);\n componentB.emit('collisionStart', componentA.gameObject, componentB.gameObject);\n }\n });\n\n // endContact: emitted when two bodies stop touching\n this.world.addEventListener('endContact', (event: any) => {\n const bodyA = event.bodyA as PhysicsLinkedBody;\n const bodyB = event.bodyB as PhysicsLinkedBody;\n const componentA: Component = bodyA.component;\n const componentB: Component = bodyB.component;\n if (componentA && componentB) {\n componentA.emit('collisionEnd', componentB.gameObject, componentA.gameObject);\n componentB.emit('collisionEnd', componentA.gameObject, componentB.gameObject);\n }\n });\n }\n}\n","import { System, decorators, OBSERVER_TYPE, Transform } from '@combos-fun/engine';\nimport type { ComponentChanged } from '@combos-fun/engine';\nimport Physics3DEngine from './Physics3DEngine';\nimport { Physics3D } from './Physics3D';\n\nexport interface Physics3DSystemParams {\n gravity?: {\n x: number\n y: number\n z: number\n }\n fixedTimeStep?: number\n maxSubSteps?: number\n allowSleep?: boolean\n solver?: {\n iterations?: number\n tolerance?: number\n }\n}\n\n@decorators.componentObserver({\n Physics3D: [{ prop: ['bodyParams'], deep: true }],\n Transform: ['_parent'],\n})\nexport default class Physics3DSystem extends System<Physics3DSystemParams> {\n static systemName = 'Physics3DSystem';\n private engine: Physics3DEngine;\n\n init(param?: Physics3DSystemParams) {\n this.engine = new Physics3DEngine(this.game, param);\n }\n\n awake() { }\n\n start() {\n this.engine.start();\n }\n\n update(e) {\n const changes = this.componentObserver.clear();\n for (const changed of changes) {\n if (changed) {\n this.componentChanged(changed);\n }\n }\n this.engine.update(e);\n }\n\n componentChanged(changed: ComponentChanged) {\n if (changed.component instanceof Physics3D) {\n switch (changed.type) {\n case OBSERVER_TYPE.ADD: {\n if (changed.gameObject.transform.parent && !changed.gameObject.getComponent(Physics3D).body) {\n this.engine.add(changed.component);\n }\n break;\n }\n case OBSERVER_TYPE.CHANGE: {\n this.engine.change(changed.component);\n break;\n }\n case OBSERVER_TYPE.REMOVE: {\n break;\n }\n }\n } else {\n // Transform._parent change\n switch (changed.type) {\n case OBSERVER_TYPE.CHANGE: {\n if ((changed.component as Transform).parent) {\n let physics = changed.gameObject.getComponent(Physics3D);\n if (physics && !physics.body) {\n this.engine.add(physics);\n }\n } else {\n let physics = changed.gameObject.getComponent(Physics3D);\n physics && this.engine.remove(physics);\n }\n }\n }\n }\n }\n\n lateUpdate() { }\n\n onResume() {\n if (!this.engine.enabled) {\n this.engine.awake();\n }\n }\n\n onPause() {\n this.engine.stop();\n }\n\n onDestroy() {\n this.engine?.destroy();\n }\n}\n"],"names":[],"mappings":";;;;IAGY;AAAZ,CAAA,UAAY,aAAa,EAAA;AACvB,IAAA,aAAA,CAAA,KAAA,CAAA,GAAA,KAAW;AACX,IAAA,aAAA,CAAA,QAAA,CAAA,GAAA,QAAiB;AACjB,IAAA,aAAA,CAAA,UAAA,CAAA,GAAA,UAAqB;AACrB,IAAA,aAAA,CAAA,OAAA,CAAA,GAAA,OAAe;AACjB,CAAC,EALW,aAAa,KAAb,aAAa,GAAA,EAAA,CAAA,CAAA;AAsCnB,MAAO,SAAU,SAAQ,SAA0B,CAAA;AAAzD,IAAA,WAAA,GAAA;;;QAOS,IAAA,CAAA,SAAS,GAAW,CAAC;QACrB,IAAA,CAAA,SAAS,GAAW,CAAC;QACrB,IAAA,CAAA,SAAS,GAAW,CAAC;QACrB,IAAA,CAAA,SAAS,GAAW,CAAC;QACrB,IAAA,CAAA,SAAS,GAAW,CAAC;QACrB,IAAA,CAAA,SAAS,GAAW,CAAC;AAEpB,QAAA,IAAA,CAAA,MAAM,GAAgB,IAAI,MAAM,CAAC,IAAI,EAAE;IAkDjD;aA/DS,IAAA,CAAA,aAAa,GAAW,WAAX,CAAuB;AAe3C,IAAA,IAAI,CAAC,MAAuB,EAAA;AAC1B,QAAA,IAAI,CAAC,UAAU,GAAG,MAAM;IAC1B;IAEA,MAAM,GAAA;QACJ,IAAI,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,UAAU,EAAE;;YAEhC,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YACrC,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YACrC,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;;AAGrC,YAAA,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,YAAY,EAAE;gBACjC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC;gBACzC,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC;gBAC9B,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC;gBAC9B,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC;YAChC;;YAGA,IAAI,CAAC,eAAe,EAAE;QACxB;IACF;IAEA,SAAS,GAAA;QACP,IAAI,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,IAAI,EAAE;YAC3B,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC;QAClC;IACF;IAEQ,eAAe,GAAA;AACrB,QAAA,MAAM,UAAU,GAAG,IAAI,CAAC,UAAU,CAAC,UAAU;AAC7C,QAAA,IAAI,CAAC,UAAU;YAAE;AACjB,QAAA,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,UAAU,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;AAC1C,YAAA,MAAM,IAAI,GAAG,UAAU,CAAC,CAAC,CAAQ;YACjC,IAAI,IAAI,KAAK,IAAI;gBAAE;AACnB,YAAA,IAAI,WAAW,IAAI,IAAI,IAAI,WAAW,IAAI,IAAI,IAAI,WAAW,IAAI,IAAI,EAAE;AACrE,gBAAA,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,SAAS;AAC/B,gBAAA,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,SAAS;AAC/B,gBAAA,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,SAAS;YACjC;AACA,YAAA,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,YAAY,IAAI,WAAW,IAAI,IAAI,IAAI,WAAW,IAAI,IAAI,IAAI,WAAW,IAAI,IAAI,EAAE;AACtG,gBAAA,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,SAAS;AAC/B,gBAAA,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,SAAS;AAC/B,gBAAA,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,SAAS;YACjC;QACF;IACF;;;ACpGY,MAAO,aAAa,CAAA;AACzB,IAAA,MAAM,CAAC,SAAoB,EAAA;AAChC,QAAA,MAAM,EAAE,UAAU,EAAE,GAAG,SAAS;QAChC,MAAM,IAAI,GAAG,UAAU,CAAC,IAAI,IAAI,aAAa,CAAC,GAAG;AACjD,QAAA,MAAM,IAAI,GAAG,UAAU,CAAC,IAAI,IAAI,CAAC;AACjC,QAAA,MAAM,OAAO,GAAG,UAAU,CAAC,WAAW,IAAI,EAAE;;AAG5C,QAAA,IAAI,KAAmB;QACvB,QAAQ,IAAI;AACV,YAAA,KAAK,aAAa,CAAC,MAAM,EAAE;AACzB,gBAAA,MAAM,MAAM,GAAG,UAAU,CAAC,MAAM,IAAI,GAAG;gBACvC,KAAK,GAAG,IAAI,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC;gBACjC;YACF;AACA,YAAA,KAAK,aAAa,CAAC,QAAQ,EAAE;gBAC3B,MAAM,SAAS,GAAG,UAAU,CAAC,SAAS,IAAI,UAAU,CAAC,MAAM,IAAI,GAAG;gBAClE,MAAM,YAAY,GAAG,UAAU,CAAC,YAAY,IAAI,UAAU,CAAC,MAAM,IAAI,GAAG;AACxE,gBAAA,MAAM,MAAM,GAAG,UAAU,CAAC,MAAM,IAAI,CAAC;AACrC,gBAAA,MAAM,QAAQ,GAAG,UAAU,CAAC,QAAQ,IAAI,EAAE;AAC1C,gBAAA,KAAK,GAAG,IAAI,MAAM,CAAC,QAAQ,CAAC,SAAS,EAAE,YAAY,EAAE,MAAM,EAAE,QAAQ,CAAC;gBACtE;YACF;AACA,YAAA,KAAK,aAAa,CAAC,KAAK,EAAE;AACxB,gBAAA,KAAK,GAAG,IAAI,MAAM,CAAC,KAAK,EAAE;gBAC1B;YACF;YACA,KAAK,aAAa,CAAC,GAAG;YACtB,SAAS;AACP,gBAAA,MAAM,CAAC,GAAG,UAAU,CAAC,KAAK,IAAI,CAAC;AAC/B,gBAAA,MAAM,CAAC,GAAG,UAAU,CAAC,MAAM,IAAI,CAAC;AAChC,gBAAA,MAAM,CAAC,GAAG,UAAU,CAAC,KAAK,IAAI,CAAC;gBAC/B,KAAK,GAAG,IAAI,MAAM,CAAC,GAAG,CAAC,IAAI,MAAM,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;gBAC5D;YACF;;;AAIF,QAAA,MAAM,IAAI,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC;AAC3B,YAAA,IAAI,EAAE,IAAI,KAAK,aAAa,CAAC,KAAK,GAAG,CAAC,GAAG,IAAI;YAC7C,KAAK;AACN,SAAA,CAAC;;AAGF,QAAA,MAAM,GAAG,GAAG,UAAU,CAAC,QAAQ;QAC/B,IAAI,GAAG,EAAE;YACP,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC;QACvD;;AAGA,QAAA,MAAM,GAAG,GAAG,UAAU,CAAC,QAAQ;QAC/B,IAAI,GAAG,EAAE;YACP,IAAI,CAAC,UAAU,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC;QAClE;;AAGA,QAAA,IAAI,OAAO,CAAC,QAAQ,KAAK,SAAS;YAAE,IAAI,CAAC,QAAQ,GAAG,IAAI,MAAM,CAAC,QAAQ,CAAC,EAAE,QAAQ,EAAE,OAAO,CAAC,QAAQ,EAAE,WAAW,EAAE,OAAO,CAAC,WAAW,IAAI,GAAG,EAAE,CAAC;QAChJ,IAAI,OAAO,CAAC,WAAW,KAAK,SAAS,IAAI,CAAC,IAAI,CAAC,QAAQ;YAAE,IAAI,CAAC,QAAQ,GAAG,IAAI,MAAM,CAAC,QAAQ,CAAC,EAAE,QAAQ,EAAE,GAAG,EAAE,WAAW,EAAE,OAAO,CAAC,WAAW,EAAE,CAAC;AACjJ,QAAA,IAAI,OAAO,CAAC,aAAa,KAAK,SAAS;AAAE,YAAA,IAAI,CAAC,aAAa,GAAG,OAAO,CAAC,aAAa;AACnF,QAAA,IAAI,OAAO,CAAC,cAAc,KAAK,SAAS;AAAE,YAAA,IAAI,CAAC,cAAc,GAAG,OAAO,CAAC,cAAc;AACtF,QAAA,IAAI,OAAO,CAAC,aAAa,KAAK,SAAS;AAAE,YAAA,IAAI,CAAC,aAAa,GAAG,OAAO,CAAC,aAAa;QACnF,IAAI,CAAC,oBAAoB,EAAE;AAE3B,QAAA,OAAO,IAAI;IACb;AACD;;AC3Da,MAAO,eAAe,CAAA;IAOlC,WAAA,CAAY,IAAU,EAAE,OAA8B,EAAA;QAF/C,IAAA,CAAA,OAAO,GAAY,KAAK;AAG7B,QAAA,IAAI,CAAC,IAAI,GAAG,IAAI;AAChB,QAAA,IAAI,CAAC,OAAO,GAAG,OAAO;AACtB,QAAA,IAAI,CAAC,aAAa,GAAG,IAAI,aAAa,EAAE;IAC1C;IAEO,KAAK,GAAA;QACV,IAAI,CAAC,KAAK,GAAG,IAAI,MAAM,CAAC,KAAK,EAAE;;QAG/B,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,IAAI,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,EAAE;AAChE,QAAA,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC;;AAGvD,QAAA,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE;AACvB,YAAA,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,MAAyB;YACnD,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,UAAU,KAAK,SAAS,EAAE;gBAChD,MAAM,CAAC,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,UAAU;YACpD;YACA,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,SAAS,KAAK,SAAS,EAAE;gBAC/C,MAAM,CAAC,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,SAAS;YAClD;QACF;QAEA,IAAI,CAAC,KAAK,CAAC,UAAU,GAAG,IAAI,MAAM,CAAC,eAAe,EAAE;AACpD,QAAA,IAAI,CAAC,KAAK,CAAC,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,IAAI,KAAK;AAExD,QAAA,IAAI,CAAC,OAAO,GAAG,IAAI;QACnB,IAAI,CAAC,mBAAmB,EAAE;IAC5B;AAEO,IAAA,MAAM,CAAC,CAAC,EAAA;QACb,IAAI,CAAC,IAAI,CAAC,KAAK,IAAI,CAAC,IAAI,CAAC,OAAO;YAAE;QAClC,MAAM,aAAa,GAAG,IAAI,CAAC,OAAO,CAAC,aAAa,IAAI,CAAC,GAAG,EAAE;QAC1D,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,CAAC,WAAW,IAAI,CAAC;QACjD,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC,SAAS,IAAI,KAAK,IAAI,IAAI;QACxC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,aAAa,EAAE,EAAE,EAAE,WAAW,CAAC;IACjD;IAEO,IAAI,GAAA;AACT,QAAA,IAAI,CAAC,OAAO,GAAG,KAAK;IACtB;IAEO,KAAK,GAAA;AACV,QAAA,IAAI,CAAC,OAAO,GAAG,IAAI;IACrB;IAEO,OAAO,GAAA;AACZ,QAAA,IAAI,IAAI,CAAC,KAAK,EAAE;;YAEd,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE;AACnC,gBAAA,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;YAC7C;AACA,YAAA,IAAI,CAAC,KAAK,GAAG,IAAI;QACnB;IACF;AAEO,IAAA,GAAG,CAAC,SAAoB,EAAA;QAC7B,MAAM,IAAI,GAAG,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,SAAS,CAAsB;AACtE,QAAA,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC;;AAGxB,QAAA,SAAS,CAAC,IAAI,GAAG,IAAI;AACpB,QAAA,SAAiB,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK;;AAGrC,QAAA,IAAI,CAAC,SAAS,GAAG,SAAS;IAC5B;AAEO,IAAA,MAAM,CAAC,SAAoB,EAAA;;AAEhC,QAAA,IAAI,SAAS,CAAC,IAAI,EAAE;YAClB,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,SAAS,CAAC,IAAI,CAAC;QACvC;QACA,MAAM,OAAO,GAAG,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,SAAS,CAAsB;AACzE,QAAA,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC;AAC3B,QAAA,SAAS,CAAC,IAAI,GAAG,OAAO;AACxB,QAAA,OAAO,CAAC,SAAS,GAAG,SAAS;IAC/B;AAEO,IAAA,MAAM,CAAC,SAAoB,EAAA;AAChC,QAAA,IAAI,SAAS,CAAC,IAAI,EAAE;YAClB,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,SAAS,CAAC,IAAI,CAAC;AACrC,YAAA,SAAS,CAAC,IAAI,GAAG,SAAS;QAC5B;IACF;IAEQ,mBAAmB,GAAA;;QAEzB,IAAI,CAAC,KAAK,CAAC,gBAAgB,CAAC,cAAc,EAAE,CAAC,KAAU,KAAI;AACzD,YAAA,MAAM,KAAK,GAAG,KAAK,CAAC,KAA0B;AAC9C,YAAA,MAAM,KAAK,GAAG,KAAK,CAAC,KAA0B;AAC9C,YAAA,MAAM,UAAU,GAAc,KAAK,CAAC,SAAS;AAC7C,YAAA,MAAM,UAAU,GAAc,KAAK,CAAC,SAAS;AAC7C,YAAA,IAAI,UAAU,IAAI,UAAU,EAAE;AAC5B,gBAAA,UAAU,CAAC,IAAI,CAAC,gBAAgB,EAAE,UAAU,CAAC,UAAU,EAAE,UAAU,CAAC,UAAU,CAAC;AAC/E,gBAAA,UAAU,CAAC,IAAI,CAAC,gBAAgB,EAAE,UAAU,CAAC,UAAU,EAAE,UAAU,CAAC,UAAU,CAAC;YACjF;AACF,QAAA,CAAC,CAAC;;QAGF,IAAI,CAAC,KAAK,CAAC,gBAAgB,CAAC,YAAY,EAAE,CAAC,KAAU,KAAI;AACvD,YAAA,MAAM,KAAK,GAAG,KAAK,CAAC,KAA0B;AAC9C,YAAA,MAAM,KAAK,GAAG,KAAK,CAAC,KAA0B;AAC9C,YAAA,MAAM,UAAU,GAAc,KAAK,CAAC,SAAS;AAC7C,YAAA,MAAM,UAAU,GAAc,KAAK,CAAC,SAAS;AAC7C,YAAA,IAAI,UAAU,IAAI,UAAU,EAAE;AAC5B,gBAAA,UAAU,CAAC,IAAI,CAAC,cAAc,EAAE,UAAU,CAAC,UAAU,EAAE,UAAU,CAAC,UAAU,CAAC;AAC7E,gBAAA,UAAU,CAAC,IAAI,CAAC,cAAc,EAAE,UAAU,CAAC,UAAU,EAAE,UAAU,CAAC,UAAU,CAAC;YAC/E;AACF,QAAA,CAAC,CAAC;IACJ;AACD;;ACzGc,IAAM,eAAe,GAArB,MAAM,eAAgB,SAAQ,MAA6B,CAAA;aACjE,IAAA,CAAA,UAAU,GAAG,iBAAH,CAAqB;AAGtC,IAAA,IAAI,CAAC,KAA6B,EAAA;AAChC,QAAA,IAAI,CAAC,MAAM,GAAG,IAAI,eAAe,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC;IACrD;AAEA,IAAA,KAAK,KAAK;IAEV,KAAK,GAAA;AACH,QAAA,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE;IACrB;AAEA,IAAA,MAAM,CAAC,CAAC,EAAA;QACN,MAAM,OAAO,GAAG,IAAI,CAAC,iBAAiB,CAAC,KAAK,EAAE;AAC9C,QAAA,KAAK,MAAM,OAAO,IAAI,OAAO,EAAE;YAC7B,IAAI,OAAO,EAAE;AACX,gBAAA,IAAI,CAAC,gBAAgB,CAAC,OAAO,CAAC;YAChC;QACF;AACA,QAAA,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC;IACvB;AAEA,IAAA,gBAAgB,CAAC,OAAyB,EAAA;AACxC,QAAA,IAAI,OAAO,CAAC,SAAS,YAAY,SAAS,EAAE;AAC1C,YAAA,QAAQ,OAAO,CAAC,IAAI;AAClB,gBAAA,KAAK,aAAa,CAAC,GAAG,EAAE;oBACtB,IAAI,OAAO,CAAC,UAAU,CAAC,SAAS,CAAC,MAAM,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,YAAY,CAAC,SAAS,CAAC,CAAC,IAAI,EAAE;wBAC3F,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,SAAS,CAAC;oBACpC;oBACA;gBACF;AACA,gBAAA,KAAK,aAAa,CAAC,MAAM,EAAE;oBACzB,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC;oBACrC;gBACF;AACA,gBAAA,KAAK,aAAa,CAAC,MAAM,EAAE;oBACzB;gBACF;;QAEJ;aAAO;;AAEL,YAAA,QAAQ,OAAO,CAAC,IAAI;AAClB,gBAAA,KAAK,aAAa,CAAC,MAAM,EAAE;AACzB,oBAAA,IAAK,OAAO,CAAC,SAAuB,CAAC,MAAM,EAAE;wBAC3C,IAAI,OAAO,GAAG,OAAO,CAAC,UAAU,CAAC,YAAY,CAAC,SAAS,CAAC;AACxD,wBAAA,IAAI,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE;AAC5B,4BAAA,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC;wBAC1B;oBACF;yBAAO;wBACL,IAAI,OAAO,GAAG,OAAO,CAAC,UAAU,CAAC,YAAY,CAAC,SAAS,CAAC;wBACxD,OAAO,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC;oBACxC;gBACF;;QAEJ;IACF;AAEA,IAAA,UAAU,KAAK;IAEf,QAAQ,GAAA;AACN,QAAA,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE;AACxB,YAAA,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE;QACrB;IACF;IAEA,OAAO,GAAA;AACL,QAAA,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE;IACpB;IAEA,SAAS,GAAA;AACP,QAAA,IAAI,CAAC,MAAM,EAAE,OAAO,EAAE;IACxB;;AAzEmB,eAAe,GAAA,UAAA,CAAA;IAJnC,UAAU,CAAC,iBAAiB,CAAC;AAC5B,QAAA,SAAS,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,YAAY,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;QACjD,SAAS,EAAE,CAAC,SAAS,CAAC;KACvB;AACoB,CAAA,EAAA,eAAe,CA0EnC;8BA1EoB,eAAe;;;;"}
|
package/index.js
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@combos-fun/plugin-cannon",
|
|
3
|
+
"version": "0.0.6",
|
|
4
|
+
"description": "@combos-fun/plugin-cannon",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"module": "dist/plugin-cannon.esm.js",
|
|
7
|
+
"bundle": "CombosFun.plugin.cannon",
|
|
8
|
+
"unpkg": "dist/CombosFun.plugin.cannon.min.js",
|
|
9
|
+
"files": [
|
|
10
|
+
"index.js",
|
|
11
|
+
"dist"
|
|
12
|
+
],
|
|
13
|
+
"types": "dist/plugin-cannon.d.ts",
|
|
14
|
+
"keywords": [
|
|
15
|
+
"combos-fun",
|
|
16
|
+
"game",
|
|
17
|
+
"physics",
|
|
18
|
+
"3d",
|
|
19
|
+
"cannon"
|
|
20
|
+
],
|
|
21
|
+
"author": "sun668 <q947692259@gmail.com>",
|
|
22
|
+
"dependencies": {
|
|
23
|
+
"cannon-es": "^0.20.0",
|
|
24
|
+
"@combos-fun/engine": "0.0.6"
|
|
25
|
+
},
|
|
26
|
+
"scripts": {
|
|
27
|
+
"build": "node ../../scripts/build-package.mjs"
|
|
28
|
+
}
|
|
29
|
+
}
|