@edv4h/usketch-plugin-character 0.2.3 → 0.3.1

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 (44) hide show
  1. package/README.md +35 -7
  2. package/dist/character-input.d.ts +9 -4
  3. package/dist/character-input.d.ts.map +1 -1
  4. package/dist/character-input.js +151 -11
  5. package/dist/character-input.js.map +1 -1
  6. package/dist/character-layer.d.ts +3 -1
  7. package/dist/character-layer.d.ts.map +1 -1
  8. package/dist/character-layer.js +29 -6
  9. package/dist/character-layer.js.map +1 -1
  10. package/dist/character-physics.d.ts +55 -2
  11. package/dist/character-physics.d.ts.map +1 -1
  12. package/dist/character-physics.js +90 -9
  13. package/dist/character-physics.js.map +1 -1
  14. package/dist/character-runtime.d.ts.map +1 -1
  15. package/dist/character-runtime.js +13 -5
  16. package/dist/character-runtime.js.map +1 -1
  17. package/dist/character-service.d.ts +6 -2
  18. package/dist/character-service.d.ts.map +1 -1
  19. package/dist/character-service.js +2 -0
  20. package/dist/character-service.js.map +1 -1
  21. package/dist/character-store.d.ts +8 -1
  22. package/dist/character-store.d.ts.map +1 -1
  23. package/dist/character-store.js +40 -4
  24. package/dist/character-store.js.map +1 -1
  25. package/dist/character-sync.d.ts +7 -1
  26. package/dist/character-sync.d.ts.map +1 -1
  27. package/dist/character-sync.js +13 -1
  28. package/dist/character-sync.js.map +1 -1
  29. package/dist/character-types.d.ts +13 -0
  30. package/dist/character-types.d.ts.map +1 -1
  31. package/dist/character-types.js +1 -0
  32. package/dist/character-types.js.map +1 -1
  33. package/dist/index.d.ts +1 -1
  34. package/dist/index.d.ts.map +1 -1
  35. package/dist/index.js +1 -1
  36. package/dist/index.js.map +1 -1
  37. package/dist/plugin.d.ts +7 -2
  38. package/dist/plugin.d.ts.map +1 -1
  39. package/dist/plugin.js +1 -0
  40. package/dist/plugin.js.map +1 -1
  41. package/dist/register-character-hud.d.ts.map +1 -1
  42. package/dist/register-character-hud.js +12 -0
  43. package/dist/register-character-hud.js.map +1 -1
  44. package/package.json +3 -3
package/README.md CHANGED
@@ -23,6 +23,7 @@ createCharacterPlugin({
23
23
  keys: { up: ["KeyW", "ArrowUp"] }, // KeyboardEvent.code values
24
24
  cameraMode: "rotate", // "fixed" | "rotate" | "free"
25
25
  controlScheme: "vehicle", // "directional" | "vehicle"
26
+ drift: true, // vehicle: Space + steer drifts (or tuning overrides)
26
27
  screenAnchor: { x: 0.5, y: 0.75 },
27
28
  });
28
29
  ```
@@ -32,8 +33,8 @@ createCharacterPlugin({
32
33
  - **Heading**: degrees, `0` = up (world −y), clockwise-positive — the same convention
33
34
  as CSS `rotate()` and the viewport `rotation`.
34
35
  - **Render props**: `heading` (world), `screenHeading` (= `heading + viewport.rotation`,
35
- what to rotate a top-down sprite by), `moving`, `speed`, `zoom`, `appearance`,
36
- `name`, `isSelf`, `id`. Each character is placed centered on its screen position
36
+ what to rotate a top-down sprite by), `moving`, `speed`, `steering`, `slip`,
37
+ `drifting`, `zoom`, `appearance`, `name`, `isSelf`, `id`, `elevation`. Each character is placed centered on its screen position
37
38
  in one screen-space layer, so self and remote characters look the same under zoom
38
39
  and camera rotation.
39
40
  - **Control schemes**
@@ -41,7 +42,26 @@ createCharacterPlugin({
41
42
  turns toward the movement at `turnRate`. With the `rotate` camera, left/right
42
43
  therefore circle (the camera follows the turn).
43
44
  - `vehicle` — up/down throttle and reverse, left/right steer. Steering scales
44
- with speed (a stopped car can't turn) and inverts in reverse.
45
+ with speed (a stopped car can't turn) and inverts in reverse. The held steering
46
+ (-1 … 1) is in the pose and render props, e.g. to turn the front wheels.
47
+ - **Drift** (`vehicle`, opt-in via `drift`): hold the drift key (Space) and steer at
48
+ speed to start an arcade drift toward the steering. It turns tighter than normal
49
+ steering and slides the body by `slip` degrees (draw the car at `heading + slip`;
50
+ it keeps traveling along `heading`). Steering into the drift tightens it,
51
+ countersteering opens it (never spins). Releasing the key, slowing below
52
+ `stopSpeed` or reversing ends it, and the slip eases back. Tuning (`DriftParams`):
53
+ `startSpeed` / `stopSpeed` (fractions of `moveSpeed`), `turnRate` / `steerRate`
54
+ (multiples of `turnRate`), `slipAngle` / `steerSlipAngle` (degrees), `recoveryRate`
55
+ (1/s). The drift key is only captured while drift is on.
56
+ - **Keyboard focus**: movement keys are captured on `window` while the character is
57
+ on, except where the page needs them: nothing is taken while a text field has focus
58
+ or focus is inside a dialog / menu (`dialog`, `role="dialog"`, `alertdialog`, `menu`;
59
+ a dialog that contains the board itself doesn't count), arrow keys are left to
60
+ widgets that use them (range / radio inputs, `role="slider"`, `radio`, `tab`,
61
+ `option`, `combobox`, `menubar` items, `grid`, `treeitem` …) while WASD keeps
62
+ driving, and Space is left to buttons, links and other controls it activates. Focus
63
+ is read through `composedPath()`, so web-component dialogs count too. Moving focus
64
+ to such a target releases the held keys it uses.
45
65
  - **Camera modes**
46
66
  - `fixed` — follow, world stays upright.
47
67
  - `rotate` — follow and turn the world by `-heading` (character always faces up).
@@ -51,8 +71,15 @@ createCharacterPlugin({
51
71
  following. Turning the character off turns the camera back upright.
52
72
  - **Multiplayer**: pass `wsProvider` (anything with a y-protocols `awareness`). Your
53
73
  character is published under the `character` awareness field (~20 Hz, only when it
54
- changes) and others are eased between updates. It's ephemeral: a character
74
+ changes, including `steering`, `slip` and `drifting`) and others are eased between
75
+ updates. It's ephemeral: a character
55
76
  vanishes when its owner disconnects or turns it off. Nothing is stored as shapes.
77
+ - **Ground height**: when a plugin provides `groundHeightService` (from
78
+ `@edv4h/usketch-shared`, e.g. the map plugin's raised terrain), moving onto
79
+ ground more than `motion.maxStep` (default 24 world units, HUD "登れる段差") higher
80
+ than where the character stands is blocked; it slides along the cliff instead.
81
+ Stepping down is always allowed. The render props carry `elevation`, and under a
82
+ 3D view (Mode 7) the character is lifted onto the ground it stands on.
56
83
  - **Input**: held keys are tracked from window `keydown`/`keyup` (capture phase,
57
84
  `event.code`), swallowed while the character is on so single-letter tool
58
85
  shortcuts don't fire. Typing in text fields, and key chords with Ctrl/Cmd/Alt,
@@ -60,8 +87,8 @@ createCharacterPlugin({
60
87
 
61
88
  ## HUD
62
89
 
63
- A "キャラクター" settings group (on/off, camera, scheme, speed, turn rate, screen
64
- position, camera lag) plus actions to toggle the character and to place it at the
90
+ A "キャラクター" settings group (on/off, camera, scheme, drift, speed, turn rate,
91
+ climbable step, screen position, camera lag) plus actions to toggle the character and to place it at the
65
92
  screen position.
66
93
 
67
94
  ## Service
@@ -73,7 +100,8 @@ const api = getCharacterApi(app.services);
73
100
  api?.enable();
74
101
  api?.setCameraMode("rotate");
75
102
  api?.setRenderer(myRenderer);
76
- api?.getPose(); // { x, y, heading, speed, moving }
103
+ api?.setDrift({ slipAngle: 35 }); // true / false / tuning overrides
104
+ api?.getPose(); // { x, y, heading, speed, moving, steering, slip, drift }
77
105
  ```
