castle-web-cli 0.4.94 → 0.4.96

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.
@@ -27,6 +27,13 @@ export const FIXED_STEP_MS = 1000 / 60;
27
27
  export const FIXED_STEP_S = FIXED_STEP_MS / 1000;
28
28
  export const MAX_STEPS_PER_FRAME = 5;
29
29
 
30
+ // Hard cap on a body's speed (px per fixed step) -- a safety net so a constraint
31
+ // blow-up (a stiff joint at a bad angle can inject huge velocity in one step)
32
+ // can't fling a body off screen. Well above any intended motion (a slingshot
33
+ // launch is ~20), so normal gameplay never touches it; it only ever engages to
34
+ // bound a runaway.
35
+ export const MAX_SPEED = 60;
36
+
30
37
  // World gravity in matter's own units. `scale` matches matter's internal
31
38
  // default; `y` is what a scene tunes (1 ~= a gentle arcade fall).
32
39
  export const DEFAULT_GRAVITY = { x: 0, y: 1, scale: 0.001 };
@@ -73,7 +80,10 @@ function shapeToPart(s) {
73
80
  if (part) return part;
74
81
  return Matter.Bodies.rectangle((x0 + x1) / 2, (y0 + y1) / 2, Math.max(1, x1 - x0), Math.max(1, y1 - y0));
75
82
  }
76
- return Matter.Bodies.rectangle(s.cx, s.cy, Math.max(1, s.width), Math.max(1, s.height));
83
+ // `s.angle` (deg) rotates the box part about its center at creation; the
84
+ // compound body's Layout.rotation composes on top.
85
+ const opts = s.angle ? { angle: s.angle * DEG_TO_RAD } : undefined;
86
+ return Matter.Bodies.rectangle(s.cx, s.cy, Math.max(1, s.width), Math.max(1, s.height), opts);
77
87
  }
78
88
 
79
89
  // Structural signature: when this changes we rebuild the body (shape set / sizes
@@ -87,7 +97,7 @@ export function bodySignature(actor) {
87
97
  s.type === 'circle'
88
98
  ? `c${Math.round(s.radius)}`
89
99
  : s.type === 'box'
90
- ? `b${Math.round(s.width)}x${Math.round(s.height)}`
100
+ ? `b${Math.round(s.width)}x${Math.round(s.height)}@${Math.round(s.angle ?? 0)}`
91
101
  : `${s.type[0]}${(s.points ?? []).length}`
92
102
  )
93
103
  .join(',');
@@ -173,3 +183,13 @@ export function applyAngularDrag(bodies) {
173
183
  if (drag > 0 && !body.isStatic) body.angularVelocity *= Math.max(0, 1 - drag * FIXED_STEP_S);
174
184
  }
175
185
  }
186
+
187
+ // Safety clamp: bound each body's speed to MAX_SPEED so a constraint blow-up
188
+ // can't fling it off screen. Run right after each Engine.update.
189
+ export function clampSpeeds(bodies) {
190
+ for (const body of bodies) {
191
+ if (body.isStatic) continue;
192
+ const s = Math.hypot(body.velocity.x, body.velocity.y);
193
+ if (s > MAX_SPEED) Matter.Body.setVelocity(body, { x: (body.velocity.x / s) * MAX_SPEED, y: (body.velocity.y / s) * MAX_SPEED });
194
+ }
195
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "castle-web-cli",
3
- "version": "0.4.94",
3
+ "version": "0.4.96",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "castle-web": "./dist/index.js"