diff --git a/src/components/MainScene/MiddleRing/MiddleRing.tsx b/src/components/MainScene/MiddleRing/MiddleRing.tsx index e65d1ab..25bcadb 100644 --- a/src/components/MainScene/MiddleRing/MiddleRing.tsx +++ b/src/components/MainScene/MiddleRing/MiddleRing.tsx @@ -12,10 +12,6 @@ import sleep from "../../../utils/sleep"; const MiddleRing = () => { const middleRingTex = useLoader(THREE.TextureLoader, middleRingTexture); - const middleRingMaterialRef = useRef(); - const middleRingRef = useRef(); - const middleRingPartRef = useRef(); - const vertexShader = ` varying vec2 vUv; uniform float uTime; @@ -168,6 +164,9 @@ const MiddleRing = () => { const noiseAmpRef = useRef(0.03); const wobbleAmpRef = useRef(0); + const middleRingMaterialRef = useRef(); + const middleRingRef = useRef(); + const middleRingPartRef = useRef(); useFrame(() => { if (middleRingMaterialRef.current) { @@ -227,7 +226,7 @@ const MiddleRing = () => { setRot({ rotZ: rotValues[1] }); isAnimatingRef.current = false; - + await sleep(1000); setRot({ rotZ: 0 }); }; diff --git a/src/components/MainScene/Site/Node.tsx b/src/components/MainScene/Site/Node.tsx index fa96c7a..fa2f586 100644 --- a/src/components/MainScene/Site/Node.tsx +++ b/src/components/MainScene/Site/Node.tsx @@ -132,32 +132,34 @@ const Node = memo((props: NodeContructorProps) => { config: { duration: 800 }, })); - useEffect(() => { - useStore.subscribe(set, (state) => ({ - activeNodePosX: state.activeNodeAttributes.interactedWith - ? state.activeNodePos[0] - : props.position[0], - activeNodePosY: state.activeNodeAttributes.interactedWith - ? state.activeNodePos[1] - : props.position[1], - activeNodePosZ: state.activeNodeAttributes.interactedWith - ? state.activeNodePos[2] - : props.position[2], - activeNodeRotZ: state.activeNodeAttributes.interactedWith - ? state.activeNodeRot[2] - : 0, - activeNodeScale: state.activeNodeAttributes.shrinking ? 0 : 1, - activeNodeVisible: state.activeNodeAttributes.visible, - })); - }, [ - props.level, - activeNodePosX, - activeNodePosZ, - activeNodeRotZ, - props.position, - set, - props.rotation, - ]); + useEffect( + () => + useStore.subscribe(set, (state) => ({ + activeNodePosX: state.activeNodeAttributes.interactedWith + ? state.activeNodePos[0] + : props.position[0], + activeNodePosY: state.activeNodeAttributes.interactedWith + ? state.activeNodePos[1] + : props.position[1], + activeNodePosZ: state.activeNodeAttributes.interactedWith + ? state.activeNodePos[2] + : props.position[2], + activeNodeRotZ: state.activeNodeAttributes.interactedWith + ? state.activeNodeRot[2] + : 0, + activeNodeScale: state.activeNodeAttributes.shrinking ? 0 : 1, + activeNodeVisible: state.activeNodeAttributes.visible, + })), + [ + props.level, + activeNodePosX, + activeNodePosZ, + activeNodeRotZ, + props.position, + set, + props.rotation, + ] + ); useFrame(() => { if (materialRef.current) { diff --git a/src/components/MainScene/Site/PurpleRing.tsx b/src/components/MainScene/Site/PurpleRing.tsx index 924ab68..9086ffc 100644 --- a/src/components/MainScene/Site/PurpleRing.tsx +++ b/src/components/MainScene/Site/PurpleRing.tsx @@ -18,8 +18,10 @@ const PurpleRing = memo((props: PurpleRingProps) => { const purpleRingRef = useRef(); - const dispatchSiteLevelTextureOffset = (level: string) => { - const siteTextures = { + const levelTextureOffsets = useMemo(() => { + const formattedLevel = props.level.padStart(2, "0"); + + const offsets: { [key: string]: number } = { "9": 0.035, "8": 0.039, "7": 0.001, @@ -31,25 +33,27 @@ const PurpleRing = memo((props: PurpleRingProps) => { "1": 0.026, "0": 0.031, }; - return siteTextures[level as keyof typeof siteTextures]; - }; + + return [ + offsets[formattedLevel.charAt(0)], + offsets[formattedLevel.charAt(1)], + ]; + }, [props.level]); const uniforms = useMemo(() => { const uniform = THREE.UniformsUtils.merge([THREE.UniformsLib["lights"]]); - const formattedLevel = props.level.padStart(2, "0"); - uniform.tex = { type: "t", value: null }; uniform.siteLevels = { type: "t", value: siteLevels }; uniform.siteLevelFirstCharacterOffset = { - value: dispatchSiteLevelTextureOffset(formattedLevel.charAt(0)), + value: levelTextureOffsets[0], }; uniform.siteLevelSecondCharacterOffset = { - value: dispatchSiteLevelTextureOffset(formattedLevel.charAt(1)), + value: levelTextureOffsets[1], }; return uniform; - }, [props.level, siteLevels]); + }, [siteLevels, levelTextureOffsets]); const vertexShader = ` varying vec2 vUv; diff --git a/src/components/MainScene/Site/Site.tsx b/src/components/MainScene/Site/Site.tsx index 1603e0a..7d92571 100644 --- a/src/components/MainScene/Site/Site.tsx +++ b/src/components/MainScene/Site/Site.tsx @@ -43,19 +43,31 @@ const Site = (props: SiteProps) => { config: { duration: 1200 }, })); - useEffect(() => { - useStore.subscribe(setRotY, (state) => ({ - y: state.siteRot[1], - delay: 1100, - })); - useStore.subscribe(setRotX, (state) => ({ - x: state.siteRot[0], - })); - useStore.subscribe(setPos, (state) => ({ - y: -level_y_values[state.activeLevel as keyof typeof level_y_values], - delay: 1300, - })); - }, [setPos, setRotX, setRotY]); + useEffect( + () => + useStore.subscribe(setRotY, (state) => ({ + y: state.siteRot[1], + delay: 1100, + })), + [setRotY] + ); + + useEffect( + () => + useStore.subscribe(setRotX, (state) => ({ + x: state.siteRot[0], + })), + [setRotX] + ); + + useEffect( + () => + useStore.subscribe(setPos, (state) => ({ + y: -level_y_values[state.activeLevel as keyof typeof level_y_values], + delay: 1300, + })), + [setPos] + ); const activeSite = useStore((state) => state.activeSite); const gameProgress = useStore((state) => state.gameProgress); diff --git a/src/components/MediaScene/Selectables/LeftSide.tsx b/src/components/MediaScene/Selectables/LeftSide.tsx index e8623a7..0eaca92 100644 --- a/src/components/MediaScene/Selectables/LeftSide.tsx +++ b/src/components/MediaScene/Selectables/LeftSide.tsx @@ -60,7 +60,7 @@ const LeftSide = memo(() => { { + setTimeout(() => playMediaElement(), 1200); + }, + ], +}; + export const playMedia = { state: [{ mutation: { mediaPercentageElapsed: 0, inputCooldown: 500 } }], + audio: [{ sfx: [audio.sound28] }], effects: [playMediaElement], }; diff --git a/src/core/input-handlers/handleMediaSceneInput.ts b/src/core/input-handlers/handleMediaSceneInput.ts index 9a7deb9..449e990 100644 --- a/src/core/input-handlers/handleMediaSceneInput.ts +++ b/src/core/input-handlers/handleMediaSceneInput.ts @@ -1,4 +1,7 @@ -import { findNodeFromWord } from "../../helpers/media-helpers"; +import { + findNodeFromWord, + playMediaElement, +} from "../../helpers/media-helpers"; import { changeLeftMediaComponent, changeMediaSide, @@ -8,6 +11,7 @@ import { resetInputCooldown, selectWord, wordNotFound, + playMediaMovie, } from "../eventTemplates"; import { isNodeVisible } from "../../helpers/node-helpers"; import { @@ -58,7 +62,10 @@ const handleMediaSceneInput = ( "media" ) as HTMLMediaElement; - if (!mediaElement.paused) return; + if (!mediaElement.paused) return resetInputCooldown; + + if (!activeNode.media_file.includes("XA")) return playMediaMovie; + return playMedia; case "exit": return exitMedia; diff --git a/src/scenes/EndScene.tsx b/src/scenes/EndScene.tsx index 6fe65c8..8753c7a 100644 --- a/src/scenes/EndScene.tsx +++ b/src/scenes/EndScene.tsx @@ -17,6 +17,7 @@ const EndScene = () => { (state) => state.setEndSceneSelectionVisible ); const setAudioAnalyser = useStore((state) => state.setAudioAnalyser); + const audioAnalyser = useStore((state) => state.audioAnalyser); useFrame(() => { if (mainCylinderRef.current) { @@ -44,14 +45,18 @@ const EndScene = () => { const setInputCooldown = useStore((state) => state.setInputCooldown); + useEffect(() => { + if (!audioAnalyser) setAudioAnalyser(createAudioAnalyser()); + }, [audioAnalyser, setAudioAnalyser]); + useEffect(() => { const mediaElement = document.getElementById("media") as HTMLMediaElement; if (mediaElement) { const playMedia = async (idx: number) => { switch (idx) { + // intro speech case 0: - setAudioAnalyser(createAudioAnalyser()); setObjectsVisible(true); setIsIntro(true); @@ -62,6 +67,7 @@ const EndScene = () => { mediaElement.play(); setIsIntro(false); break; + // name pronounciation syllable by syllable default: import("../static/voice/" + playerNameVoices[idx - 1] + ".mp4") .then((media) => { @@ -71,6 +77,7 @@ const EndScene = () => { }) .catch((e) => console.log(e)); break; + // outro laugh case playerNameVoices.length + 1: mediaElement.src = outroSpeech; mediaElement.load(); @@ -92,10 +99,16 @@ const EndScene = () => { playMedia(0); mediaElement.addEventListener("ended", () => { playedMediaCountRef.current++; - playMedia(playedMediaCountRef.current); + if (playedMediaCountRef.current <= playerNameVoices.length + 1) + playMedia(playedMediaCountRef.current); }); } - }, [playerNameVoices, setAudioAnalyser, setInputCooldown, setSelectionVisible]); + }, [ + playerNameVoices, + setAudioAnalyser, + setInputCooldown, + setSelectionVisible, + ]); return ( <> diff --git a/src/scenes/MediaScene.tsx b/src/scenes/MediaScene.tsx index 6fae4b7..c3096cb 100644 --- a/src/scenes/MediaScene.tsx +++ b/src/scenes/MediaScene.tsx @@ -30,23 +30,27 @@ const MediaScene = () => { const setNodeViewed = useStore.getState().setNodeViewed; + const isAudioOnly = useMemo(() => activeNode.media_file.includes("XA"), [ + activeNode, + ]); + useEffect(() => { if (percentageElapsed === 100) { + const mediaElement = document.getElementById("media") as HTMLMediaElement; + const trackElement = document.getElementById("track") as HTMLTrackElement; + + if (!isAudioOnly && mediaElement) { + mediaElement.currentTime = 0; + mediaElement.pause(); + } + setNodeViewed(activeNode.node_name); if (endrollPlayingRef.current) setScene("end"); - else if (!endrollPlayingRef.current && activeNode.triggers_final_video) { if (mediaSceneGroupRef.current) mediaSceneGroupRef.current.visible = false; - const mediaElement = document.getElementById( - "media" - ) as HTMLMediaElement; - const trackElement = document.getElementById( - "track" - ) as HTMLTrackElement; - if (mediaElement) { mediaElement.currentTime = 0; @@ -64,15 +68,12 @@ const MediaScene = () => { activeNode.node_name, activeNode.triggers_final_video, incrementFinalVideoViewCount, + isAudioOnly, percentageElapsed, setNodeViewed, setScene, ]); - const isAudioOnly = useMemo(() => activeNode.media_file.includes("XA"), [ - activeNode, - ]); - useEffect(() => { const mediaElement = document.getElementById("media") as HTMLMediaElement; const trackElement = document.getElementById("track") as HTMLTrackElement;