three-gamepad-controls 0.25.0 → 0.25.2

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.
@@ -10,6 +10,7 @@ import { FirstPersonControls } from "three/addons/controls/FirstPersonControls.j
10
10
  export type GamepadFirstPersonControlsOptions = GamepadControlsOptions & {
11
11
  /**
12
12
  * Multiplier on `FirstPersonControls.movementSpeed` for translation.
13
+ * Applied after normalizing combined stick and trigger movement.
13
14
  * @default 1.0
14
15
  */
15
16
  moveSpeed: number;
@@ -19,7 +20,7 @@ export type GamepadFirstPersonControlsOptions = GamepadControlsOptions & {
19
20
  */
20
21
  lookSpeed: number;
21
22
  /**
22
- * Movement stick axes and processing pipeline.
23
+ * Axes and processing pipeline for yaw-based movement in the XZ plane.
23
24
  */
24
25
  moveStick: GamepadStickBindingOptions;
25
26
  /**
@@ -32,12 +33,12 @@ export type GamepadFirstPersonControlsOptions = GamepadControlsOptions & {
32
33
  */
33
34
  buttonDeadzone: number;
34
35
  /**
35
- * Button index for **moving up** (analog trigger value used for proportional speed).
36
+ * Button index for **moving up** along Y (analog value used for proportional speed).
36
37
  * @default 6 - Left trigger
37
38
  */
38
39
  buttonMoveUp: number;
39
40
  /**
40
- * Button index for **moving down** (analog trigger value used for proportional speed).
41
+ * Button index for **moving down** along Y (analog value used for proportional speed).
41
42
  * @default 7 - Right trigger
42
43
  */
43
44
  buttonMoveDown: number;
@@ -47,6 +48,10 @@ export type GamepadFirstPersonControlsOptions = GamepadControlsOptions & {
47
48
  *
48
49
  * Gamepad input is additive with keyboard/mouse input - call
49
50
  * `gamepadControls.update(delta)` before `controls.update(delta)` each frame.
51
+ * Movement follows the native keyboard frame: yaw-based translation in XZ
52
+ * and climbing along Y, independent of camera pitch and roll.
53
+ * Combined gamepad movement is limited to unit magnitude before speed and
54
+ * forward height gains, preserving smaller analog intentions unchanged.
50
55
  * Bindings and speeds are configurable via {@link GamepadFirstPersonControlsOptions}.
51
56
  */
52
57
  export declare class GamepadFirstPersonControls extends GamepadControls {
@@ -26,6 +26,10 @@ const LOOK_SPEED_SCALE = 36e3;
26
26
  *
27
27
  * Gamepad input is additive with keyboard/mouse input - call
28
28
  * `gamepadControls.update(delta)` before `controls.update(delta)` each frame.
29
+ * Movement follows the native keyboard frame: yaw-based translation in XZ
30
+ * and climbing along Y, independent of camera pitch and roll.
31
+ * Combined gamepad movement is limited to unit magnitude before speed and
32
+ * forward height gains, preserving smaller analog intentions unchanged.
29
33
  * Bindings and speeds are configurable via {@link GamepadFirstPersonControlsOptions}.
30
34
  */
31
35
  var GamepadFirstPersonControls = class extends GamepadControls {
@@ -64,7 +68,10 @@ var GamepadFirstPersonControls = class extends GamepadControls {
64
68
  this.#applyLook(deltaTime, lookSpeed, lookStick);
65
69
  }
66
70
  /**
67
- * Applies local translation input to FirstPersonControls' object.
71
+ * Applies translation in the native keyboard frame, using yaw before look.
72
+ * Triggers are filtered independently before the combined movement intent
73
+ * is limited to unit magnitude. Speed and forward height gains follow this
74
+ * normalization; height gain uses the initial Y position before climbing.
68
75
  *
69
76
  * @param deltaTime - Seconds since the last frame.
70
77
  * @param moveSpeed - User-configured movement speed multiplier.
@@ -76,23 +83,33 @@ var GamepadFirstPersonControls = class extends GamepadControls {
76
83
  #applyMovement(deltaTime, moveSpeed, moveStick, buttonDeadzone, buttonMoveUp, buttonMoveDown) {
77
84
  const controls = this.#controls;
78
85
  const input = this.gamepadInput;
79
- const moveMult = deltaTime * controls.movementSpeed * moveSpeed;
80
86
  const move = input.stick(moveStick.xAxis, moveStick.yAxis, moveStick.pipeline);
81
- const forward = move.y;
82
- if (forward !== 0) {
83
- let distance = forward * moveMult;
84
- if (forward < 0 && controls.heightSpeed) {
87
+ const up = input.buttonValue(buttonMoveUp);
88
+ const down = input.buttonValue(buttonMoveDown);
89
+ let strafe = move.x;
90
+ let forward = -move.y;
91
+ let climb = (up > buttonDeadzone ? up : 0) - (down > buttonDeadzone ? down : 0);
92
+ const magnitude = Math.hypot(strafe, forward, climb);
93
+ if (magnitude > 1) {
94
+ strafe /= magnitude;
95
+ forward /= magnitude;
96
+ climb /= magnitude;
97
+ }
98
+ const moveMult = deltaTime * controls.movementSpeed * moveSpeed;
99
+ if (strafe !== 0 || forward !== 0) {
100
+ const yaw = MathUtils.degToRad(this.#getOrientation().lon);
101
+ const sinYaw = Math.sin(yaw);
102
+ const cosYaw = Math.cos(yaw);
103
+ let forwardDistance = forward * moveMult;
104
+ if (forward > 0 && controls.heightSpeed) {
85
105
  const heightDelta = MathUtils.clamp(controls.object.position.y, controls.heightMin, controls.heightMax) - controls.heightMin;
86
- distance -= -forward * deltaTime * heightDelta * controls.heightCoef * moveSpeed;
106
+ forwardDistance += forward * deltaTime * heightDelta * controls.heightCoef * moveSpeed;
87
107
  }
88
- controls.object.translateZ(distance);
108
+ const strafeDistance = strafe * moveMult;
109
+ controls.object.position.x += sinYaw * forwardDistance - cosYaw * strafeDistance;
110
+ controls.object.position.z += cosYaw * forwardDistance + sinYaw * strafeDistance;
89
111
  }
90
- const strafe = move.x;
91
- if (strafe !== 0) controls.object.translateX(strafe * moveMult);
92
- const up = input.buttonValue(buttonMoveUp);
93
- const down = input.buttonValue(buttonMoveDown);
94
- if (up > buttonDeadzone) controls.object.translateY(up * moveMult);
95
- if (down > buttonDeadzone) controls.object.translateY(-down * moveMult);
112
+ if (climb !== 0) controls.object.position.y += climb * moveMult;
96
113
  }
97
114
  /**
98
115
  * Applies camera look input while keeping FirstPersonControls state in sync.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "three-gamepad-controls",
3
3
  "description": "Gamepad support for Three.js controls.",
4
- "version": "0.25.0",
4
+ "version": "0.25.2",
5
5
  "license": "MIT",
6
6
  "homepage": "https://github.com/luckasnix/three-gamepad-controls#readme",
7
7
  "author": {