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:
@@ -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);
|
||||
document.exitPointerLock();
|
||||
if (document.pointerLockElement) {
|
||||
document.exitPointerLock();
|
||||
}
|
||||
};
|
||||
}, [camera]);
|
||||
|
||||
return <PointerLockControls />;
|
||||
return (
|
||||
<PointerLockControls
|
||||
enabled={!isSettingsMenuOpen}
|
||||
selector="#game-canvas"
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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,19 +485,21 @@ export function PlayerController({
|
||||
}
|
||||
}
|
||||
|
||||
const groundHeight = terrainHeight.getHeight(
|
||||
capsule.current.end.x,
|
||||
capsule.current.end.z,
|
||||
);
|
||||
if (groundHeight !== null && velocity.current.y <= 0) {
|
||||
const groundOffset = getCapsuleFootY(capsule.current) - groundHeight;
|
||||
if (sceneMode === "game") {
|
||||
const groundHeight = terrainHeight.getHeight(
|
||||
capsule.current.end.x,
|
||||
capsule.current.end.z,
|
||||
);
|
||||
if (groundHeight !== null && velocity.current.y <= 0) {
|
||||
const groundOffset = getCapsuleFootY(capsule.current) - groundHeight;
|
||||
|
||||
if (groundOffset <= PLAYER_GROUND_SNAP_DISTANCE) {
|
||||
capsule.current.translate(
|
||||
_collisionCorrection.set(0, -groundOffset, 0),
|
||||
);
|
||||
velocity.current.y = 0;
|
||||
onFloor.current = true;
|
||||
if (groundOffset <= PLAYER_GROUND_SNAP_DISTANCE) {
|
||||
capsule.current.translate(
|
||||
_collisionCorrection.set(0, -groundOffset, 0),
|
||||
);
|
||||
velocity.current.y = 0;
|
||||
onFloor.current = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user