diff --git a/public/fear/snd/glitch.mp3 b/public/fear/snd/glitch.mp3 new file mode 100644 index 0000000..6cfcc18 Binary files /dev/null and b/public/fear/snd/glitch.mp3 differ diff --git a/public/fear/snd/riser.mp3 b/public/fear/snd/riser.mp3 new file mode 100644 index 0000000..8a23f03 Binary files /dev/null and b/public/fear/snd/riser.mp3 differ diff --git a/src/app/fear/page.tsx b/src/app/fear/page.tsx index a633de2..ca670a3 100644 --- a/src/app/fear/page.tsx +++ b/src/app/fear/page.tsx @@ -2,7 +2,7 @@ import './page.css'; -import { Canvas } from "@react-three/fiber"; +import { Canvas, useThree } from "@react-three/fiber"; import { BrightnessContrast, EffectComposer, HueSaturation, Noise, Pixelation, Vignette } from "@react-three/postprocessing"; import { Suspense, useEffect, useState } from "react"; @@ -14,34 +14,53 @@ import TheCreature from './scene-components/creature'; import Player from './scene-components/player'; import Hallway from './scene-components/hallway'; +import { AudioListener } from 'three'; + function PostProcessing() { - const [getCaught, setCaught] = useState(fearState.wasCaught); + const [wasCaught, setWasCaught] = useState(fearState.wasCaught); useEffect(() => { const unsubscribe = fearState.subscribe(() => { - setCaught(fearState.wasCaught); + setWasCaught(fearState.wasCaught); }); return () => unsubscribe(); }, []); return ( - + - + - + ) } +function ListenerCreator() { + const { camera } = useThree(); + + useEffect(() => { + const listener = new AudioListener(); + camera.add(listener); + + return () => { + camera.remove(listener); + }; + }, [camera]); + + return null; +} + export default function Fear() { const [isRustActive, setIsRustActive] = useState(fearState.isRustActive); + const [wasCaught, setWasCaught] = useState(fearState.isRustActive); useEffect(() => { const unsubscribe = fearState.subscribe(() => { setIsRustActive(fearState.isRustActive); + setWasCaught(fearState.wasCaught) }); return () => unsubscribe(); }, []); @@ -53,6 +72,8 @@ export default function Fear() { className='canvas' camera={{ position: [0, 3, -5], fov: 65, far: 100 }} > + + @@ -67,6 +88,11 @@ export default function Fear() { url='fear/snd/ambience.mp3' volume={isRustActive ? 0 : 1} /> + + {wasCaught ? : null} ) diff --git a/src/app/fear/scene-components/creature.tsx b/src/app/fear/scene-components/creature.tsx index 5700452..0559c59 100644 --- a/src/app/fear/scene-components/creature.tsx +++ b/src/app/fear/scene-components/creature.tsx @@ -1,4 +1,4 @@ -import { useTexture } from "@react-three/drei"; +import { useTexture, PositionalAudio } from "@react-three/drei"; import { useFrame, useThree } from "@react-three/fiber"; import { useEffect, useRef, useState } from "react"; @@ -8,6 +8,7 @@ import { fearState } from "../state"; export default function TheCreature() { const texture = useTexture('fear/img/creature.png'); const meshRef = useRef(null); + const audioRef = useRef(null); const { camera } = useThree(); const [hasTriggered, setHasTriggered] = useState(false); @@ -17,6 +18,8 @@ export default function TheCreature() { const globalDistance = useRef(32); const [currentLoop, setCurrentLoop] = useState(fearState.loopCount); + const audioPlaying = useRef(false); + useEffect(() => { const unsubscribe = fearState.subscribe(() => { setCurrentLoop(fearState.loopCount); @@ -25,6 +28,11 @@ export default function TheCreature() { setIsSpawned(false); setHasTriggered(false); globalDistance.current = 32; + audioPlaying.current = false; + + if (audioRef.current && audioRef.current.isPlaying) { + audioRef.current.stop(); + } } }); return () => unsubscribe(); @@ -41,12 +49,22 @@ export default function TheCreature() { globalDistance.current = 32; } - if (!hasTriggered) - if (globalDistance.current < 40) setHasTriggered(true); + if (!hasTriggered) { + if (globalDistance.current < 40) { + setHasTriggered(true); + } + } if (hasTriggered) { globalDistance.current -= speed * delta; + if (audioRef.current && !audioPlaying.current) { + audioPlaying.current = true; + if (audioRef.current.context.state === 'suspended') + audioRef.current.context.resume(); + audioRef.current.play(); + } + const shakeIntensity = Math.max(0, 1 - (globalDistance.current / 32)) * 0.22; camera.position.x += (Math.random() - 0.5) * shakeIntensity; camera.position.y += (Math.random() - 0.5) * shakeIntensity; @@ -80,6 +98,16 @@ export default function TheCreature() { depthWrite={false} side={THREE.DoubleSide} /> + + {currentLoop >= 4 && ( + + )} ); -} +} \ No newline at end of file diff --git a/src/app/fear/scene-components/player.tsx b/src/app/fear/scene-components/player.tsx index 0bc3248..ebd6ab6 100644 --- a/src/app/fear/scene-components/player.tsx +++ b/src/app/fear/scene-components/player.tsx @@ -1,9 +1,10 @@ import { useFrame, useThree } from "@react-three/fiber"; import { useEffect, useRef } from "react"; -import * as THREE from "three"; import { FEAR_SETTINGS, fearState } from "../state"; import { PointerLockControls } from "@react-three/drei"; +import * as THREE from "three"; + const forward = new THREE.Vector3(); const side = new THREE.Vector3(); const direction = new THREE.Vector3(); diff --git a/src/app/fear/state.ts b/src/app/fear/state.ts index 3d2fb42..18065d9 100644 --- a/src/app/fear/state.ts +++ b/src/app/fear/state.ts @@ -5,7 +5,7 @@ export const FEAR_SETTINGS = { HALLWAY_WIDTH: 6, HALLWAY_HEIGHT: 5, PLAYER_HEIGHT: 3, - PLAYER_SPEED: 6, + PLAYER_SPEED: 4, WALL_BUFFER: 0.6, };