@datamoc/mw_games 0.38.0 → 0.40.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +75 -0
- package/api-surface.json +500 -2
- package/data/microgm-opt.PROVENANCE.md +20 -0
- package/data/microgm-opt.sf2 +0 -0
- package/dist/assets/SvgParts.d.ts +31 -0
- package/dist/assets/SvgParts.d.ts.map +1 -0
- package/dist/assets/SvgParts.js +54 -0
- package/dist/assets/SvgParts.js.map +1 -0
- package/dist/assets/SvgSource.d.ts +3 -0
- package/dist/assets/SvgSource.d.ts.map +1 -0
- package/dist/assets/SvgSource.js +22 -0
- package/dist/assets/SvgSource.js.map +1 -0
- package/dist/assets/index.d.ts +2 -0
- package/dist/assets/index.d.ts.map +1 -1
- package/dist/assets/index.js +1 -0
- package/dist/assets/index.js.map +1 -1
- package/dist/assets/svg.d.ts.map +1 -1
- package/dist/assets/svg.js +9 -5
- package/dist/assets/svg.js.map +1 -1
- package/dist/mw_games.global.js +110 -110
- package/dist/mwl/presentation.d.ts.map +1 -1
- package/dist/mwl/presentation.js +25 -18
- package/dist/mwl/presentation.js.map +1 -1
- package/dist/physics/PhysicsWorld.d.ts +49 -17
- package/dist/physics/PhysicsWorld.d.ts.map +1 -1
- package/dist/physics/PhysicsWorld.js +297 -59
- package/dist/physics/PhysicsWorld.js.map +1 -1
- package/dist/physics/XpbdWorld.d.ts +1 -1
- package/dist/physics/XpbdWorld.js +1 -1
- package/dist/physics/cloth/index.d.ts +98 -0
- package/dist/physics/cloth/index.d.ts.map +1 -0
- package/dist/physics/cloth/index.js +207 -0
- package/dist/physics/cloth/index.js.map +1 -0
- package/dist/physics/index.d.ts +4 -0
- package/dist/physics/index.d.ts.map +1 -1
- package/dist/physics/index.js +2 -0
- package/dist/physics/index.js.map +1 -1
- package/dist/physics/spring/index.d.ts +90 -0
- package/dist/physics/spring/index.d.ts.map +1 -0
- package/dist/physics/spring/index.js +97 -0
- package/dist/physics/spring/index.js.map +1 -0
- package/dist/skeleton/index.d.ts +94 -13
- package/dist/skeleton/index.d.ts.map +1 -1
- package/dist/skeleton/index.js +192 -73
- package/dist/skeleton/index.js.map +1 -1
- package/dist/two-d/presentation/MwlPresentation.d.ts +12 -0
- package/dist/two-d/presentation/MwlPresentation.d.ts.map +1 -1
- package/dist/two-d/presentation/MwlPresentation.js +204 -153
- package/dist/two-d/presentation/MwlPresentation.js.map +1 -1
- package/dist/two-d/render/ClothSprite.d.ts +83 -0
- package/dist/two-d/render/ClothSprite.d.ts.map +1 -0
- package/dist/two-d/render/ClothSprite.js +105 -0
- package/dist/two-d/render/ClothSprite.js.map +1 -0
- package/dist/two-d/render/HazeLayer.d.ts +112 -0
- package/dist/two-d/render/HazeLayer.d.ts.map +1 -0
- package/dist/two-d/render/HazeLayer.js +185 -0
- package/dist/two-d/render/HazeLayer.js.map +1 -0
- package/dist/two-d/render/NeonGlow.d.ts +100 -0
- package/dist/two-d/render/NeonGlow.d.ts.map +1 -0
- package/dist/two-d/render/NeonGlow.js +183 -0
- package/dist/two-d/render/NeonGlow.js.map +1 -0
- package/dist/two-d/render/SkeletalSprite.d.ts +5 -2
- package/dist/two-d/render/SkeletalSprite.d.ts.map +1 -1
- package/dist/two-d/render/SkeletalSprite.js +27 -3
- package/dist/two-d/render/SkeletalSprite.js.map +1 -1
- package/dist/two-d/render/SpringSprite.d.ts +40 -0
- package/dist/two-d/render/SpringSprite.d.ts.map +1 -0
- package/dist/two-d/render/SpringSprite.js +39 -0
- package/dist/two-d/render/SpringSprite.js.map +1 -0
- package/dist/two-d/render/SpriteDeform.d.ts +156 -0
- package/dist/two-d/render/SpriteDeform.d.ts.map +1 -0
- package/dist/two-d/render/SpriteDeform.js +278 -0
- package/dist/two-d/render/SpriteDeform.js.map +1 -0
- package/dist/two-d/render/SvgSkeleton.d.ts +54 -0
- package/dist/two-d/render/SvgSkeleton.d.ts.map +1 -0
- package/dist/two-d/render/SvgSkeleton.js +112 -0
- package/dist/two-d/render/SvgSkeleton.js.map +1 -0
- package/dist/two-d/render/index.d.ts +12 -0
- package/dist/two-d/render/index.d.ts.map +1 -1
- package/dist/two-d/render/index.js +6 -0
- package/dist/two-d/render/index.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +11 -7
- package/sbom.cdx.json +6 -58
- package/tools/asset-report.d.mts +37 -0
- package/tools/asset-report.mjs +157 -0
- package/tools/compile-resources.d.mts +24 -0
- package/tools/compile-resources.mjs +138 -5
- package/tools/emit-page.d.mts +9 -1
- package/tools/emit-page.mjs +31 -3
- package/tools/vite.mjs +6 -1
|
@@ -1,17 +1,20 @@
|
|
|
1
|
-
import Matter from 'matter-js';
|
|
2
1
|
import { FixedStepper } from '../core/FixedStepper.js';
|
|
3
2
|
import { Signal } from '../core/Signal.js';
|
|
4
3
|
/**
|
|
5
|
-
* Rigid bodies and constraints
|
|
4
|
+
* Rigid bodies and constraints in plain TypeScript, stepped on a fixed clock.
|
|
6
5
|
*
|
|
7
|
-
* The
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
6
|
+
* The framework side of game physics in a mwg game: it owns the solver, steps it with a
|
|
7
|
+
* `FixedStepper` so the simulation is the same at any display refresh rate, and reports
|
|
8
|
+
* contacts through a `Signal`, while leaving the bodies themselves as plain objects a game
|
|
9
|
+
* reads `position` and `angle` from to place its sprites. It is renderer-free, so a game's
|
|
10
|
+
* headless tests can run the same world. No third-party engine: semi-implicit Euler,
|
|
11
|
+
* impulse contacts with restitution and Coulomb friction, and projected distance joints.
|
|
12
|
+
*
|
|
13
|
+
* Bodies never spin: `angle` stays where a game puts it (a display offset), collisions use
|
|
14
|
+
* the unrotated shape, and joints rotate their attachment points by it. Circles and
|
|
15
|
+
* axis-aligned boxes collide with each other in every pairing; that is the whole shape
|
|
16
|
+
* catalogue, by design rather than by omission - a game needing polygons brings its own.
|
|
12
17
|
*
|
|
13
|
-
* `matter-js` is an optional peer dependency (`npm install matter-js`), imported only by this
|
|
14
|
-
* module (`@datamoc/mw_games/physics`), so a game that never simulates physics never bundles it.
|
|
15
18
|
* Constraints are springs and rods. Give one a `maxStretch` and it breaks when pulled that far
|
|
16
19
|
* past its rest length (`onBreak`); a game with a different stress rule reads `stretchOf` itself
|
|
17
20
|
* and calls `remove`.
|
|
@@ -29,28 +32,26 @@ import { Signal } from '../core/Signal.js';
|
|
|
29
32
|
*/
|
|
30
33
|
export class PhysicsWorld {
|
|
31
34
|
constructor(options = {}) {
|
|
32
|
-
/** fires once per new contact between two bodies, with the
|
|
35
|
+
/** fires once per new contact between two bodies, with the bodies of the pair */
|
|
33
36
|
this.onContact = new Signal();
|
|
34
37
|
/** fires when a breakable constraint passes its `maxStretch`; it is already removed from the world */
|
|
35
38
|
this.onBreak = new Signal();
|
|
36
|
-
this.
|
|
37
|
-
this.
|
|
39
|
+
this.bodies_ = [];
|
|
40
|
+
this.constraints_ = [];
|
|
41
|
+
this.touching = new Set();
|
|
42
|
+
this.nextId = 1;
|
|
38
43
|
const gravity = options.gravity ?? { x: 0, y: 9.8 };
|
|
39
|
-
//matter's
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
this.
|
|
44
|
+
//the option reads like matter-js's historic default pull; internally it scales to
|
|
45
|
+
//world units per second squared (measured: matter drops ~413 units in the first
|
|
46
|
+
//second at its own default, i.e. about 826 units/s^2, air drag aside)
|
|
47
|
+
this.gravity = { x: gravity.x * GRAVITY_SCALE, y: gravity.y * GRAVITY_SCALE };
|
|
43
48
|
this.stepper = new FixedStepper(options.step ?? 1 / 60, options.maxSubsteps ?? 5);
|
|
44
|
-
Matter.Events.on(this.engine, 'collisionStart', (event) => {
|
|
45
|
-
for (const pair of event.pairs)
|
|
46
|
-
this.onContact.dispatch({ a: pair.bodyA, b: pair.bodyB });
|
|
47
|
-
});
|
|
48
49
|
}
|
|
49
50
|
get bodies() {
|
|
50
|
-
return
|
|
51
|
+
return this.bodies_;
|
|
51
52
|
}
|
|
52
53
|
get constraints() {
|
|
53
|
-
return
|
|
54
|
+
return this.constraints_;
|
|
54
55
|
}
|
|
55
56
|
/** how far into the next fixed step the clock is, 0 to 1, for interpolated drawing */
|
|
56
57
|
get alpha() {
|
|
@@ -58,42 +59,43 @@ export class PhysicsWorld {
|
|
|
58
59
|
}
|
|
59
60
|
/** a box centred on (x, y) */
|
|
60
61
|
addBox(x, y, width, height, options = {}) {
|
|
61
|
-
return this.add(
|
|
62
|
+
return this.add(makeBody(`box ${width}x${height}`, { kind: 'box', width, height }, x, y, options));
|
|
62
63
|
}
|
|
63
64
|
addCircle(x, y, radius, options = {}) {
|
|
64
|
-
return this.add(
|
|
65
|
+
return this.add(makeBody(`circle r=${radius}`, { kind: 'circle', radius }, x, y, options));
|
|
65
66
|
}
|
|
66
67
|
/** joins two bodies, or a body to a fixed point in the world when `b` is a point */
|
|
67
68
|
addConstraint(a, b, options = {}) {
|
|
68
69
|
const isBody = (value) => 'position' in value;
|
|
69
|
-
const
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
...(options.pointA ? { pointA: options.pointA } : {}),
|
|
73
|
-
...(isBody(b) && options.pointB ? { pointB: options.pointB } : {}),
|
|
74
|
-
stiffness: options.stiffness ?? 1,
|
|
75
|
-
damping: options.damping ?? 0,
|
|
76
|
-
...(options.length !== undefined ? { length: options.length } : {}),
|
|
77
|
-
});
|
|
78
|
-
Matter.Composite.add(this.engine.world, constraint);
|
|
79
|
-
if (options.maxStretch !== undefined)
|
|
80
|
-
this.breakable.set(constraint, options.maxStretch);
|
|
81
|
-
return constraint;
|
|
70
|
+
const joint = new DistanceJoint(bodyOf(a, 'a'), isBody(b) ? bodyOf(b, 'b') : null, isBody(b) ? null : { x: b.x, y: b.y }, options);
|
|
71
|
+
this.constraints_.push(joint);
|
|
72
|
+
return joint;
|
|
82
73
|
}
|
|
83
|
-
/** removes a body, or a constraint, from the simulation */
|
|
74
|
+
/** removes a body (with its joints), or a constraint, from the simulation */
|
|
84
75
|
remove(item) {
|
|
85
|
-
|
|
86
|
-
|
|
76
|
+
const bodyIndex = this.bodies_.indexOf(item);
|
|
77
|
+
if (bodyIndex >= 0) {
|
|
78
|
+
this.bodies_.splice(bodyIndex, 1);
|
|
79
|
+
for (let index = this.constraints_.length - 1; index >= 0; index--) {
|
|
80
|
+
if (this.constraints_[index].touches(item))
|
|
81
|
+
this.constraints_.splice(index, 1);
|
|
82
|
+
}
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
const jointIndex = this.constraints_.indexOf(item);
|
|
86
|
+
if (jointIndex >= 0)
|
|
87
|
+
this.constraints_.splice(jointIndex, 1);
|
|
87
88
|
}
|
|
88
89
|
/**
|
|
89
90
|
* How far a constraint is stretched past its rest length, as a fraction of it (0.1 is 10%
|
|
90
91
|
* longer); for a zero-length joint, the distance between its ends. Negative when compressed.
|
|
91
92
|
*/
|
|
92
93
|
stretchOf(constraint) {
|
|
93
|
-
const
|
|
94
|
-
const
|
|
94
|
+
const joint = constraint;
|
|
95
|
+
const a = joint.endA();
|
|
96
|
+
const b = joint.endB();
|
|
95
97
|
const distance = Math.hypot(a.x - b.x, a.y - b.y);
|
|
96
|
-
return
|
|
98
|
+
return joint.length > 0 ? distance / joint.length - 1 : distance;
|
|
97
99
|
}
|
|
98
100
|
/**
|
|
99
101
|
* Advances the simulation by `dt` seconds of real time, running as many fixed steps as that
|
|
@@ -103,35 +105,271 @@ export class PhysicsWorld {
|
|
|
103
105
|
*/
|
|
104
106
|
update(dt) {
|
|
105
107
|
return this.stepper.advance(dt, (step) => {
|
|
106
|
-
|
|
108
|
+
this.step(step);
|
|
107
109
|
this.breakOverstretched();
|
|
108
110
|
});
|
|
109
111
|
}
|
|
112
|
+
step(h) {
|
|
113
|
+
for (const body of this.bodies_) {
|
|
114
|
+
if (body.isStatic)
|
|
115
|
+
continue;
|
|
116
|
+
body.velocity.x += this.gravity.x * h;
|
|
117
|
+
body.velocity.y += this.gravity.y * h;
|
|
118
|
+
body.position.x += body.velocity.x * h;
|
|
119
|
+
body.position.y += body.velocity.y * h;
|
|
120
|
+
}
|
|
121
|
+
for (const joint of this.constraints_)
|
|
122
|
+
joint.solve();
|
|
123
|
+
this.collide();
|
|
124
|
+
}
|
|
125
|
+
collide() {
|
|
126
|
+
const seen = new Set();
|
|
127
|
+
const list = this.bodies_;
|
|
128
|
+
for (let i = 0; i < list.length; i++) {
|
|
129
|
+
for (let j = i + 1; j < list.length; j++) {
|
|
130
|
+
const a = list[i];
|
|
131
|
+
const b = list[j];
|
|
132
|
+
if (a.isStatic && b.isStatic)
|
|
133
|
+
continue;
|
|
134
|
+
const contact = findContact(a, b);
|
|
135
|
+
if (!contact)
|
|
136
|
+
continue;
|
|
137
|
+
resolveContact(contact);
|
|
138
|
+
const key = a.id < b.id ? `${a.id}:${b.id}` : `${b.id}:${a.id}`;
|
|
139
|
+
seen.add(key);
|
|
140
|
+
if (!this.touching.has(key))
|
|
141
|
+
this.onContact.dispatch({ a, b });
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
this.touching = seen;
|
|
145
|
+
}
|
|
110
146
|
breakOverstretched() {
|
|
111
|
-
//collected first: removing while iterating
|
|
147
|
+
//collected first: removing while iterating would skip entries
|
|
112
148
|
const snapped = [];
|
|
113
|
-
for (const
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
149
|
+
for (const joint of this.constraints_) {
|
|
150
|
+
if (joint.breakLimit === undefined)
|
|
151
|
+
continue;
|
|
152
|
+
const stretch = this.stretchOf(joint);
|
|
153
|
+
if (stretch > joint.breakLimit)
|
|
154
|
+
snapped.push([joint, stretch]);
|
|
117
155
|
}
|
|
118
|
-
for (const [
|
|
119
|
-
this.remove(
|
|
120
|
-
this.onBreak.dispatch({ constraint, stretch });
|
|
156
|
+
for (const [joint, stretch] of snapped) {
|
|
157
|
+
this.remove(joint);
|
|
158
|
+
this.onBreak.dispatch({ constraint: joint, stretch });
|
|
121
159
|
}
|
|
122
160
|
}
|
|
123
161
|
add(body) {
|
|
124
|
-
|
|
162
|
+
body.id = this.nextId++;
|
|
163
|
+
this.bodies_.push(body);
|
|
125
164
|
return body;
|
|
126
165
|
}
|
|
127
166
|
}
|
|
128
|
-
/**
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
167
|
+
/** world units per second squared per gravity unit; the default pull matches matter-js's historic one */
|
|
168
|
+
const GRAVITY_SCALE = 826 / 9.8;
|
|
169
|
+
function shapeArea(shape) {
|
|
170
|
+
return shape.kind === 'circle' ? Math.PI * shape.radius * shape.radius : shape.width * shape.height;
|
|
171
|
+
}
|
|
172
|
+
class SimulatedBody {
|
|
173
|
+
constructor(shape, x, y, options) {
|
|
174
|
+
this.id = 0;
|
|
175
|
+
this.velocity = { x: 0, y: 0 };
|
|
176
|
+
this.shape = shape;
|
|
177
|
+
this.position = { x, y };
|
|
178
|
+
this.angle = options.angle ?? 0;
|
|
179
|
+
this.label = options.label ?? '';
|
|
180
|
+
this.isStatic = options.isStatic ?? false;
|
|
181
|
+
const density = options.density ?? 1;
|
|
182
|
+
this.invMass = this.isStatic || !(density > 0) ? 0 : 1 / (density * shapeArea(shape));
|
|
183
|
+
this.restitution = options.restitution ?? 0;
|
|
184
|
+
this.friction = options.friction ?? 0.1;
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
function makeBody(description, shape, x, y, options) {
|
|
188
|
+
if (shape.kind === 'circle' ? !(shape.radius > 0) : !(shape.width > 0 && shape.height > 0)) {
|
|
189
|
+
throw new RangeError(`a physics ${description} needs positive size`);
|
|
190
|
+
}
|
|
191
|
+
if (!Number.isFinite(x) || !Number.isFinite(y)) {
|
|
192
|
+
throw new RangeError(`a physics ${description} needs a finite position, saw (${x}, ${y})`);
|
|
193
|
+
}
|
|
194
|
+
return new SimulatedBody(shape, x, y, options);
|
|
195
|
+
}
|
|
196
|
+
function bodyOf(value, name) {
|
|
197
|
+
if (value instanceof SimulatedBody)
|
|
198
|
+
return value;
|
|
199
|
+
throw new Error(`physics constraint end ${name} is not a body of this world`);
|
|
200
|
+
}
|
|
201
|
+
class DistanceJoint {
|
|
202
|
+
constructor(a, b, anchor, options) {
|
|
203
|
+
this.a = a;
|
|
204
|
+
this.b = b;
|
|
205
|
+
if (anchor && (!Number.isFinite(anchor.x) || !Number.isFinite(anchor.y))) {
|
|
206
|
+
throw new RangeError(`a physics joint needs a finite anchor, saw (${anchor.x}, ${anchor.y})`);
|
|
207
|
+
}
|
|
208
|
+
this.anchor = anchor;
|
|
209
|
+
this.pointA = { ...(options.pointA ?? { x: 0, y: 0 }) };
|
|
210
|
+
this.pointB = { ...(options.pointB ?? { x: 0, y: 0 }) };
|
|
211
|
+
this.stiffness = options.stiffness ?? 1;
|
|
212
|
+
this.damping = options.damping ?? 0;
|
|
213
|
+
const endA = this.endA();
|
|
214
|
+
const endB = this.endB();
|
|
215
|
+
this.length = options.length ?? Math.hypot(endA.x - endB.x, endA.y - endB.y);
|
|
216
|
+
this.breakLimit = options.maxStretch;
|
|
217
|
+
}
|
|
218
|
+
touches(body) {
|
|
219
|
+
return this.a === body || this.b === body;
|
|
220
|
+
}
|
|
221
|
+
endA() {
|
|
222
|
+
return turn(this.a, this.pointA);
|
|
223
|
+
}
|
|
224
|
+
endB() {
|
|
225
|
+
return this.b ? turn(this.b, this.pointB) : { ...this.anchor };
|
|
226
|
+
}
|
|
227
|
+
/** one projection pass: stiff rods land on their rest length, soft joints close a share of the error */
|
|
228
|
+
solve() {
|
|
229
|
+
const a = this.endA();
|
|
230
|
+
const b = this.endB();
|
|
231
|
+
const dx = b.x - a.x;
|
|
232
|
+
const dy = b.y - a.y;
|
|
233
|
+
const distance = Math.hypot(dx, dy);
|
|
234
|
+
if (distance === 0)
|
|
235
|
+
return;
|
|
236
|
+
const error = ((distance - this.length) / distance) * this.stiffness;
|
|
237
|
+
const wa = this.a.invMass;
|
|
238
|
+
const wb = this.b ? this.b.invMass : 0;
|
|
239
|
+
const total = wa + wb;
|
|
240
|
+
if (total === 0)
|
|
241
|
+
return;
|
|
242
|
+
this.a.position.x += dx * error * (wa / total);
|
|
243
|
+
this.a.position.y += dy * error * (wa / total);
|
|
244
|
+
if (this.b) {
|
|
245
|
+
this.b.position.x -= dx * error * (wb / total);
|
|
246
|
+
this.b.position.y -= dy * error * (wb / total);
|
|
247
|
+
}
|
|
248
|
+
//radial oscillation leaves through velocity, or a spring would ring forever
|
|
249
|
+
const nx = dx / distance;
|
|
250
|
+
const ny = dy / distance;
|
|
251
|
+
const kill = Math.min(1, Math.max(0, this.stiffness + this.damping));
|
|
252
|
+
if (kill === 0)
|
|
253
|
+
return;
|
|
254
|
+
const va = this.a.velocity;
|
|
255
|
+
const vb = this.b ? this.b.velocity : { x: 0, y: 0 };
|
|
256
|
+
const closing = (vb.x - va.x) * nx + (vb.y - va.y) * ny;
|
|
257
|
+
va.x += closing * kill * (wa / total) * nx;
|
|
258
|
+
va.y += closing * kill * (wa / total) * ny;
|
|
259
|
+
if (this.b) {
|
|
260
|
+
this.b.velocity.x -= closing * kill * (wb / total) * nx;
|
|
261
|
+
this.b.velocity.y -= closing * kill * (wb / total) * ny;
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
/** a constraint end in world space: the body's attachment point turned by its angle, or the fixed point itself */
|
|
266
|
+
function turn(body, local) {
|
|
133
267
|
const cos = Math.cos(body.angle);
|
|
134
268
|
const sin = Math.sin(body.angle);
|
|
135
|
-
return {
|
|
269
|
+
return {
|
|
270
|
+
x: body.position.x + local.x * cos - local.y * sin,
|
|
271
|
+
y: body.position.y + local.x * sin + local.y * cos,
|
|
272
|
+
};
|
|
273
|
+
}
|
|
274
|
+
function findContact(a, b) {
|
|
275
|
+
const sa = a.shape;
|
|
276
|
+
const sb = b.shape;
|
|
277
|
+
if (sa.kind === 'circle' && sb.kind === 'circle')
|
|
278
|
+
return circleCircle(a, sa.radius, b, sb.radius);
|
|
279
|
+
if (sa.kind === 'circle')
|
|
280
|
+
return circleBox(a, b, sa.radius, sb);
|
|
281
|
+
if (sb.kind === 'circle') {
|
|
282
|
+
const contact = circleBox(b, a, sb.radius, sa);
|
|
283
|
+
//the helper reports ball first: swap back so the normal runs from a to b
|
|
284
|
+
if (contact)
|
|
285
|
+
return { a, b, nx: -contact.nx, ny: -contact.ny, penetration: contact.penetration };
|
|
286
|
+
return null;
|
|
287
|
+
}
|
|
288
|
+
return boxBox(a, sa, b, sb);
|
|
289
|
+
}
|
|
290
|
+
function circleCircle(a, ra, b, rb) {
|
|
291
|
+
const dx = b.position.x - a.position.x;
|
|
292
|
+
const dy = b.position.y - a.position.y;
|
|
293
|
+
const distance = Math.hypot(dx, dy);
|
|
294
|
+
if (distance >= ra + rb)
|
|
295
|
+
return null;
|
|
296
|
+
if (distance === 0)
|
|
297
|
+
return { a, b, nx: 1, ny: 0, penetration: ra + rb };
|
|
298
|
+
return { a, b, nx: dx / distance, ny: dy / distance, penetration: ra + rb - distance };
|
|
299
|
+
}
|
|
300
|
+
/**
|
|
301
|
+
* Ball first, box second: the normal runs from the ball toward the box. A centre on or
|
|
302
|
+
* inside the edge leaves along the least-penetrated axis instead.
|
|
303
|
+
*/
|
|
304
|
+
function circleBox(ball, boxBody, radius, box) {
|
|
305
|
+
const hw = box.width / 2;
|
|
306
|
+
const hh = box.height / 2;
|
|
307
|
+
const dx = ball.position.x - boxBody.position.x;
|
|
308
|
+
const dy = ball.position.y - boxBody.position.y;
|
|
309
|
+
const cx = Math.max(-hw, Math.min(hw, dx));
|
|
310
|
+
const cy = Math.max(-hh, Math.min(hh, dy));
|
|
311
|
+
const px = dx - cx;
|
|
312
|
+
const py = dy - cy;
|
|
313
|
+
const distance = Math.hypot(px, py);
|
|
314
|
+
if (distance === 0) {
|
|
315
|
+
const ox = hw - Math.abs(dx);
|
|
316
|
+
const oy = hh - Math.abs(dy);
|
|
317
|
+
const exitX = ox < oy;
|
|
318
|
+
const nx = exitX ? -(Math.sign(dx) || 1) : 0;
|
|
319
|
+
const ny = exitX ? 0 : -(Math.sign(dy) || 1);
|
|
320
|
+
return { a: ball, b: boxBody, nx, ny, penetration: Math.min(ox, oy) + radius };
|
|
321
|
+
}
|
|
322
|
+
if (distance >= radius)
|
|
323
|
+
return null;
|
|
324
|
+
return { a: ball, b: boxBody, nx: -px / distance, ny: -py / distance, penetration: radius - distance };
|
|
325
|
+
}
|
|
326
|
+
function boxBox(a, sa, b, sb) {
|
|
327
|
+
const ox = (sa.width + sb.width) / 2 - Math.abs(a.position.x - b.position.x);
|
|
328
|
+
if (ox <= 0)
|
|
329
|
+
return null;
|
|
330
|
+
const oy = (sa.height + sb.height) / 2 - Math.abs(a.position.y - b.position.y);
|
|
331
|
+
if (oy <= 0)
|
|
332
|
+
return null;
|
|
333
|
+
if (ox < oy) {
|
|
334
|
+
const sign = Math.sign(b.position.x - a.position.x) || 1;
|
|
335
|
+
return { a, b, nx: sign, ny: 0, penetration: ox };
|
|
336
|
+
}
|
|
337
|
+
const sign = Math.sign(b.position.y - a.position.y) || 1;
|
|
338
|
+
return { a, b, nx: 0, ny: sign, penetration: oy };
|
|
339
|
+
}
|
|
340
|
+
function resolveContact({ a, b, nx, ny, penetration }) {
|
|
341
|
+
const total = a.invMass + b.invMass;
|
|
342
|
+
if (total === 0)
|
|
343
|
+
return;
|
|
344
|
+
//depenetrate fully: with restitution handled below, nothing re-sinks a resting body
|
|
345
|
+
a.position.x -= nx * penetration * (a.invMass / total);
|
|
346
|
+
a.position.y -= ny * penetration * (a.invMass / total);
|
|
347
|
+
b.position.x += nx * penetration * (b.invMass / total);
|
|
348
|
+
b.position.y += ny * penetration * (b.invMass / total);
|
|
349
|
+
const rvx = b.velocity.x - a.velocity.x;
|
|
350
|
+
const rvy = b.velocity.y - a.velocity.y;
|
|
351
|
+
const closing = rvx * nx + rvy * ny;
|
|
352
|
+
if (closing >= 0)
|
|
353
|
+
return;
|
|
354
|
+
//slow grazes do not bounce, or stacks would jitter forever
|
|
355
|
+
const restitution = -closing > 1 ? Math.max(a.restitution, b.restitution) : 0;
|
|
356
|
+
const impulse = (-(1 + restitution) * closing) / total;
|
|
357
|
+
a.velocity.x -= impulse * nx * a.invMass;
|
|
358
|
+
a.velocity.y -= impulse * ny * a.invMass;
|
|
359
|
+
b.velocity.x += impulse * nx * b.invMass;
|
|
360
|
+
b.velocity.y += impulse * ny * b.invMass;
|
|
361
|
+
const friction = Math.sqrt(a.friction * b.friction);
|
|
362
|
+
if (friction > 0) {
|
|
363
|
+
const tvx = rvx - closing * nx;
|
|
364
|
+
const tvy = rvy - closing * ny;
|
|
365
|
+
const slide = Math.hypot(tvx, tvy);
|
|
366
|
+
if (slide > 0) {
|
|
367
|
+
const grip = Math.min(slide / total, friction * impulse);
|
|
368
|
+
a.velocity.x += (tvx / slide) * grip * a.invMass;
|
|
369
|
+
a.velocity.y += (tvy / slide) * grip * a.invMass;
|
|
370
|
+
b.velocity.x -= (tvx / slide) * grip * b.invMass;
|
|
371
|
+
b.velocity.y -= (tvy / slide) * grip * b.invMass;
|
|
372
|
+
}
|
|
373
|
+
}
|
|
136
374
|
}
|
|
137
375
|
//# sourceMappingURL=PhysicsWorld.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PhysicsWorld.js","sourceRoot":"","sources":["../../src/physics/PhysicsWorld.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"PhysicsWorld.js","sourceRoot":"","sources":["../../src/physics/PhysicsWorld.ts"],"names":[],"mappings":"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"}
|
|
@@ -79,7 +79,7 @@ export interface XpbdLink {
|
|
|
79
79
|
*
|
|
80
80
|
* It is the engine of Pontifex (a bridge-building game), generalised: the vehicle, the water
|
|
81
81
|
* and the levels stay in the game, and what is here is only nodes, links, forces and breaking.
|
|
82
|
-
* Unlike `PhysicsWorld` it has no rigid bodies or collisions and
|
|
82
|
+
* Unlike `PhysicsWorld` it has no rigid bodies or collisions: nodes and links only.
|
|
83
83
|
*
|
|
84
84
|
* @example
|
|
85
85
|
* ```ts
|
|
@@ -14,7 +14,7 @@ import { Signal } from '../core/Signal.js';
|
|
|
14
14
|
*
|
|
15
15
|
* It is the engine of Pontifex (a bridge-building game), generalised: the vehicle, the water
|
|
16
16
|
* and the levels stay in the game, and what is here is only nodes, links, forces and breaking.
|
|
17
|
-
* Unlike `PhysicsWorld` it has no rigid bodies or collisions and
|
|
17
|
+
* Unlike `PhysicsWorld` it has no rigid bodies or collisions: nodes and links only.
|
|
18
18
|
*
|
|
19
19
|
* @example
|
|
20
20
|
* ```ts
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A small pinned-point cloth mesh: Verlet integration over a grid of points joined by
|
|
3
|
+
* structural distance constraints, the top row pinned by default. Renderer-free arithmetic
|
|
4
|
+
* (roadmap 423): no physics engine, no allocations per step, deterministic for a fixed
|
|
5
|
+
* `update(dt)` sequence, so a frame budget is exact rather than hoped for - one update
|
|
6
|
+
* costs O(points + links), two relaxation passes over structural links only, never shear
|
|
7
|
+
* or bend constraints and never a full cloth simulator. A skirt, tunic or scarf follows
|
|
8
|
+
* its character with a slight lag; `ClothSprite` draws the mesh on the GPU path 414 ships.
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```ts
|
|
12
|
+
* import { Cloth } from '@datamoc/mw_games/physics';
|
|
13
|
+
*
|
|
14
|
+
* const scarf = new Cloth({ width: 60, height: 20, segmentsX: 6, segmentsY: 2, gravity: { x: 0, y: 900 } });
|
|
15
|
+
* for (let i = 0; i < 60; i++) scarf.update(1 / 60); // one fixed second
|
|
16
|
+
* console.log(scarf.pointPosition(scarf.indexOf(3, 2)).y > 20); // true - the free end sags down
|
|
17
|
+
* console.log(scarf.pointPosition(scarf.indexOf(0, 0))); // { x: 0, y: 0 } - the pinned edge never moves
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
20
|
+
export interface ClothOptions {
|
|
21
|
+
/** rest width in world units; must be finite and above 0 */
|
|
22
|
+
width: number;
|
|
23
|
+
/** rest height in world units; must be finite and above 0 */
|
|
24
|
+
height: number;
|
|
25
|
+
/** quads across; an integer of at least 1 (points across are `segmentsX + 1`) */
|
|
26
|
+
segmentsX: number;
|
|
27
|
+
/** quads down; an integer of at least 1 (points down are `segmentsY + 1`) */
|
|
28
|
+
segmentsY: number;
|
|
29
|
+
/** how much of each constraint error one relaxation pass removes, 0 to 1; default 0.9 */
|
|
30
|
+
stiffness?: number;
|
|
31
|
+
/** share of velocity lost per update, 0 to 1; default 0.02 */
|
|
32
|
+
damping?: number;
|
|
33
|
+
/** acceleration in world units per second squared; default `{ x: 0, y: 0 }` */
|
|
34
|
+
gravity?: {
|
|
35
|
+
x: number;
|
|
36
|
+
y: number;
|
|
37
|
+
};
|
|
38
|
+
/** acceleration in world units per second squared; default `{ x: 0, y: 0 }` */
|
|
39
|
+
wind?: {
|
|
40
|
+
x: number;
|
|
41
|
+
y: number;
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
export declare class Cloth {
|
|
45
|
+
readonly segmentsX: number;
|
|
46
|
+
readonly segmentsY: number;
|
|
47
|
+
readonly stiffness: number;
|
|
48
|
+
readonly damping: number;
|
|
49
|
+
private gravity;
|
|
50
|
+
private wind;
|
|
51
|
+
private readonly rest;
|
|
52
|
+
private readonly positions;
|
|
53
|
+
private readonly previous;
|
|
54
|
+
private readonly pinned;
|
|
55
|
+
private readonly links;
|
|
56
|
+
constructor(options: ClothOptions);
|
|
57
|
+
/** how many simulated points the mesh holds */
|
|
58
|
+
get pointCount(): number;
|
|
59
|
+
/** the flat index of the point at `(column, row)`; throws a RangeError outside the grid */
|
|
60
|
+
indexOf(column: number, row: number): number;
|
|
61
|
+
private checkIndex;
|
|
62
|
+
/** the current position of one point */
|
|
63
|
+
pointPosition(index: number): {
|
|
64
|
+
x: number;
|
|
65
|
+
y: number;
|
|
66
|
+
};
|
|
67
|
+
/** whether a point is pinned (integration and relaxation both leave it alone) */
|
|
68
|
+
isPinned(index: number): boolean;
|
|
69
|
+
/** index pairs joined by a structural constraint, row links then column links, for drawing the mesh */
|
|
70
|
+
pointLinks(): Array<readonly [number, number]>;
|
|
71
|
+
/** pin a point where it currently stands */
|
|
72
|
+
pinPoint(index: number): void;
|
|
73
|
+
/** release a pinned point; it keeps its current position and moves from there */
|
|
74
|
+
unpinPoint(index: number): void;
|
|
75
|
+
/** replace the wind acceleration; validated, so a gust can never smuggle in a NaN */
|
|
76
|
+
setWind(x: number, y: number): void;
|
|
77
|
+
/** replace the gravity acceleration */
|
|
78
|
+
setGravity(x: number, y: number): void;
|
|
79
|
+
/** put every point back at rest with no velocity; pins are kept */
|
|
80
|
+
reset(): void;
|
|
81
|
+
/** how many points currently sit away from their rest positions */
|
|
82
|
+
movedCount(): number;
|
|
83
|
+
/**
|
|
84
|
+
* Write every current position into `into`, which must hold exactly
|
|
85
|
+
* `pointCount * 2` floats. The mesh side calls this with its GPU position array.
|
|
86
|
+
*/
|
|
87
|
+
writePositions(into: Float32Array): void;
|
|
88
|
+
/**
|
|
89
|
+
* Advance the mesh by `dt` seconds: one Verlet integration pass, then two relaxation
|
|
90
|
+
* passes over the structural links. Call with a fixed `dt` (a `FixedStepper` does that)
|
|
91
|
+
* for a deterministic sequence; keep it small (60 Hz steps), since Verlet answers a
|
|
92
|
+
* huge step with a huge swing rather than an error. A zero `dt` holds still; a negative
|
|
93
|
+
* or non-finite one throws a RangeError.
|
|
94
|
+
*/
|
|
95
|
+
update(dt: number): void;
|
|
96
|
+
private relax;
|
|
97
|
+
}
|
|
98
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/physics/cloth/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,WAAW,YAAY;IAC5B,4DAA4D;IAC5D,KAAK,EAAE,MAAM,CAAC;IACd,6DAA6D;IAC7D,MAAM,EAAE,MAAM,CAAC;IACf,iFAAiF;IACjF,SAAS,EAAE,MAAM,CAAC;IAClB,6EAA6E;IAC7E,SAAS,EAAE,MAAM,CAAC;IAClB,yFAAyF;IACzF,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,8DAA8D;IAC9D,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,+EAA+E;IAC/E,OAAO,CAAC,EAAE;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACnC,+EAA+E;IAC/E,IAAI,CAAC,EAAE;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CAChC;AAUD,qBAAa,KAAK;IACjB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,OAAO,CAAC,OAAO,CAA2B;IAC1C,OAAO,CAAC,IAAI,CAA2B;IACvC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAe;IACpC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAe;IACzC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAe;IACxC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAa;IACpC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAA2C;IAEjE,YAAY,OAAO,EAAE,YAAY,EAuDhC;IAED,+CAA+C;IAC/C,IAAI,UAAU,IAAI,MAAM,CAEvB;IAED,2FAA2F;IAC3F,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAc3C;IAED,OAAO,CAAC,UAAU;IAMlB,wCAAwC;IACxC,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,CAGrD;IAED,iFAAiF;IACjF,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAG/B;IAED,uGAAuG;IACvG,UAAU,IAAI,KAAK,CAAC,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAE7C;IAED,4CAA4C;IAC5C,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAK5B;IAED,iFAAiF;IACjF,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAG9B;IAED,qFAAqF;IACrF,OAAO,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,IAAI,CAGlC;IAED,uCAAuC;IACvC,UAAU,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,IAAI,CAGrC;IAED,mEAAmE;IACnE,KAAK,IAAI,IAAI,CAGZ;IAED,mEAAmE;IACnE,UAAU,IAAI,MAAM,CAUnB;IAED;;;OAGG;IACH,cAAc,CAAC,IAAI,EAAE,YAAY,GAAG,IAAI,CAOvC;IAED;;;;;;OAMG;IACH,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAoBvB;IAED,OAAO,CAAC,KAAK;CAqBb"}
|