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 { useEffect } from "react";
|
||||||
import { useThree } from "@react-three/fiber";
|
import { useThree } from "@react-three/fiber";
|
||||||
import { PointerLockControls } from "@react-three/drei";
|
import { PointerLockControls } from "@react-three/drei";
|
||||||
|
import { useSettingsStore } from "@/managers/stores/useSettingsStore";
|
||||||
import { setGlobalCamera } from "@/world/GameCinematics";
|
import { setGlobalCamera } from "@/world/GameCinematics";
|
||||||
|
|
||||||
export function PlayerCamera(): React.JSX.Element {
|
export function PlayerCamera(): React.JSX.Element {
|
||||||
const camera = useThree((state) => state.camera);
|
const camera = useThree((state) => state.camera);
|
||||||
|
const isSettingsMenuOpen = useSettingsStore(
|
||||||
|
(state) => state.isSettingsMenuOpen,
|
||||||
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setGlobalCamera(camera);
|
setGlobalCamera(camera);
|
||||||
return () => {
|
return () => {
|
||||||
setGlobalCamera(null);
|
setGlobalCamera(null);
|
||||||
document.exitPointerLock();
|
if (document.pointerLockElement) {
|
||||||
|
document.exitPointerLock();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}, [camera]);
|
}, [camera]);
|
||||||
|
|
||||||
return <PointerLockControls />;
|
return (
|
||||||
|
<PointerLockControls
|
||||||
|
enabled={!isSettingsMenuOpen}
|
||||||
|
selector="#game-canvas"
|
||||||
|
/>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ import {
|
|||||||
EBIKE_CAMERA_TRANSFORM,
|
EBIKE_CAMERA_TRANSFORM,
|
||||||
EBIKE_DECELERATION_DURATION_MS,
|
EBIKE_DECELERATION_DURATION_MS,
|
||||||
} from "@/data/ebike/ebikeConfig";
|
} from "@/data/ebike/ebikeConfig";
|
||||||
|
import { useSceneMode } from "@/hooks/debug/useSceneMode";
|
||||||
|
|
||||||
/** Global window properties used for ebike communication */
|
/** Global window properties used for ebike communication */
|
||||||
interface EbikeGlobalState {
|
interface EbikeGlobalState {
|
||||||
@@ -152,6 +153,7 @@ export function PlayerController({
|
|||||||
spawnPosition,
|
spawnPosition,
|
||||||
}: PlayerControllerProps): null {
|
}: PlayerControllerProps): null {
|
||||||
const camera = useThree((state) => state.camera);
|
const camera = useThree((state) => state.camera);
|
||||||
|
const sceneMode = useSceneMode();
|
||||||
const movementLocked = useRepairMovementLocked();
|
const movementLocked = useRepairMovementLocked();
|
||||||
const terrainHeight = useTerrainHeightSampler();
|
const terrainHeight = useTerrainHeightSampler();
|
||||||
const movementLockedRef = useRef(movementLocked);
|
const movementLockedRef = useRef(movementLocked);
|
||||||
@@ -483,19 +485,21 @@ export function PlayerController({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const groundHeight = terrainHeight.getHeight(
|
if (sceneMode === "game") {
|
||||||
capsule.current.end.x,
|
const groundHeight = terrainHeight.getHeight(
|
||||||
capsule.current.end.z,
|
capsule.current.end.x,
|
||||||
);
|
capsule.current.end.z,
|
||||||
if (groundHeight !== null && velocity.current.y <= 0) {
|
);
|
||||||
const groundOffset = getCapsuleFootY(capsule.current) - groundHeight;
|
if (groundHeight !== null && velocity.current.y <= 0) {
|
||||||
|
const groundOffset = getCapsuleFootY(capsule.current) - groundHeight;
|
||||||
|
|
||||||
if (groundOffset <= PLAYER_GROUND_SNAP_DISTANCE) {
|
if (groundOffset <= PLAYER_GROUND_SNAP_DISTANCE) {
|
||||||
capsule.current.translate(
|
capsule.current.translate(
|
||||||
_collisionCorrection.set(0, -groundOffset, 0),
|
_collisionCorrection.set(0, -groundOffset, 0),
|
||||||
);
|
);
|
||||||
velocity.current.y = 0;
|
velocity.current.y = 0;
|
||||||
onFloor.current = true;
|
onFloor.current = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user