diff --git a/.claude/docs/overworld.md b/.claude/docs/overworld.md index 106dec7..ae28f88 100644 --- a/.claude/docs/overworld.md +++ b/.claude/docs/overworld.md @@ -73,20 +73,24 @@ Camera-relative direction is derived from the active `Camera3D`'s basis — the ## Camera -`OverworldCamera` orbits around `targetNode` using yaw/pitch angles. It operates in two modes: `CameraMode.FREE` (stays where placed) and `CameraMode.CENTERED` (lerps to orbit directly behind the player). +`OverworldCamera` orbits around `targetNode` using yaw/pitch angles. It operates in two modes: `CameraMode.FREE` (stays where placed) and `CameraMode.CENTERED` (eases to orbit behind the player using a velocity-based approach). | Export | Default | Purpose | |---|---|---| | `targetNode:Node3D` | — | Node to orbit (assign Player in scene) | | `pivotOffset:Vector3` | `(0, 1.2, 0)` | Orbit point above entity origin | | `distance:float` | `7.0` | Orbit radius | -| `minDistance:float` | `2.0` | Minimum camera distance (collision won't push closer) | +| `minDistance:float` | `2.5` | Minimum camera distance (collision won't push closer) | | `pitchMin/Max:float` | `-80° / 70°` | Vertical clamp | | `orbitSensitivity:float` | `144.0` | Degrees/sec at full controller input | | `orbitAcceleration:float` | `600.0` | Controller ramp speed (deg/s²) | +| `orbitFriction:float` | `10.0` | Controller/centering velocity decay rate | | `mouseSensitivity:float` | `0.3` | Right-click drag sensitivity | -| `centeredDelay:float` | `2.0` | Seconds of walking + no camera input before switching to CENTERED | -| `centeredFollowRate:float` | `3.0` | Lerp rate in CENTERED mode (higher = faster; 3 ≈ 1s to fully center) | +| `centeredDelay:float` | `1.0` | Seconds of walking + no camera input before switching to CENTERED | +| `centeredFollowRate:float` | `0.75` | Base centering rate; scales up with angular distance from target | +| `centeredMaxFollowRate:float` | `3.0` | Cap on the dynamic follow rate | +| `centeredAcceleration:float` | `180.0` | How fast `_centerVelocity` ramps up toward target (deg/s²) | +| `centeredMaxYawDiff:float` | `120.0` | If yaw offset exceeds this, centering is suppressed (e.g. player walking toward camera) | | `centeredPitch:float` | `30.0` | Target pitch in CENTERED mode | | `collisionMask:int` | `1` | Physics layers the camera avoids; entities are on layer 2 and excluded by default | @@ -94,7 +98,13 @@ Camera-relative direction is derived from the active `Camera3D`'s basis — the - FREE → CENTERED: after `centeredDelay` seconds of player movement with no camera input, or immediately via `center_camera` (G / LB) - CENTERED → FREE: any manual camera input (controller stick or right-click drag) -Collision resolution uses a sphere-plane circle intersection so the camera satisfies both `minDistance` and terrain clearance simultaneously (`COLLISION_MARGIN = 0.3`). +**CENTERED mode behaviour:** +- "Behind" direction is derived from the player's velocity vector (not facing direction), so centering tracks actual movement and eases out naturally as the player decelerates +- Yaw uses a velocity model: `_centerVelocity` (deg/s) accelerates toward the target rate via `centeredAcceleration` and friction-decays via `orbitFriction` when the player stops — no sudden snap +- Pitch recenters at 3× the yaw rate via direct lerp +- If `abs(yawDiff) > centeredMaxYawDiff`, centering is suppressed and `_centerVelocity` decays instead + +Collision resolution uses a sphere-plane circle intersection so the camera satisfies both `minDistance` and terrain clearance simultaneously. ## Adding a new map