mirror of
https://github.com/storytold/spark.git
synced 2026-10-17 00:12:59 +00:00
Initial commit
This commit is contained in:
@@ -0,0 +1,152 @@
|
||||
# Controls
|
||||
|
||||
A program using `Forge` can use any camera control scheme they want that is compatible with Three.js and will typically manipulate a `THREE.Camera` object's transform. `Forge` ships with simple, intuitive controls for navigating 3D space that use the keyboard + mouse, game pad, or mobile multi-touch. To add these controls, you can add:
|
||||
|
||||
```typescript
|
||||
const controls = new ForgeControls({
|
||||
canvas: HTMLCanvasElement;
|
||||
});
|
||||
|
||||
renderer.setAnimationLoop((time) => {
|
||||
renderer.render(scene, camera);)
|
||||
controls.update(camera);
|
||||
});
|
||||
```
|
||||
|
||||
`ForgeControls` instantiates two classes `FpsMovement` and `PointerControls` that it updates internally. You can also instantiate and use these two classes separately:
|
||||
|
||||
## `class FpsMovement`
|
||||
|
||||
`FpsMovement` implements controls that will be familiar to anyone who plays First Person Shooters using keyboard + mouse or a gamepad. Creating a `FpsMovement` instance provides many parameters:
|
||||
|
||||
```typescript
|
||||
const fpsMovement = new FpsMovement({
|
||||
moveSpeed?: number;
|
||||
rollSpeed?: number;
|
||||
stickThreshold?: number;
|
||||
rotateSpeed?: number;
|
||||
keycodeMoveMapping?: { [key: string]: THREE.Vector3 };
|
||||
keycodeRotateMapping?: { [key: string]: THREE.Vector3 };
|
||||
gamepadMapping?: {
|
||||
[button: number]: "shift" | "ctrl" | "rollLeft" | "rollRight";
|
||||
};
|
||||
capsMultiplier?: number;
|
||||
shiftMultiplier?: number;
|
||||
ctrlMultiplier?: number;
|
||||
xr?: THREE.WebXRManager;
|
||||
});
|
||||
```
|
||||
When gamepads are connected, `FpsMovement` will always use gamepad index 0 for twin-stick movement and rotation.
|
||||
|
||||
If `xr` is passed in, the WebXR controllers can be used as a split gamepad to control movement and rotation. (tested on Quest 3)
|
||||
|
||||
### Optional parameters
|
||||
|
||||
| Parameter | Default | Description |
|
||||
|-----------|---------|-------------|
|
||||
| `moveSpeed` | `1.0` | Base movement speed |
|
||||
| `rollSpeed` | `2.0` | Speed of roll rotation |
|
||||
| `stickThreshold` | `0.1` | Deadzone for gamepad analog sticks |
|
||||
| `rotateSpeed` | `2.0` | Speed of rotation when using gamepad or keys |
|
||||
| `keycodeMoveMapping` | `{...WASD_KEYCODE_MOVE, ...ARROW_KEYCODE_MOVE}` | Maps keyboard keys to movement directions |
|
||||
| `keycodeRotateMapping` | `{...QE_KEYCODE_ROTATE, ...ARROW_KEYCODE_ROTATE}` | Maps keyboard keys to rotation directions |
|
||||
| `gamepadMapping` | `{4: "rollLeft", 5: "rollRight", 6: "ctrl", 7: "shift"}` | Maps gamepad buttons to actions |
|
||||
| `capsMultiplier` | `10.0` | Speed multiplier when Caps Lock is active |
|
||||
| `shiftMultiplier` | `5.0` | Speed multiplier when Shift is held |
|
||||
| `ctrlMultiplier` | `0.2` | Speed multiplier when Ctrl is held |
|
||||
| `xr` | `undefined` | Optional WebXR manager for XR controller stick support
|
||||
|
||||
### `update(deltaTime, control)`
|
||||
|
||||
Call this method in your render loop with `control` set to the object to control (`THREE.Camera` or a `THREE.Object3D` that contains it), with `deltaTime` in seconds since the last update.
|
||||
The update method handles:
|
||||
|
||||
- Processing keyboard input for movement and rotation
|
||||
- Processing gamepad input for movement and rotation
|
||||
- Applying speed multipliers based on modifier keys and gamepad buttons
|
||||
- Applying movement and rotation to the controlled object
|
||||
|
||||
|
||||
## `class PointerControls`
|
||||
|
||||
`PointerControls` implements pointer/mouse/touch controls on the canvas, for both desktop and mobile web applications. Creating a new control:
|
||||
```typescript
|
||||
const pointerControls = new PointerControls({
|
||||
canvas: HTMLCanvasElement;
|
||||
rotateSpeed?: number;
|
||||
slideSpeed?: number;
|
||||
scrollSpeed?: number;
|
||||
reverseRotate?: boolean;
|
||||
reverseSlide?: boolean;
|
||||
reverseSwipe?: boolean;
|
||||
reverseScroll?: boolean;
|
||||
moveInertia?: number;
|
||||
rotateInertia?: number;
|
||||
doublePress?: ({
|
||||
position,
|
||||
intervalMs,
|
||||
}: { position: THREE.Vector2; intervalMs: number }) => void;
|
||||
})
|
||||
```
|
||||
|
||||
### Require parameters
|
||||
|
||||
| Parameter | Description |
|
||||
|-----------|-------------|
|
||||
| `canvas` | The HTML canvas element to attach pointer events to |
|
||||
|
||||
### Optional parameters
|
||||
|
||||
| Parameter | Default | Description |
|
||||
|-----------|---------|-------------|
|
||||
| `rotateSpeed` | `0.002` | Speed of rotation when dragging |
|
||||
| `slideSpeed` | `0.006` | Speed of sliding when dragging with right button or two fingers |
|
||||
| `scrollSpeed` | `0.0015` | Speed of movement when using mouse wheel |
|
||||
| `reverseRotate` | `false` | Reverse the direction of rotation |
|
||||
| `reverseSlide` | `false` | Reverse the direction of sliding |
|
||||
| `reverseSwipe` | `false` | Reverse the direction of swipe gestures |
|
||||
| `reverseScroll` | `false` | Reverse the direction of scroll wheel movement |
|
||||
| `moveInertia` | `0.15` | Inertia factor for movement |
|
||||
| `rotateInertia` | `0.15` | Inertia factor for rotation |
|
||||
| `doublePress` | `undefined` | Callback function for double-press/double-tap events |
|
||||
|
||||
### `update(deltaTime, control)`
|
||||
|
||||
Call this method in your render loop with `control` set to the object to control (`THREE.Camera` or a `THREE.Object3D` that contains it), with `deltaTime` in seconds since the last update.
|
||||
|
||||
The update method handles:
|
||||
|
||||
- Processing pointer/mouse/touch movements for rotation
|
||||
- Handling dual-press touch gestures for camera movement
|
||||
- Applying scroll wheel input
|
||||
- Calculating and applying inertia for smooth motion
|
||||
- Updating the camera position and orientation
|
||||
|
||||
|
||||
## Adding a simple GUI to configure controls
|
||||
|
||||
Add `lil-gui` to your package (`npm add lil-gui`) to provide a simple configurable GUI.
|
||||
|
||||
```typescript
|
||||
import GUI from "lil-gui";
|
||||
|
||||
const gui = new GUI({ title: "Settings + Controls" }).close();
|
||||
const controlOptions = {
|
||||
reversePointerFps: false,
|
||||
reversePointerPan: false,
|
||||
};
|
||||
gui
|
||||
.add(controlOptions, "reversePointerFps")
|
||||
.name("Reverse Pointer FPS")
|
||||
.onChange((value: boolean) => {
|
||||
pointerControls.reverseRotate = value;
|
||||
pointerControls.reverseScroll = value;
|
||||
});
|
||||
gui
|
||||
.add(controlOptions, "reversePointerPan")
|
||||
.name("Reverse Pointer Pan")
|
||||
.onChange((value: boolean) => {
|
||||
pointerControls.reverseSlide = value;
|
||||
pointerControls.reverseSwipe = value;
|
||||
});
|
||||
```
|
||||
Reference in New Issue
Block a user