@msb235/blits-rapier 0.7.1 → 0.7.3

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 CHANGED
@@ -4,6 +4,23 @@ This package follows [semver](https://semver.org). Below 1.0.0, a breaking chang
4
4
  version and everything else the patch. The release workflow refuses a `rapier-v*` tag with no
5
5
  section here.
6
6
 
7
+ ## 0.7.3
8
+
9
+ ### Changed
10
+
11
+ - `Body.cue` and `Body.drive` cue through the engine's `bind`, so a spec naming `subjects` throws
12
+ the engine's message, prefixed `blits:`.
13
+ - Needs `@msb235/blits` 1.3.0 or later, for `bind`: the peer range rises with the next engine release.
14
+ - `channels2`, `channels3`, `kinematic2`, and `kinematic3` are typed as the engine's `Kit`, so their
15
+ properties are `readonly`. They behave as before.
16
+
17
+ ## 0.7.2
18
+
19
+ ### Fixed
20
+
21
+ - A seek past memory through a store that returns everything replays from the world's latest copy
22
+ before the time sought, not its first, so the log of frames it brings back stays bounded.
23
+
7
24
  ## 0.7.1
8
25
 
9
26
  ### Changed
@@ -1,4 +1,4 @@
1
- import { type Channel, type Vec } from '@msb235/blits';
1
+ import { type Kit, type Vec } from '@msb235/blits';
2
2
  /** The channels a 2D world reads and writes: a body's pose, and the push on its controls. */
3
3
  export interface Pose2 {
4
4
  position: Vec<2>;
@@ -14,13 +14,9 @@ export interface Pose3 {
14
14
  torque: Vec<3>;
15
15
  }
16
16
  /** A 2D world's channels, to spread into a kit. */
17
- export declare const channels2: {
18
- [K in keyof Pose2]: Channel<Pose2[K]>;
19
- };
17
+ export declare const channels2: Kit<Pose2>;
20
18
  /** A 3D world's channels, to spread into a kit. */
21
- export declare const channels3: {
22
- [K in keyof Pose3]: Channel<Pose3[K]>;
23
- };
19
+ export declare const channels3: Kit<Pose3>;
24
20
  /**
25
21
  * Where a voice on a kinematic 2D body's controls moves it: a position and an angle in radians. Each
26
22
  * has no rest, so a body with no voice writing it stays where it is. A voice's weight only switches
@@ -36,10 +32,6 @@ export interface Kinematic3 {
36
32
  facing?: Vec<4>;
37
33
  }
38
34
  /** A kinematic 2D body's channels, to spread into a kit beside `channels2`. */
39
- export declare const kinematic2: {
40
- [K in keyof Kinematic2]-?: Channel<NonNullable<Kinematic2[K]>>;
41
- };
35
+ export declare const kinematic2: Kit<Kinematic2>;
42
36
  /** A kinematic 3D body's channels, to spread into a kit beside `channels3`. */
43
- export declare const kinematic3: {
44
- [K in keyof Kinematic3]-?: Channel<NonNullable<Kinematic3[K]>>;
45
- };
37
+ export declare const kinematic3: Kit<Kinematic3>;
package/dist/channels.js CHANGED
@@ -13,14 +13,13 @@ export const channels3 = {
13
13
  force: vec(3, sum()),
14
14
  torque: vec(3, sum()),
15
15
  };
16
- const along = (a, b, u) => a + (b - a) * u;
17
16
  /** A kinematic 2D body's channels, to spread into a kit beside `channels2`. */
18
17
  export const kinematic2 = {
19
- goal: vec(2, last({ lerp: along })),
18
+ goal: vec(2, last({ lerp: sum().lerp })),
20
19
  facing: last({ lerp: angle({ turn: 2 * Math.PI }).lerp }),
21
20
  };
22
21
  /** A kinematic 3D body's channels, to spread into a kit beside `channels3`. */
23
22
  export const kinematic3 = {
24
- goal: vec(3, last({ lerp: along })),
23
+ goal: vec(3, last({ lerp: sum().lerp })),
25
24
  facing: last({ lerp: quat().lerp }),
26
25
  };
package/dist/physics.js CHANGED
@@ -1,4 +1,4 @@
1
- import { mix, patch, watched, } from '@msb235/blits';
1
+ import { bind, mix, patch, watched, } from '@msb235/blits';
2
2
  import { dimsOf } from './rapier.js';
3
3
  import { applyLog, copy, insert, pack, unpack, worldOf } from './world.js';
4
4
  const ROLE = 'physics';
@@ -20,10 +20,16 @@ export function physicsStore(store) {
20
20
  const all = await store.load(t);
21
21
  for (const w of worlds) {
22
22
  // A replay to t starts from the world's latest copy at or before it, which needs the frames from there.
23
- let from = t;
23
+ let from = Number.NEGATIVE_INFINITY;
24
24
  for (const r of all)
25
- if (r.mix === w.name && r.stream === 'snap' && r.subject === 'world' && r.at < from)
25
+ if (r.mix === w.name &&
26
+ r.stream === 'snap' &&
27
+ r.subject === 'world' &&
28
+ r.at <= t &&
29
+ r.at > from)
26
30
  from = r.at;
31
+ if (from === Number.NEGATIVE_INFINITY)
32
+ from = t;
27
33
  w.restore(from < t ? await store.load(from) : all, from);
28
34
  }
29
35
  return all.filter((r) => !(r.stream === 'host' && r.subject === FRAMES));
@@ -309,24 +315,19 @@ export function physics(kit, opts) {
309
315
  call('add body', adding(key, desc, colliders));
310
316
  const controls = {};
311
317
  keys.set(controls, `controls ${key}`);
312
- const own = (spec, subject) => {
313
- if ('subjects' in spec)
314
- throw new Error('blits-rapier: a body cues on itself; its spec names no subjects');
315
- return m.cue({ ...spec, subjects: [subject] });
316
- };
317
318
  const body = {
318
319
  key,
319
320
  controls,
320
321
  simulated: undefined,
321
322
  cue: (spec) => {
322
- const h = own(spec, body);
323
+ const h = self.cue(spec);
323
324
  if (spec.role === ROLE)
324
325
  authored.set(body, [...(authored.get(body) ?? []), h]);
325
326
  return h;
326
327
  },
327
328
  drive: (spec) => {
328
329
  driven.add(body);
329
- return own(spec, controls);
330
+ return steer.cue(spec);
330
331
  },
331
332
  impulse: (v) => {
332
333
  const copied = [...v];
@@ -334,6 +335,8 @@ export function physics(kit, opts) {
334
335
  },
335
336
  drop: () => call('drop body', (at, seq) => ({ at, seq, key, kind: 'drop' })),
336
337
  };
338
+ const self = bind(m, body);
339
+ const steer = bind(m, controls);
337
340
  keys.set(body, `body ${key}`);
338
341
  body.simulated = m.cue({
339
342
  patch: simulated,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@msb235/blits-rapier",
3
- "version": "0.7.1",
3
+ "version": "0.7.3",
4
4
  "description": "Pairs Rapier rigid-body physics with a blits mix: voices push bodies, and each body's simulated pose blends with authored motion",
5
5
  "keywords": [
6
6
  "physics",
@@ -45,7 +45,7 @@
45
45
  "devDependencies": {
46
46
  "@dimforge/rapier2d-compat": "0.21.0",
47
47
  "@dimforge/rapier3d-compat": "0.21.0",
48
- "@msb235/blits": "1.1.1"
48
+ "@msb235/blits": "1.3.0"
49
49
  },
50
50
  "peerDependenciesMeta": {
51
51
  "@dimforge/rapier2d-compat": {