update step
This commit is contained in:
@@ -0,0 +1,151 @@
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
import { useFrame, useThree } from "@react-three/fiber";
|
||||
import * as THREE from "three";
|
||||
import { ZONES } from "@/data/zones";
|
||||
import { GameStepManager } from "@/stateManager/GameStepManager";
|
||||
import { Debug } from "@/utils/debug/Debug";
|
||||
|
||||
const _playerPos = new THREE.Vector3();
|
||||
const _zonePos = new THREE.Vector3();
|
||||
|
||||
export function ZoneDetection(): null {
|
||||
const camera = useThree((state) => state.camera);
|
||||
const manager = GameStepManager.getInstance();
|
||||
const triggeredZones = useRef<Set<string>>(new Set());
|
||||
const debug = Debug.getInstance();
|
||||
|
||||
useEffect(() => {
|
||||
if (!debug.active) return;
|
||||
|
||||
const folder = debug.createFolder("Game");
|
||||
if (!folder) return;
|
||||
|
||||
const gameState = { step: manager.getStep() };
|
||||
const playerPos = { x: 0, y: 0, z: 0 };
|
||||
|
||||
folder
|
||||
.add(gameState, "step", ["intro", "outOfFabrik"])
|
||||
.name("Game Step")
|
||||
.disable();
|
||||
|
||||
folder.add(playerPos, "x").name("Player X").listen().disable();
|
||||
folder.add(playerPos, "y").name("Player Y").listen().disable();
|
||||
folder.add(playerPos, "z").name("Player Z").listen().disable();
|
||||
|
||||
const unsubManager = manager.subscribe(() => {
|
||||
gameState.step = manager.getStep();
|
||||
folder.controllersRecursive().forEach((c) => c.updateDisplay());
|
||||
});
|
||||
|
||||
let frameId: number;
|
||||
const updatePlayerPos = (): void => {
|
||||
camera.getWorldPosition(_playerPos);
|
||||
playerPos.x = Math.round(_playerPos.x * 100) / 100;
|
||||
playerPos.y = Math.round(_playerPos.y * 100) / 100;
|
||||
playerPos.z = Math.round(_playerPos.z * 100) / 100;
|
||||
folder.controllersRecursive().forEach((c) => c.updateDisplay());
|
||||
frameId = requestAnimationFrame(updatePlayerPos);
|
||||
};
|
||||
updatePlayerPos();
|
||||
|
||||
return () => {
|
||||
cancelAnimationFrame(frameId);
|
||||
debug.destroyFolder("Game");
|
||||
unsubManager();
|
||||
};
|
||||
}, [debug, manager, camera]);
|
||||
|
||||
useFrame(() => {
|
||||
camera.getWorldPosition(_playerPos);
|
||||
|
||||
for (const zone of ZONES) {
|
||||
if (triggeredZones.current.has(zone.id)) continue;
|
||||
|
||||
_zonePos.set(...zone.position);
|
||||
|
||||
const distanceSq = _playerPos.distanceToSquared(_zonePos);
|
||||
|
||||
if (distanceSq <= zone.radius * zone.radius) {
|
||||
manager.transitionTo(zone.targetStep);
|
||||
triggeredZones.current.add(zone.id);
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
interface ZoneVisualProps {
|
||||
position: [number, number, number];
|
||||
radius: number;
|
||||
height: number;
|
||||
triggered: boolean;
|
||||
}
|
||||
|
||||
function ZoneVisual({
|
||||
position,
|
||||
radius,
|
||||
height,
|
||||
triggered,
|
||||
}: ZoneVisualProps): React.JSX.Element {
|
||||
const color = triggered ? "#00ff00" : "#ff0000";
|
||||
|
||||
return (
|
||||
<group position={position}>
|
||||
<mesh rotation={[-Math.PI / 2, 0, 0]}>
|
||||
<ringGeometry args={[radius - 0.3, radius, 32]} />
|
||||
<meshBasicMaterial color={color} side={THREE.DoubleSide} />
|
||||
</mesh>
|
||||
<mesh position={[0, height / 2, 0]}>
|
||||
<cylinderGeometry args={[radius, radius, height, 32, 1, true]} />
|
||||
<meshBasicMaterial
|
||||
color={color}
|
||||
transparent
|
||||
opacity={0.15}
|
||||
side={THREE.DoubleSide}
|
||||
depthWrite={false}
|
||||
/>
|
||||
</mesh>
|
||||
</group>
|
||||
);
|
||||
}
|
||||
|
||||
export function ZoneDebugVisuals(): React.JSX.Element | null {
|
||||
const debug = Debug.getInstance();
|
||||
const camera = useThree((state) => state.camera);
|
||||
const [triggeredZones, setTriggeredZones] = useState<Set<string>>(new Set());
|
||||
|
||||
useFrame(() => {
|
||||
camera.getWorldPosition(_playerPos);
|
||||
|
||||
for (const zone of ZONES) {
|
||||
if (triggeredZones.has(zone.id)) continue;
|
||||
|
||||
_zonePos.set(...zone.position);
|
||||
|
||||
const distanceSq = _playerPos.distanceToSquared(_zonePos);
|
||||
|
||||
if (distanceSq <= zone.radius * zone.radius) {
|
||||
setTriggeredZones((prev) => new Set(prev).add(zone.id));
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (!debug.active) return null;
|
||||
|
||||
return (
|
||||
<>
|
||||
{ZONES.map((zone) => (
|
||||
<ZoneVisual
|
||||
key={zone.id}
|
||||
position={[zone.position[0], 0.1, zone.position[2]]}
|
||||
radius={zone.radius}
|
||||
height={zone.height}
|
||||
triggered={triggeredZones.has(zone.id)}
|
||||
/>
|
||||
))}
|
||||
</>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user