@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.
Files changed (92) hide show
  1. package/CHANGELOG.md +75 -0
  2. package/api-surface.json +500 -2
  3. package/data/microgm-opt.PROVENANCE.md +20 -0
  4. package/data/microgm-opt.sf2 +0 -0
  5. package/dist/assets/SvgParts.d.ts +31 -0
  6. package/dist/assets/SvgParts.d.ts.map +1 -0
  7. package/dist/assets/SvgParts.js +54 -0
  8. package/dist/assets/SvgParts.js.map +1 -0
  9. package/dist/assets/SvgSource.d.ts +3 -0
  10. package/dist/assets/SvgSource.d.ts.map +1 -0
  11. package/dist/assets/SvgSource.js +22 -0
  12. package/dist/assets/SvgSource.js.map +1 -0
  13. package/dist/assets/index.d.ts +2 -0
  14. package/dist/assets/index.d.ts.map +1 -1
  15. package/dist/assets/index.js +1 -0
  16. package/dist/assets/index.js.map +1 -1
  17. package/dist/assets/svg.d.ts.map +1 -1
  18. package/dist/assets/svg.js +9 -5
  19. package/dist/assets/svg.js.map +1 -1
  20. package/dist/mw_games.global.js +110 -110
  21. package/dist/mwl/presentation.d.ts.map +1 -1
  22. package/dist/mwl/presentation.js +25 -18
  23. package/dist/mwl/presentation.js.map +1 -1
  24. package/dist/physics/PhysicsWorld.d.ts +49 -17
  25. package/dist/physics/PhysicsWorld.d.ts.map +1 -1
  26. package/dist/physics/PhysicsWorld.js +297 -59
  27. package/dist/physics/PhysicsWorld.js.map +1 -1
  28. package/dist/physics/XpbdWorld.d.ts +1 -1
  29. package/dist/physics/XpbdWorld.js +1 -1
  30. package/dist/physics/cloth/index.d.ts +98 -0
  31. package/dist/physics/cloth/index.d.ts.map +1 -0
  32. package/dist/physics/cloth/index.js +207 -0
  33. package/dist/physics/cloth/index.js.map +1 -0
  34. package/dist/physics/index.d.ts +4 -0
  35. package/dist/physics/index.d.ts.map +1 -1
  36. package/dist/physics/index.js +2 -0
  37. package/dist/physics/index.js.map +1 -1
  38. package/dist/physics/spring/index.d.ts +90 -0
  39. package/dist/physics/spring/index.d.ts.map +1 -0
  40. package/dist/physics/spring/index.js +97 -0
  41. package/dist/physics/spring/index.js.map +1 -0
  42. package/dist/skeleton/index.d.ts +94 -13
  43. package/dist/skeleton/index.d.ts.map +1 -1
  44. package/dist/skeleton/index.js +192 -73
  45. package/dist/skeleton/index.js.map +1 -1
  46. package/dist/two-d/presentation/MwlPresentation.d.ts +12 -0
  47. package/dist/two-d/presentation/MwlPresentation.d.ts.map +1 -1
  48. package/dist/two-d/presentation/MwlPresentation.js +204 -153
  49. package/dist/two-d/presentation/MwlPresentation.js.map +1 -1
  50. package/dist/two-d/render/ClothSprite.d.ts +83 -0
  51. package/dist/two-d/render/ClothSprite.d.ts.map +1 -0
  52. package/dist/two-d/render/ClothSprite.js +105 -0
  53. package/dist/two-d/render/ClothSprite.js.map +1 -0
  54. package/dist/two-d/render/HazeLayer.d.ts +112 -0
  55. package/dist/two-d/render/HazeLayer.d.ts.map +1 -0
  56. package/dist/two-d/render/HazeLayer.js +185 -0
  57. package/dist/two-d/render/HazeLayer.js.map +1 -0
  58. package/dist/two-d/render/NeonGlow.d.ts +100 -0
  59. package/dist/two-d/render/NeonGlow.d.ts.map +1 -0
  60. package/dist/two-d/render/NeonGlow.js +183 -0
  61. package/dist/two-d/render/NeonGlow.js.map +1 -0
  62. package/dist/two-d/render/SkeletalSprite.d.ts +5 -2
  63. package/dist/two-d/render/SkeletalSprite.d.ts.map +1 -1
  64. package/dist/two-d/render/SkeletalSprite.js +27 -3
  65. package/dist/two-d/render/SkeletalSprite.js.map +1 -1
  66. package/dist/two-d/render/SpringSprite.d.ts +40 -0
  67. package/dist/two-d/render/SpringSprite.d.ts.map +1 -0
  68. package/dist/two-d/render/SpringSprite.js +39 -0
  69. package/dist/two-d/render/SpringSprite.js.map +1 -0
  70. package/dist/two-d/render/SpriteDeform.d.ts +156 -0
  71. package/dist/two-d/render/SpriteDeform.d.ts.map +1 -0
  72. package/dist/two-d/render/SpriteDeform.js +278 -0
  73. package/dist/two-d/render/SpriteDeform.js.map +1 -0
  74. package/dist/two-d/render/SvgSkeleton.d.ts +54 -0
  75. package/dist/two-d/render/SvgSkeleton.d.ts.map +1 -0
  76. package/dist/two-d/render/SvgSkeleton.js +112 -0
  77. package/dist/two-d/render/SvgSkeleton.js.map +1 -0
  78. package/dist/two-d/render/index.d.ts +12 -0
  79. package/dist/two-d/render/index.d.ts.map +1 -1
  80. package/dist/two-d/render/index.js +6 -0
  81. package/dist/two-d/render/index.js.map +1 -1
  82. package/dist/version.d.ts +1 -1
  83. package/dist/version.js +1 -1
  84. package/package.json +11 -7
  85. package/sbom.cdx.json +6 -58
  86. package/tools/asset-report.d.mts +37 -0
  87. package/tools/asset-report.mjs +157 -0
  88. package/tools/compile-resources.d.mts +24 -0
  89. package/tools/compile-resources.mjs +138 -5
  90. package/tools/emit-page.d.mts +9 -1
  91. package/tools/emit-page.mjs +31 -3
  92. 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 through matter-js, stepped on a fixed clock.
