fix(player): scope pointer lock and ground snap to game scene

PointerLockControls now targets #game-canvas and respects the
settings menu, and document.exitPointerLock() only runs when a
pointer lock is actually active. The terrain ground snap in
PlayerController is gated on sceneMode === "game" so it doesn't
fight the physics test scene's flat floor.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Tom Boullay
2026-06-02 16:33:54 +02:00
parent 72cb9f5be6
commit 3fe5b32de2
2 changed files with 29 additions and 14 deletions
+12 -1
View File
@@ -1,18 +1,29 @@
import { useEffect } from "react";
import { useThree } from "@react-three/fiber";
import { PointerLockControls } from "@react-three/drei";
import { useSettingsStore } from "@/managers/stores/useSettingsStore";
import { setGlobalCamera } from "@/world/GameCinematics";
export function PlayerCamera(): React.JSX.Element {
const camera = useThree((state) => state.camera);
const isSettingsMenuOpen = useSettingsStore(
(state) => state.isSettingsMenuOpen,
);
useEffect(() => {
setGlobalCamera(camera);
return () => {
setGlobalCamera(null);
if (document.pointerLockElement) {
document.exitPointerLock();
}
};
}, [camera]);
return <PointerLockControls />;
return (
<PointerLockControls
enabled={!isSettingsMenuOpen}
selector="#game-canvas"
/>
);
}
+4
View File
@@ -34,6 +34,7 @@ import {
EBIKE_CAMERA_TRANSFORM,
EBIKE_DECELERATION_DURATION_MS,
} from "@/data/ebike/ebikeConfig";
import { useSceneMode } from "@/hooks/debug/useSceneMode";
/** Global window properties used for ebike communication */
interface EbikeGlobalState {
@@ -152,6 +153,7 @@ export function PlayerController({
spawnPosition,
}: PlayerControllerProps): null {
const camera = useThree((state) => state.camera);
const sceneMode = useSceneMode();
const movementLocked = useRepairMovementLocked();
const terrainHeight = useTerrainHeightSampler();
const movementLockedRef = useRef(movementLocked);
@@ -483,6 +485,7 @@ export function PlayerController({
}
}
if (sceneMode === "game") {
const groundHeight = terrainHeight.getHeight(
capsule.current.end.x,
capsule.current.end.z,
@@ -498,6 +501,7 @@ export function PlayerController({
onFloor.current = true;
}
}
}
if (movementModeRef.current === "ebike") {
let targetSteer = 0;