78
106
 
79
107
  ## Limitations
@@ -1,7 +1,7 @@
1
1
  import type { MoveInput } from "./character-physics.js";
2
2
  import type { CharacterKeys } from "./character-types.js";
3
3
  export interface KeyInput {
4
- /** The currently held directions. */
4
+ /** The currently held directions (and the drift key). */
5
5
  read(): MoveInput;
6
6
  /** Whether any bound key is held. */
7
7
  anyHeld(): boolean;
@@ -11,8 +11,13 @@ export interface KeyInput {
11
11
  }
12
12
  /**
13
13
  * Listen for the bound keys on `window`. `isActive()` gates everything: while it is
14
- * false no key is captured (and none is swallowed). Held keys are cleared on window
15
- * blur / tab hide so a key released elsewhere can't get stuck "down".
14
+ * false no key is captured (and none is swallowed). Keys are left alone while focus is
15
+ * in a text field or inside a dialog / menu, arrow keys while a widget that uses them
16
+ * (slider, radio, tab …) has focus, and the drift key on controls Space activates.
17
+ * Held keys are cleared on window blur and tab hide, and released when focus moves to
18
+ * a target that uses them, so a key released elsewhere can't get stuck "down".
16
19
  */
17
- export declare function createKeyInput(initialKeys: CharacterKeys, isActive: () => boolean): KeyInput;
20
+ export declare function createKeyInput(initialKeys: CharacterKeys, isActive: () => boolean,
21
+ /** Whether the drift key does anything now (else it is left to the host, e.g. Space-pan). */
22
+ isDriftActive?: () => boolean): KeyInput;
18
23
  //# sourceMappingURL=character-input.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"character-input.d.ts","sourceRoot":"","sources":["../src/character-input.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACxD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAE1D,MAAM,WAAW,QAAQ;IACxB,qCAAqC;IACrC,IAAI,IAAI,SAAS,CAAC;IAClB,qCAAqC;IACrC,OAAO,IAAI,OAAO,CAAC;IACnB,wDAAwD;IACxD,OAAO,CAAC,IAAI,EAAE,aAAa,GAAG,IAAI,CAAC;IACnC,OAAO,IAAI,IAAI,CAAC;CAChB;AAuBD;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,WAAW,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,OAAO,GAAG,QAAQ,CA6D5F"}
1
+ {"version":3,"file":"character-input.d.ts","sourceRoot":"","sources":["../src/character-input.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACxD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAE1D,MAAM,WAAW,QAAQ;IACxB,yDAAyD;IACzD,IAAI,IAAI,SAAS,CAAC;IAClB,qCAAqC;IACrC,OAAO,IAAI,OAAO,CAAC;IACnB,wDAAwD;IACxD,OAAO,CAAC,IAAI,EAAE,aAAa,GAAG,IAAI,CAAC;IACnC,OAAO,IAAI,IAAI,CAAC;CAChB;AAkJD;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAC7B,WAAW,EAAE,aAAa,EAC1B,QAAQ,EAAE,MAAM,OAAO;AACvB,6FAA6F;AAC7F,aAAa,GAAE,MAAM,OAAqB,GACxC,QAAQ,CAwFV"}
@@ -10,9 +10,115 @@ const NON_TEXT_INPUTS = new Set([
10
10
  "file",
11
11
  "image",
12
12
  ]);
13
- function isTextInput(target) {
13
+ /** ARIA widgets Space activates or types into. */
14
+ const SPACE_ROLES = new Set([
15
+ "button",
16
+ "checkbox",
17
+ "combobox",
18
+ "link",
19
+ "menuitem",
20
+ "menuitemcheckbox",
21
+ "menuitemradio",
22
+ "option",
23
+ "radio",
24
+ "slider",
25
+ "switch",
26
+ "tab",
27
+ "textbox",
28
+ ]);
29
+ const asElement = (target) => {
14
30
  const el = target;
15
- if (!el || typeof el.tagName !== "string")
31
+ return el && typeof el.tagName === "string" ? el : null;
32
+ };
33
+ /**
34
+ * The focused element and its ancestors, innermost first. `composedPath()` reaches into
35
+ * (open) shadow roots, so a web-component dialog or slider is seen as itself rather than
36
+ * as its retargeted host; without it, the light-DOM parent chain.
37
+ */
38
+ function focusPath(e) {
39
+ const raw = typeof e.composedPath === "function" ? e.composedPath() : [];
40
+ const path = raw.map(asElement).filter((el) => el !== null);
41
+ if (path.length > 0)
42
+ return path;
43
+ const chain = [];
44
+ for (let el = asElement(e.target); el; el = asElement(el.parentElement))
45
+ chain.push(el);
46
+ return chain;
47
+ }
48
+ const roleOf = (el) => el && typeof el.getAttribute === "function" ? el.getAttribute("role") : null;
49
+ /** Elements Space activates (or types into): the drift key must not steal it from them. */
50
+ function isSpaceTarget(el) {
51
+ if (!el)
52
+ return false;
53
+ if (["INPUT", "TEXTAREA", "SELECT", "BUTTON", "A", "SUMMARY"].includes(el.tagName))
54
+ return true;
55
+ if (el.isContentEditable === true)
56
+ return true;
57
+ const role = roleOf(el);
58
+ return role !== null && SPACE_ROLES.has(role);
59
+ }
60
+ /**
61
+ * Overlays that own the keyboard while focus is inside them (a dialog or menu opened
62
+ * mid-drive). Persistent containers such as a menubar or a sidebar listbox are not
63
+ * here: their items are arrow-key widgets, which keep WASD driving.
64
+ */
65
+ const KEY_OWNER_SELECTOR = 'dialog, [role="dialog"], [role="alertdialog"], [role="menu"]';
66
+ /** Marks the board's layers, to tell a host dialog that wraps the whole board apart. */
67
+ const BOARD_SELECTOR = "[data-layer-id]";
68
+ /** `<input type>`s that move their value or selection with the arrow keys. */
69
+ const ARROW_INPUTS = new Set(["range", "radio"]);
70
+ /** ARIA widgets (and composite containers that keep focus) that use the arrow keys. */
71
+ const ARROW_ROLES = new Set([
72
+ "combobox",
73
+ "grid",
74
+ "gridcell",
75
+ "listbox",
76
+ "menubar",
77
+ "menuitem",
78
+ "menuitemcheckbox",
79
+ "menuitemradio",
80
+ "option",
81
+ "radio",
82
+ "radiogroup",
83
+ "scrollbar",
84
+ "separator",
85
+ "slider",
86
+ "spinbutton",
87
+ "tab",
88
+ "tablist",
89
+ "toolbar",
90
+ "tree",
91
+ "treegrid",
92
+ "treeitem",
93
+ ]);
94
+ /**
95
+ * Focus is inside a dialog or menu: every bound key is left to it. A dialog that holds
96
+ * the board itself (the host shows the board in a modal) doesn't count, or the
97
+ * character could never be driven there.
98
+ */
99
+ function isInKeyOwner(path) {
100
+ const owner = path.find((el) => typeof el.matches === "function" && el.matches(KEY_OWNER_SELECTOR));
101
+ if (!owner)
102
+ return false;
103
+ return typeof owner.querySelector !== "function" || owner.querySelector(BOARD_SELECTOR) === null;
104
+ }
105
+ /** The focused element uses the arrow keys itself, so arrow bindings are left to it. */
106
+ function isArrowTarget(el) {
107
+ if (!el)
108
+ return false;
109
+ if (el.tagName === "INPUT" && ARROW_INPUTS.has((el.type ?? "").toLowerCase()))
110
+ return true;
111
+ const role = roleOf(el);
112
+ return role !== null && ARROW_ROLES.has(role);
113
+ }
114
+ /** Whether a key acts as an arrow (by code, or by key: numpad 4/6 with NumLock off). */
115
+ const isArrowKey = (code, key) => code.startsWith("Arrow") || (key ?? "").startsWith("Arrow");
116
+ /** Focus where no bound key may be taken: typing, or a dialog / menu. */
117
+ function blocksAllKeys(path) {
118
+ return isTextInput(path[0]) || isInKeyOwner(path);
119
+ }
120
+ function isTextInput(el) {
121
+ if (!el)
16
122
  return false;
17
123
  const tag = el.tagName;
18
124
  if (tag === "INPUT")
@@ -21,27 +127,43 @@ function isTextInput(target) {
21
127
  }
22
128
  /**
23
129
  * Listen for the bound keys on `window`. `isActive()` gates everything: while it is
24
- * false no key is captured (and none is swallowed). Held keys are cleared on window
25
- * blur / tab hide so a key released elsewhere can't get stuck "down".
130
+ * false no key is captured (and none is swallowed). Keys are left alone while focus is
131
+ * in a text field or inside a dialog / menu, arrow keys while a widget that uses them
132
+ * (slider, radio, tab …) has focus, and the drift key on controls Space activates.
133
+ * Held keys are cleared on window blur and tab hide, and released when focus moves to
134
+ * a target that uses them, so a key released elsewhere can't get stuck "down".
26
135
  */
27
- export function createKeyInput(initialKeys, isActive) {
136
+ export function createKeyInput(initialKeys, isActive,
137
+ /** Whether the drift key does anything now (else it is left to the host, e.g. Space-pan). */
138
+ isDriftActive = () => false) {
28
139
  let keys = initialKeys;
29
- const held = new Set();
140
+ /** Held codes → the `key` they produced (to tell numpad arrows from digits). */
141
+ const held = new Map();
30
142
  const directionOf = (code) => {
31
143
  for (const dir of ["up", "down", "left", "right"]) {
32
144
  if (keys[dir].includes(code))
33
145
  return dir;
34
146
  }
147
+ if (keys.drift?.includes(code) && isDriftActive())
148
+ return "drift";
35
149
  return null;
36
150
  };
37
151
  const onKeyDown = (e) => {
38
- if (!isActive() || isTextInput(e.target))
152
+ if (!isActive())
39
153
  return;
40
154
  if (e.ctrlKey || e.metaKey || e.altKey)
41
155
  return; // leave chords (Cmd+S …) alone
42
- if (!directionOf(e.code))
156
+ const dir = directionOf(e.code);
157
+ if (!dir)
158
+ return;
159
+ const path = focusPath(e);
160
+ if (blocksAllKeys(path))
43
161
  return;
44
- held.add(e.code);
162
+ if (dir === "drift" && isSpaceTarget(path[0]))
163
+ return;
164
+ if (isArrowKey(e.code, e.key) && isArrowTarget(path[0]))
165
+ return;
166
+ held.set(e.code, e.key ?? "");
45
167
  e.preventDefault();
46
168
  e.stopImmediatePropagation();
47
169
  };
@@ -56,24 +178,41 @@ export function createKeyInput(initialKeys, isActive) {
56
178
  if (typeof document !== "undefined" && document.hidden)
57
179
  clear();
58
180
  };
181
+ // Focus moving to a target that uses a held key hands that key to it: release it, or
182
+ // the character keeps going and the key's keyup is swallowed (a button that Space
183
+ // activates on keyup would never fire). Keys the new target ignores stay held.
184
+ const onFocusIn = (e) => {
185
+ const path = focusPath(e);
186
+ if (blocksAllKeys(path)) {
187
+ clear();
188
+ return;
189
+ }
190
+ const owned = [...held].filter(([code, key]) => (isArrowKey(code, key) && isArrowTarget(path[0])) ||
191
+ ((keys.drift?.includes(code) ?? false) && isSpaceTarget(path[0])));
192
+ for (const [code] of owned)
193
+ held.delete(code);
194
+ };
59
195
  const hasWindow = typeof window !== "undefined";
60
196
  if (hasWindow) {
61
197
  window.addEventListener("keydown", onKeyDown, true);
62
198
  window.addEventListener("keyup", onKeyUp, true);
63
199
  window.addEventListener("blur", clear);
64
200
  document.addEventListener("visibilitychange", onVisibility);
201
+ document.addEventListener("focusin", onFocusIn);
65
202
  }
66
- const isHeld = (dir) => keys[dir].some((c) => held.has(c));
203
+ const isHeld = (dir) => keys[dir]?.some((c) => held.has(c)) ?? false;
67
204
  return {
68
205
  read: () => ({
69
206
  up: isHeld("up"),
70
207
  down: isHeld("down"),
71
208
  left: isHeld("left"),
72
209
  right: isHeld("right"),
210
+ drift: isHeld("drift"),
73
211
  }),
74
212
  anyHeld: () => held.size > 0,
75
213
  setKeys(next) {
76
- keys = next;
214
+ // Rebinding movement keeps the drift key unless `drift` is given (`[]` unbinds).
215
+ keys = { ...next, drift: next.drift ?? keys.drift };
77
216
  held.clear();
78
217
  },
79
218
  dispose() {
@@ -83,6 +222,7 @@ export function createKeyInput(initialKeys, isActive) {
83
222
  window.removeEventListener("keyup", onKeyUp, true);
84
223
  window.removeEventListener("blur", clear);
85
224
  document.removeEventListener("visibilitychange", onVisibility);
225
+ document.removeEventListener("focusin", onFocusIn);
86
226
  },
87
227
  };
88
228
  }
@@ -1 +1 @@
1
- {"version":3,"file":"character-input.js","sourceRoot":"","sources":["../src/character-input.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"character-input.js","sourceRoot":"","sources":["../src/character-input.ts"],"names":[],"mappings":"AAkBA,6FAA6F;AAC7F,MAAM,eAAe,GAAG,IAAI,GAAG,CAAC;IAC/B,UAAU;IACV,OAAO;IACP,QAAQ;IACR,QAAQ;IACR,OAAO;IACP,OAAO;IACP,OAAO;IACP,MAAM;IACN,OAAO;CACP,CAAC,CAAC;AAEH,kDAAkD;AAClD,MAAM,WAAW,GAAG,IAAI,GAAG,CAAC;IAC3B,QAAQ;IACR,UAAU;IACV,UAAU;IACV,MAAM;IACN,UAAU;IACV,kBAAkB;IAClB,eAAe;IACf,QAAQ;IACR,OAAO;IACP,QAAQ;IACR,QAAQ;IACR,KAAK;IACL,SAAS;CACT,CAAC,CAAC;AAUH,MAAM,SAAS,GAAG,CAAC,MAAsC,EAAsB,EAAE;IAChF,MAAM,EAAE,GAAG,MAAwC,CAAC;IACpD,OAAO,EAAE,IAAI,OAAO,EAAE,CAAC,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;AACzD,CAAC,CAAC;AAEF;;;;GAIG;AACH,SAAS,SAAS,CAAC,CAAQ;IAC1B,MAAM,GAAG,GAAG,OAAO,CAAC,CAAC,YAAY,KAAK,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,YAAY,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IACzE,MAAM,IAAI,GAAG,GAAG,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE,EAAqB,EAAE,CAAC,EAAE,KAAK,IAAI,CAAC,CAAC;IAC/E,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,IAAI,CAAC;IACjC,MAAM,KAAK,GAAkB,EAAE,CAAC;IAChC,KAAK,IAAI,EAAE,GAAG,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,EAAE,EAAE,EAAE,GAAG,SAAS,CAAC,EAAE,CAAC,aAAa,CAAC;QAAE,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACxF,OAAO,KAAK,CAAC;AACd,CAAC;AAED,MAAM,MAAM,GAAG,CAAC,EAA2B,EAAiB,EAAE,CAC7D,EAAE,IAAI,OAAO,EAAE,CAAC,YAAY,KAAK,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;AAE9E,2FAA2F;AAC3F,SAAS,aAAa,CAAC,EAA2B;IACjD,IAAI,CAAC,EAAE;QAAE,OAAO,KAAK,CAAC;IACtB,IAAI,CAAC,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,QAAQ,EAAE,GAAG,EAAE,SAAS,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,OAAO,CAAC;QAAE,OAAO,IAAI,CAAC;IAChG,IAAI,EAAE,CAAC,iBAAiB,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IAC/C,MAAM,IAAI,GAAG,MAAM,CAAC,EAAE,CAAC,CAAC;IACxB,OAAO,IAAI,KAAK,IAAI,IAAI,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;AAC/C,CAAC;AAED;;;;GAIG;AACH,MAAM,kBAAkB,GAAG,8DAA8D,CAAC;AAE1F,wFAAwF;AACxF,MAAM,cAAc,GAAG,iBAAiB,CAAC;AAEzC,8EAA8E;AAC9E,MAAM,YAAY,GAAG,IAAI,GAAG,CAAC,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC;AAEjD,uFAAuF;AACvF,MAAM,WAAW,GAAG,IAAI,GAAG,CAAC;IAC3B,UAAU;IACV,MAAM;IACN,UAAU;IACV,SAAS;IACT,SAAS;IACT,UAAU;IACV,kBAAkB;IAClB,eAAe;IACf,QAAQ;IACR,OAAO;IACP,YAAY;IACZ,WAAW;IACX,WAAW;IACX,QAAQ;IACR,YAAY;IACZ,KAAK;IACL,SAAS;IACT,SAAS;IACT,MAAM;IACN,UAAU;IACV,UAAU;CACV,CAAC,CAAC;AAEH;;;;GAIG;AACH,SAAS,YAAY,CAAC,IAA4B;IACjD,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,CACtB,CAAC,EAAE,EAAE,EAAE,CAAC,OAAO,EAAE,CAAC,OAAO,KAAK,UAAU,IAAI,EAAE,CAAC,OAAO,CAAC,kBAAkB,CAAC,CAC1E,CAAC;IACF,IAAI,CAAC,KAAK;QAAE,OAAO,KAAK,CAAC;IACzB,OAAO,OAAO,KAAK,CAAC,aAAa,KAAK,UAAU,IAAI,KAAK,CAAC,aAAa,CAAC,cAAc,CAAC,KAAK,IAAI,CAAC;AAClG,CAAC;AAED,wFAAwF;AACxF,SAAS,aAAa,CAAC,EAA2B;IACjD,IAAI,CAAC,EAAE;QAAE,OAAO,KAAK,CAAC;IACtB,IAAI,EAAE,CAAC,OAAO,KAAK,OAAO,IAAI,YAAY,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC;QAAE,OAAO,IAAI,CAAC;IAC3F,MAAM,IAAI,GAAG,MAAM,CAAC,EAAE,CAAC,CAAC;IACxB,OAAO,IAAI,KAAK,IAAI,IAAI,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;AAC/C,CAAC;AAED,wFAAwF;AACxF,MAAM,UAAU,GAAG,CAAC,IAAY,EAAE,GAAuB,EAAW,EAAE,CACrE,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,EAAE,CAAC,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;AAE7D,yEAAyE;AACzE,SAAS,aAAa,CAAC,IAA4B;IAClD,OAAO,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,YAAY,CAAC,IAAI,CAAC,CAAC;AACnD,CAAC;AAED,SAAS,WAAW,CAAC,EAA2B;IAC/C,IAAI,CAAC,EAAE;QAAE,OAAO,KAAK,CAAC;IACtB,MAAM,GAAG,GAAG,EAAE,CAAC,OAAO,CAAC;IACvB,IAAI,GAAG,KAAK,OAAO;QAAE,OAAO,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,IAAI,IAAI,MAAM,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC;IACpF,OAAO,GAAG,KAAK,UAAU,IAAI,GAAG,KAAK,QAAQ,IAAI,EAAE,CAAC,iBAAiB,KAAK,IAAI,CAAC;AAChF,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,cAAc,CAC7B,WAA0B,EAC1B,QAAuB;AACvB,6FAA6F;AAC7F,aAAa,GAAkB,GAAG,EAAE,CAAC,KAAK;IAE1C,IAAI,IAAI,GAAG,WAAW,CAAC;IACvB,gFAAgF;IAChF,MAAM,IAAI,GAAG,IAAI,GAAG,EAAkB,CAAC;IAEvC,MAAM,WAAW,GAAG,CAAC,IAAY,EAA8B,EAAE;QAChE,KAAK,MAAM,GAAG,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,CAAU,EAAE,CAAC;YAC5D,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC;gBAAE,OAAO,GAAG,CAAC;QAC1C,CAAC;QACD,IAAI,IAAI,CAAC,KAAK,EAAE,QAAQ,CAAC,IAAI,CAAC,IAAI,aAAa,EAAE;YAAE,OAAO,OAAO,CAAC;QAClE,OAAO,IAAI,CAAC;IACb,CAAC,CAAC;IAEF,MAAM,SAAS,GAAG,CAAC,CAAgB,EAAQ,EAAE;QAC5C,IAAI,CAAC,QAAQ,EAAE;YAAE,OAAO;QACxB,IAAI,CAAC,CAAC,OAAO,IAAI,CAAC,CAAC,OAAO,IAAI,CAAC,CAAC,MAAM;YAAE,OAAO,CAAC,+BAA+B;QAC/E,MAAM,GAAG,GAAG,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QAChC,IAAI,CAAC,GAAG;YAAE,OAAO;QACjB,MAAM,IAAI,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC;QAC1B,IAAI,aAAa,CAAC,IAAI,CAAC;YAAE,OAAO;QAChC,IAAI,GAAG,KAAK,OAAO,IAAI,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAAE,OAAO;QACtD,IAAI,UAAU,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,IAAI,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAAE,OAAO;QAChE,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,EAAE,CAAC,CAAC;QAC9B,CAAC,CAAC,cAAc,EAAE,CAAC;QACnB,CAAC,CAAC,wBAAwB,EAAE,CAAC;IAC9B,CAAC,CAAC;IAEF,MAAM,OAAO,GAAG,CAAC,CAAgB,EAAQ,EAAE;QAC1C,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC;YAAE,OAAO;QACjC,CAAC,CAAC,cAAc,EAAE,CAAC;QACnB,CAAC,CAAC,wBAAwB,EAAE,CAAC;IAC9B,CAAC,CAAC;IAEF,MAAM,KAAK,GAAG,GAAS,EAAE,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;IACvC,MAAM,YAAY,GAAG,GAAS,EAAE;QAC/B,IAAI,OAAO,QAAQ,KAAK,WAAW,IAAI,QAAQ,CAAC,MAAM;YAAE,KAAK,EAAE,CAAC;IACjE,CAAC,CAAC;IACF,qFAAqF;IACrF,kFAAkF;IAClF,+EAA+E;IAC/E,MAAM,SAAS,GAAG,CAAC,CAAa,EAAQ,EAAE;QACzC,MAAM,IAAI,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC;QAC1B,IAAI,aAAa,CAAC,IAAI,CAAC,EAAE,CAAC;YACzB,KAAK,EAAE,CAAC;YACR,OAAO;QACR,CAAC;QACD,MAAM,KAAK,GAAG,CAAC,GAAG,IAAI,CAAC,CAAC,MAAM,CAC7B,CAAC,CAAC,IAAI,EAAE,GAAG,CAAC,EAAE,EAAE,CACf,CAAC,UAAU,CAAC,IAAI,EAAE,GAAG,CAAC,IAAI,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;YACjD,CAAC,CAAC,IAAI,CAAC,KAAK,EAAE,QAAQ,CAAC,IAAI,CAAC,IAAI,KAAK,CAAC,IAAI,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAClE,CAAC;QACF,KAAK,MAAM,CAAC,IAAI,CAAC,IAAI,KAAK;YAAE,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IAC/C,CAAC,CAAC;IAEF,MAAM,SAAS,GAAG,OAAO,MAAM,KAAK,WAAW,CAAC;IAChD,IAAI,SAAS,EAAE,CAAC;QACf,MAAM,CAAC,gBAAgB,CAAC,SAAS,EAAE,SAAS,EAAE,IAAI,CAAC,CAAC;QACpD,MAAM,CAAC,gBAAgB,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;QAChD,MAAM,CAAC,gBAAgB,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;QACvC,QAAQ,CAAC,gBAAgB,CAAC,kBAAkB,EAAE,YAAY,CAAC,CAAC;QAC5D,QAAQ,CAAC,gBAAgB,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;IACjD,CAAC;IAED,MAAM,MAAM,GAAG,CAAC,GAAwB,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC;IAE1F,OAAO;QACN,IAAI,EAAE,GAAG,EAAE,CAAC,CAAC;YACZ,EAAE,EAAE,MAAM,CAAC,IAAI,CAAC;YAChB,IAAI,EAAE,MAAM,CAAC,MAAM,CAAC;YACpB,IAAI,EAAE,MAAM,CAAC,MAAM,CAAC;YACpB,KAAK,EAAE,MAAM,CAAC,OAAO,CAAC;YACtB,KAAK,EAAE,MAAM,CAAC,OAAO,CAAC;SACtB,CAAC;QACF,OAAO,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC;QAC5B,OAAO,CAAC,IAAI;YACX,iFAAiF;YACjF,IAAI,GAAG,EAAE,GAAG,IAAI,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YACpD,IAAI,CAAC,KAAK,EAAE,CAAC;QACd,CAAC;QACD,OAAO;YACN,IAAI,CAAC,SAAS;gBAAE,OAAO;YACvB,MAAM,CAAC,mBAAmB,CAAC,SAAS,EAAE,SAAS,EAAE,IAAI,CAAC,CAAC;YACvD,MAAM,CAAC,mBAAmB,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;YACnD,MAAM,CAAC,mBAAmB,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;YAC1C,QAAQ,CAAC,mBAAmB,CAAC,kBAAkB,EAAE,YAAY,CAAC,CAAC;YAC/D,QAAQ,CAAC,mBAAmB,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;QACpD,CAAC;KACD,CAAC;AACH,CAAC"}
@@ -1,7 +1,9 @@
1
1
  import { type Viewport } from "@edv4h/usketch-shared";
2
+ import type { HeightAt } from "./character-physics.js";
2
3
  import type { CharacterStore } from "./character-store.js";
3
- export declare function CharacterLayer({ store, viewport }: {
4
+ export declare function CharacterLayer({ store, viewport, heightAt, }: {
4
5
  store: CharacterStore;
5
6
  viewport: Viewport;
7
+ heightAt?: HeightAt;
6
8
  }): import("react").JSX.Element | null;
7
9
  //# sourceMappingURL=character-layer.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"character-layer.d.ts","sourceRoot":"","sources":["../src/character-layer.tsx"],"names":[],"mappings":"AAKA,OAAO,EAAE,KAAK,QAAQ,EAA4C,MAAM,uBAAuB,CAAC;AAEhG,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AA0B3D,wBAAgB,cAAc,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE;IAAE,KAAK,EAAE,cAAc,CAAC;IAAC,QAAQ,EAAE,QAAQ,CAAA;CAAE,sCAuDhG"}
1
+ {"version":3,"file":"character-layer.d.ts","sourceRoot":"","sources":["../src/character-layer.tsx"],"names":[],"mappings":"AAKA,OAAO,EAAE,KAAK,QAAQ,EAA4C,MAAM,uBAAuB,CAAC;AAEhG,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AACvD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAsC3D,wBAAgB,cAAc,CAAC,EAC9B,KAAK,EACL,QAAQ,EACR,QAAQ,GACR,EAAE;IACF,KAAK,EAAE,cAAc,CAAC;IACtB,QAAQ,EAAE,QAAQ,CAAC;IACnB,QAAQ,CAAC,EAAE,QAAQ,CAAC;CACpB,sCA+EA"}
@@ -6,10 +6,18 @@ import { jsx as _jsx } from "react/jsx-runtime";
6
6
  // `screenHeading` math under camera rotation).
7
7
  import { viewportRotation, worldToScreen, wrapDeg } from "@edv4h/usketch-shared";
8
8
  import { useSyncExternalStore } from "react";
9
- function Spot({ x, y, renderer, props, }) {
10
- return (_jsx("div", { "data-character-id": props.id, style: { position: "absolute", left: x, top: y, width: 0, height: 0, pointerEvents: "none" }, children: _jsx("div", { style: { position: "absolute", left: 0, top: 0, transform: "translate(-50%, -50%)" }, children: renderer(props) }) }));
9
+ function Spot({ x, y, lift, renderer, props, }) {
10
+ return (_jsx("div", { "data-character-id": props.id, style: {
11
+ position: "absolute",
12
+ left: x,
13
+ top: y,
14
+ width: 0,
15
+ height: 0,
16
+ pointerEvents: "none",
17
+ transform: lift > 0 ? `translateZ(${lift}px)` : undefined,
18
+ }, children: _jsx("div", { style: { position: "absolute", left: 0, top: 0, transform: "translate(-50%, -50%)" }, children: renderer(props) }) }));
11
19
  }
12
- export function CharacterLayer({ store, viewport }) {
20
+ export function CharacterLayer({ store, viewport, heightAt, }) {
13
21
  const state = useSyncExternalStore(store.subscribe, store.getState, store.getState);
14
22
  const renderer = store.getRenderer();
15
23
  if (!renderer)
@@ -18,36 +26,51 @@ export function CharacterLayer({ store, viewport }) {
18
26
  const spots = [];
19
27
  for (const r of state.remotes.values()) {
20
28
  const p = worldToScreen(r.x, r.y, viewport);
21
- spots.push(_jsx(Spot, { x: p.x, y: p.y, renderer: renderer, props: {
29
+ const elevation = heightAt?.(r.x, r.y) ?? 0;
30
+ spots.push(_jsx(Spot, { x: p.x, y: p.y, lift: elevation * viewport.zoom, renderer: renderer, props: {
22
31
  id: r.id,
23
32
  isSelf: false,
24
33
  heading: r.heading,
25
34
  screenHeading: wrapDeg(r.heading + rot),
26
35
  moving: r.moving,
27
36
  speed: r.speed,
37
+ steering: r.steering,
38
+ slip: r.slip,
39
+ drifting: r.drifting,
28
40
  zoom: viewport.zoom,
29
41
  appearance: r.appearance,
30
42
  name: r.name,
43
+ elevation,
31
44
  } }, `remote-${r.id}`));
32
45
  }
33
46
  if (state.enabled && state.spawned) {
34
47
  const { pose } = state;
35
48
  const p = worldToScreen(pose.x, pose.y, viewport);
49
+ const elevation = heightAt?.(pose.x, pose.y) ?? 0;
36
50
  // Self last → drawn on top of the others.
37
- spots.push(_jsx(Spot, { x: p.x, y: p.y, renderer: renderer, props: {
51
+ spots.push(_jsx(Spot, { x: p.x, y: p.y, lift: elevation * viewport.zoom, renderer: renderer, props: {
38
52
  id: "self",
39
53
  isSelf: true,
40
54
  heading: pose.heading,
41
55
  screenHeading: wrapDeg(pose.heading + rot),
42
56
  moving: pose.moving,
43
57
  speed: pose.speed,
58
+ steering: pose.steering,
59
+ slip: pose.slip,
60
+ drifting: pose.drift !== 0,
44
61
  zoom: viewport.zoom,
45
62
  appearance: state.appearance,
46
63
  name: state.name,
64
+ elevation,
47
65
  } }, "self"));
48
66
  }
49
67
  if (spots.length === 0)
50
68
  return null;
51
- return _jsx("div", { style: { position: "absolute", inset: 0, pointerEvents: "none" }, children: spots });
69
+ return (_jsx("div", { style: {
70
+ position: "absolute",
71
+ inset: 0,
72
+ pointerEvents: "none",
73
+ transformStyle: "preserve-3d",
74
+ }, children: spots }));
52
75
  }
53
76
  //# sourceMappingURL=character-layer.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"character-layer.js","sourceRoot":"","sources":["../src/character-layer.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"character-layer.js","sourceRoot":"","sources":["../src/character-layer.tsx"],"names":[],"mappings":"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"}
@@ -5,6 +5,8 @@ export interface MoveInput {
5
5
  down: boolean;
6
6
  left: boolean;
7
7
  right: boolean;
8
+ /** Vehicle: the drift key (only acts when drift is enabled). */
9
+ drift?: boolean;
8
10
  }
9
11
  export declare const NO_INPUT: MoveInput;
10
12
  export interface CharacterPose {
@@ -17,7 +19,18 @@ export interface CharacterPose {
17
19
  speed: number;
18
20
  /** Whether the character moved this step. */
19
21
  moving: boolean;
22
+ /** Vehicle: the held steering, -1 (left) … 1 (right). 0 for `directional`. */
23
+ steering: number;
24
+ /**
25
+ * Vehicle: body yaw relative to `heading`, degrees (clockwise-positive). The car
26
+ * travels along `heading` but is drawn at `heading + slip` while drifting.
27
+ */
28
+ slip: number;
29
+ /** Vehicle: the running drift's direction, -1 (left) / 1 (right), 0 = not drifting. */
30
+ drift: -1 | 0 | 1;
20
31
  }
32
+ /** A pose at rest at the origin, facing up. */
33
+ export declare const ORIGIN_POSE: CharacterPose;
21
34
  export interface MotionParams {
22
35
  /** Top speed, world units / s. */
23
36
  moveSpeed: number;
@@ -29,8 +42,37 @@ export interface MotionParams {
29
42
  friction: number;
30
43
  /** Vehicle: reverse top speed as a fraction of `moveSpeed`. */
31
44
  reverseRatio: number;
45
+ /** Tallest step up the character can climb, world units (ground height, e.g. the map
46
+ * plugin's raised terrain). Stepping DOWN is always allowed. */
47
+ maxStep: number;
32
48
  }
33
49
  export declare const DEFAULT_MOTION: MotionParams;
50
+ /**
51
+ * Vehicle drift tuning: holding the drift key while steering at speed starts an
52
+ * arcade drift (a tighter turn with the body slid into it); releasing the key,
53
+ * slowing down or reversing ends it, and the slip eases back.
54
+ */
55
+ export interface DriftParams {
56
+ /** Speed that starts a drift, as a fraction of `moveSpeed`. */
57
+ startSpeed: number;
58
+ /** Speed below which a drift ends, as a fraction of `moveSpeed`. */
59
+ stopSpeed: number;
60
+ /** Turn rate while drifting, as a multiple of `turnRate`. */
61
+ turnRate: number;
62
+ /**
63
+ * How much steering tightens (into the drift) or opens (against it) the turn,
64
+ * as a multiple of `turnRate`. Capped at the drift `turnRate`, so
65
+ * countersteering never turns the car the other way.
66
+ */
67
+ steerRate: number;
68
+ /** Body slip while drifting, degrees. */
69
+ slipAngle: number;
70
+ /** Extra slip when steering into the drift, degrees. */
71
+ steerSlipAngle: number;
72
+ /** How fast the slip follows its target (1/s, exponential). */
73
+ recoveryRate: number;
74
+ }
75
+ export declare const DEFAULT_DRIFT: DriftParams;
34
76
  /** Unit vector of a heading in world space (0° → (0, -1), 90° → (1, 0)). */
35
77
  export declare function headingVector(deg: number): {
36
78
  x: number;
@@ -49,7 +91,18 @@ export declare function turnToward(from: number, to: number, maxStep: number): n
49
91
  * rather than snapping keeps a heading-following camera from spinning.)
50
92
  * - `vehicle`: up/down are throttle/reverse along the heading, left/right steer.
51
93
  * Steering authority scales with speed (a stopped car can't turn) and inverts
52
- * when reversing, like a car.
94
+ * when reversing, like a car. With `driftParams`, holding the drift key while
95
+ * steering at speed drifts (see `DriftParams`).
96
+ */
97
+ export declare function stepCharacter(pose: CharacterPose, input: MoveInput, dt: number, scheme: ControlScheme, params: MotionParams, cameraRotation?: number, driftParams?: DriftParams | null): CharacterPose;
98
+ /** Ground height at a world point (world units; see `groundHeightService`). */
99
+ export type HeightAt = (x: number, y: number) => number;
100
+ /**
101
+ * Keep a step from `prev` to `next` on climbable ground: moving onto ground more than
102
+ * `maxStep` higher than where the character stands is blocked. A blocked move first
103
+ * tries to slide along the cliff (keep only the x or only the y part), so walking into
104
+ * a wall at an angle glides along it; failing both, the character stays put (a
105
+ * vehicle also loses its speed, as if it bumped the wall). The heading still turns.
53
106
  */
54
- export declare function stepCharacter(pose: CharacterPose, input: MoveInput, dt: number, scheme: ControlScheme, params: MotionParams, cameraRotation?: number): CharacterPose;
107
+ export declare function constrainToGround(prev: CharacterPose, next: CharacterPose, heightAt: HeightAt, maxStep: number): CharacterPose;
55
108
  //# sourceMappingURL=character-physics.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"character-physics.d.ts","sourceRoot":"","sources":["../src/character-physics.ts"],"names":[],"mappings":"AAKA,MAAM,MAAM,aAAa,GAAG,aAAa,GAAG,SAAS,CAAC;AAEtD,oDAAoD;AACpD,MAAM,WAAW,SAAS;IACzB,EAAE,EAAE,OAAO,CAAC;IACZ,IAAI,EAAE,OAAO,CAAC;IACd,IAAI,EAAE,OAAO,CAAC;IACd,KAAK,EAAE,OAAO,CAAC;CACf;AAED,eAAO,MAAM,QAAQ,EAAE,SAAiE,CAAC;AAEzF,MAAM,WAAW,aAAa;IAC7B,sBAAsB;IACtB,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,gDAAgD;IAChD,OAAO,EAAE,MAAM,CAAC;IAChB,8EAA8E;IAC9E,KAAK,EAAE,MAAM,CAAC;IACd,6CAA6C;IAC7C,MAAM,EAAE,OAAO,CAAC;CAChB;AAED,MAAM,WAAW,YAAY;IAC5B,kCAAkC;IAClC,SAAS,EAAE,MAAM,CAAC;IAClB,8BAA8B;IAC9B,QAAQ,EAAE,MAAM,CAAC;IACjB,wDAAwD;IACxD,YAAY,EAAE,MAAM,CAAC;IACrB,kEAAkE;IAClE,QAAQ,EAAE,MAAM,CAAC;IACjB,+DAA+D;IAC/D,YAAY,EAAE,MAAM,CAAC;CACrB;AAED,eAAO,MAAM,cAAc,EAAE,YAM5B,CAAC;AAEF,4EAA4E;AAC5E,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAAE,CAGnE;AAED,oDAAoD;AACpD,wBAAgB,aAAa,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAE1D;AAED,iFAAiF;AACjF,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAI5E;AAOD;;;;;;;;;;GAUG;AACH,wBAAgB,aAAa,CAC5B,IAAI,EAAE,aAAa,EACnB,KAAK,EAAE,SAAS,EAChB,EAAE,EAAE,MAAM,EACV,MAAM,EAAE,aAAa,EACrB,MAAM,EAAE,YAAY,EACpB,cAAc,SAAI,GAChB,aAAa,CAoDf"}
1
+ {"version":3,"file":"character-physics.d.ts","sourceRoot":"","sources":["../src/character-physics.ts"],"names":[],"mappings":"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"}