4
+ * Rigid bodies and constraints in plain TypeScript, stepped on a fixed clock.
6
5
  *
7
- * The adapter is the framework side of using matter-js in a mwg game: it owns the `Engine`,
8
- * steps it with a `FixedStepper` so the simulation is the same at any display refresh rate,
9
- * and reports contacts through a `Signal`, while leaving the bodies themselves as plain
10
- * matter-js objects a game reads `position` and `angle` from to place its sprites. It is
11
- * renderer-free, so a game's headless tests can run the same world.
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 matter-js bodies of the pair */
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.breakable = new Map();
37
- this.engine = Matter.Engine.create();
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 gravity is a direction times `scale`; 9.8 maps to its own default scale of 0.001
40
- this.engine.gravity.x = Math.sign(gravity.x);
41
- this.engine.gravity.y = Math.sign(gravity.y);
42
- this.engine.gravity.scale = Math.max(Math.abs(gravity.x), Math.abs(gravity.y)) * 0.0001;
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 Matter.Composite.allBodies(this.engine.world);
51
+ return this.bodies_;
51
52
  }
52
53
  get constraints() {
53
- return Matter.Composite.allConstraints(this.engine.world);
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(Matter.Bodies.rectangle(x, y, width, height, options));
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(Matter.Bodies.circle(x, y, radius, options));
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 constraint = Matter.Constraint.create({
70
- bodyA: a,
71
- ...(isBody(b) ? { bodyB: b } : { pointB: b }),
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
- Matter.Composite.remove(this.engine.world, item);
86
- this.breakable.delete(item);
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 a = endPoint(constraint.bodyA, constraint.pointA);
94
- const b = endPoint(constraint.bodyB, constraint.pointB);
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 constraint.length > 0 ? distance / constraint.length - 1 : distance;
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
- Matter.Engine.update(this.engine, step * 1000);
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 the map would skip entries
147
+ //collected first: removing while iterating would skip entries
112
148
  const snapped = [];
113
- for (const [constraint, limit] of this.breakable) {
114
- const stretch = this.stretchOf(constraint);
115
- if (stretch > limit)
116
- snapped.push([constraint, stretch]);
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 [constraint, stretch] of snapped) {
119
- this.remove(constraint);
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
- Matter.Composite.add(this.engine.world, body);
162
+ body.id = this.nextId++;
163
+ this.bodies_.push(body);
125
164
  return body;
126
165
  }
127
166
  }
128
- /** a constraint end in world space: the body's attachment point turned and moved with it, or the fixed point itself */
129
- function endPoint(body, point) {
130
- const local = point ?? { x: 0, y: 0 };
131
- if (!body)
132
- return local;
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 { x: body.position.x + local.x * cos - local.y * sin, y: body.position.y + local.x * sin + local.y * cos };
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 no `matter-js` dependency.
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 no `matter-js` dependency.
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"}