From dc545ba5222b7e505d5f657893b8947ca9cf1ae0 Mon Sep 17 00:00:00 2001 From: ad044 Date: Wed, 3 Feb 2021 22:54:58 +0400 Subject: [PATCH] word sleection animation --- src/components/MainScene/Lain.tsx | 25 ++++++- .../MainScene/SyncedComponentLoader.tsx | 69 ------------------- .../MainScene/SyncedComponents/MiddleRing.tsx | 15 ++++ .../MainScene/SyncedComponents/Site.tsx | 51 +++++++------- .../MainScene/SyncedComponents/Starfield.tsx | 5 +- src/core/setters/main/site/nodeManager.ts | 6 +- src/core/setters/main/site/siteManager.ts | 1 - src/core/setters/media/mediaManager.ts | 9 ++- src/resources/node_matrices.json | 2 +- src/scenes/MainScene.tsx | 55 +++++++++++---- src/store.ts | 5 +- src/utils/media-utils.ts | 7 +- 12 files changed, 129 insertions(+), 121 deletions(-) delete mode 100644 src/components/MainScene/SyncedComponentLoader.tsx diff --git a/src/components/MainScene/Lain.tsx b/src/components/MainScene/Lain.tsx index 52206ff..2975f29 100644 --- a/src/components/MainScene/Lain.tsx +++ b/src/components/MainScene/Lain.tsx @@ -1,4 +1,4 @@ -import React, { Suspense, useEffect, useMemo, useState } from "react"; +import React, { Suspense, useEffect, useMemo, useRef, useState } from "react"; import { useFrame, useLoader } from "react-three-fiber"; import * as THREE from "three"; import { PlainSingularAnimator } from "three-plain-animator/lib/plain-singular-animator"; @@ -66,6 +66,7 @@ export const LainConstructor = (props: LainConstructorProps) => { attach="material" map={lainSpriteTexture} alphaTest={0.01} + color={0xffffff} /> ); }; @@ -355,6 +356,8 @@ type LainProps = { const Lain = (props: LainProps) => { const lainMoveState = useStore((state) => state.lainMoveState); + const wordSelected = useStore((state) => state.wordSelected); + const lainAnimationDispatch = useMemo(() => { const anims = { standing: , @@ -401,9 +404,27 @@ const Lain = (props: LainProps) => { return props.shouldIntro ? introFinished : true; }, [introFinished, props.shouldIntro]); + const lainRef = useRef(); + + const glowColor = useMemo(() => new THREE.Color(2, 2, 2), []); + const regularColor = useMemo(() => new THREE.Color(1, 1, 1), []); + + useEffect(() => { + if (wordSelected) + setTimeout(() => { + if (lainRef.current) lainRef.current.material.color = glowColor; + }, 3100); + }, [glowColor, wordSelected]); + + useFrame(() => { + if (lainRef.current) { + lainRef.current.material.color.lerp(regularColor, 0.07); + } + }); + return ( - + {stopIntroAnim ? lainAnimationDispatch : } diff --git a/src/components/MainScene/SyncedComponentLoader.tsx b/src/components/MainScene/SyncedComponentLoader.tsx deleted file mode 100644 index 2ed9b21..0000000 --- a/src/components/MainScene/SyncedComponentLoader.tsx +++ /dev/null @@ -1,69 +0,0 @@ -import React, { useEffect, useMemo, useState } from "react"; -import HUD from "./SyncedComponents/HUD"; -import YellowTextRenderer from "../TextRenderer/YellowTextRenderer"; -import YellowOrb from "./SyncedComponents/YellowOrb"; -import GrayPlanes from "./SyncedComponents/GrayPlanes"; -import Starfield from "./SyncedComponents/Starfield"; -import Site from "./SyncedComponents/Site"; -import MiddleRing from "./SyncedComponents/MiddleRing"; -import Lain from "./Lain"; -import { useStore } from "../../store"; - -type SyncedComponentLoaderProps = { - paused: boolean; - shouldIntro: boolean; -}; - -const SyncedComponentLoader = (props: SyncedComponentLoaderProps) => { - const [introFinished, setIntroFinished] = useState(false); - const [paused, setPaused] = useState(false); - - useEffect(() => { - if (!props.shouldIntro) { - document.getElementsByTagName("canvas")[0].className = - "main-scene-background"; - } - setTimeout(() => { - setIntroFinished(true); - document.getElementsByTagName("canvas")[0].className = - "main-scene-background"; - }, 4000); - }, [props.shouldIntro]); - - const subscene = useStore((state) => state.mainSubscene); - - useEffect(() => { - if (subscene === "pause") { - setTimeout(() => { - setPaused(true); - }, 3400); - } else { - setPaused(false); - } - }, [subscene]); - - const visible = useMemo(() => { - return props.shouldIntro ? introFinished : true; - }, [introFinished, props.shouldIntro]); - - return ( - <> - - - - - - - - - - - - ); -}; - -export default SyncedComponentLoader; diff --git a/src/components/MainScene/SyncedComponents/MiddleRing.tsx b/src/components/MainScene/SyncedComponents/MiddleRing.tsx index c521fec..4f8166e 100644 --- a/src/components/MainScene/SyncedComponents/MiddleRing.tsx +++ b/src/components/MainScene/SyncedComponents/MiddleRing.tsx @@ -158,6 +158,8 @@ const MiddleRing = () => { const clock = new THREE.Clock(); + const wordSelected = useStore((state) => state.wordSelected); + const [wobbleAmp, setWobbleAmp] = useState(0); const [noiseAmp, setNoiseAmp] = useState(0.03); const [rotating, setRotating] = useState(true); @@ -352,6 +354,16 @@ const MiddleRing = () => { }, 950); }; + const afterWordSelection = () => { + setRotating(true); + setRot({ rotX: -0.4 }); + + // reset the rotation value to 0 + setTimeout(() => { + setRot({ rotZ: 0, rotX: 0 }); + }, 3100); + }; + if (prevData?.siteRotY !== undefined && prevData?.siteRotY !== siteRotY) { rotate(prevData?.siteRotY > siteRotY ? [-0.07, 0.03] : [0.07, -0.03]); } else if ( @@ -367,6 +379,8 @@ const MiddleRing = () => { pause(); } else if (subscene === "site" && prevData?.subscene === "pause") { unpause(); + } else if (wordSelected) { + afterWordSelection(); } }, [ activeLevel, @@ -377,6 +391,7 @@ const MiddleRing = () => { setRot, siteRotY, subscene, + wordSelected, ]); return ( diff --git a/src/components/MainScene/SyncedComponents/Site.tsx b/src/components/MainScene/SyncedComponents/Site.tsx index cd655f6..5887c28 100644 --- a/src/components/MainScene/SyncedComponents/Site.tsx +++ b/src/components/MainScene/SyncedComponents/Site.tsx @@ -10,8 +10,8 @@ import * as THREE from "three"; import site_a from "../../../resources/site_a.json"; import site_b from "../../../resources/site_b.json"; import level_y_values from "../../../resources/level_y_values.json"; -import usePrevious from "../../../hooks/usePrevious"; import { filterInvisibleNodes } from "../../../utils/node-utils"; +import usePrevious from "../../../hooks/usePrevious"; export type NodeDataType = { id: string; @@ -48,33 +48,34 @@ type SiteProps = { }; const Site = (props: SiteProps) => { - const activeLevel = useStore((state) => state.activeLevel); + const wordSelected = useStore((state) => state.wordSelected); - const [state, setState] = useSpring(() => ({ - posY: -level_y_values[ - useStore.getState().activeLevel as keyof typeof level_y_values - ], - rotX: useStore.getState().siteRot[0], - rotY: useStore.getState().siteRot[1], + const [rotState, setRot] = useSpring(() => ({ + x: wordSelected ? 0 : useStore.getState().siteRot[0], + y: wordSelected ? 0 : useStore.getState().siteRot[1], + config: { duration: 1200 }, + })); + + const [posState, setPos] = useSpring(() => ({ + y: wordSelected + ? 0 + : -level_y_values[ + useStore.getState().activeLevel as keyof typeof level_y_values + ], + delay: 1300, config: { duration: 1200 }, })); useEffect(() => { - setTimeout(() => { - setState({ - posY: -level_y_values[activeLevel as keyof typeof level_y_values], - }); - }, 1200); - }, [activeLevel, setState]); - - useEffect(() => { - useStore.subscribe(setState, (state) => { - return { - rotX: state.siteRot[0], - rotY: state.siteRot[1], - }; - }); - }, [setState]); + useStore.subscribe(setRot, (state) => ({ + x: state.siteRot[0], + y: state.siteRot[1], + })); + useStore.subscribe(setPos, (state) => ({ + y: -level_y_values[state.activeLevel as keyof typeof level_y_values], + delay: 1300, + })); + }, [setPos, setRot]); const introWrapperRef = useRef(); @@ -110,8 +111,8 @@ const Site = (props: SiteProps) => { return ( - - + + { }, []); return ( - + <> { ) : ( <> )} - + ); }); diff --git a/src/core/setters/main/site/nodeManager.ts b/src/core/setters/main/site/nodeManager.ts index 283a4eb..969ffd4 100644 --- a/src/core/setters/main/site/nodeManager.ts +++ b/src/core/setters/main/site/nodeManager.ts @@ -156,13 +156,13 @@ const nodeManager = (eventState: any) => { case "site_right": case "select_level_up": case "select_level_down": - case "media_fstWord_select": - case "media_sndWord_select": - case "media_thirdWord_select": return { action: () => updateActiveNode(eventState.node, 3900), }; case "change_node": + case "media_fstWord_select": + case "media_sndWord_select": + case "media_thirdWord_select": return { action: () => updateActiveNode(eventState.node), }; diff --git a/src/core/setters/main/site/siteManager.ts b/src/core/setters/main/site/siteManager.ts index bca996f..c4c45e2 100644 --- a/src/core/setters/main/site/siteManager.ts +++ b/src/core/setters/main/site/siteManager.ts @@ -5,7 +5,6 @@ const siteManager = (eventState: any) => { const setRotX = useStore.getState().setSiteRotX; const dispatchAction = (eventState: any) => { - console.log(eventState.siteRotY); switch (eventState.event) { case "site_left": case "site_right": diff --git a/src/core/setters/media/mediaManager.ts b/src/core/setters/media/mediaManager.ts index 4654241..a7a9857 100644 --- a/src/core/setters/media/mediaManager.ts +++ b/src/core/setters/media/mediaManager.ts @@ -7,6 +7,8 @@ const mediaManager = (eventState: any) => { const setLeftComponentMatrixIdx = useStore.getState() .setMediaLeftComponentMatrixIdx; + const setWordSelected = useStore.getState().setWordSelected; + const updateRightSide = useStore.getState().updateRightSide; const resetScene = useStore.getState().resetMediaScene; @@ -71,7 +73,12 @@ const mediaManager = (eventState: any) => { case "media_fstWord_select": case "media_sndWord_select": case "media_thirdWord_select": - return { action: () => undefined }; + return { + action: () => { + exitMedia(); + setWordSelected(true); + }, + }; } }; diff --git a/src/resources/node_matrices.json b/src/resources/node_matrices.json index a20b492..4b50451 100644 --- a/src/resources/node_matrices.json +++ b/src/resources/node_matrices.json @@ -21,7 +21,7 @@ ], "5": [ ["20", "23", "16", "19"], - ["12", "15", "09", "11"], + ["12", "15", "08", "11"], ["04", "07", "00", "03"] ], "6": [ diff --git a/src/scenes/MainScene.tsx b/src/scenes/MainScene.tsx index dac7e77..3a620ae 100644 --- a/src/scenes/MainScene.tsx +++ b/src/scenes/MainScene.tsx @@ -1,30 +1,59 @@ import { OrbitControls } from "@react-three/drei"; -import React, { Suspense, useEffect, useMemo } from "react"; -import Preloader from "../components/Preloader"; +import React, { Suspense, useEffect, useState } from "react"; import { useStore } from "../store"; import Pause from "../components/MainScene/PauseSubscene/Pause"; -import SyncedComponentLoader from "../components/MainScene/SyncedComponentLoader"; import LevelSelection from "../components/MainScene/SyncedComponents/LevelSelection"; +import HUD from "../components/MainScene/SyncedComponents/HUD"; +import YellowTextRenderer from "../components/TextRenderer/YellowTextRenderer"; +import YellowOrb from "../components/MainScene/SyncedComponents/YellowOrb"; +import MiddleRing from "../components/MainScene/SyncedComponents/MiddleRing"; +import GrayPlanes from "../components/MainScene/SyncedComponents/GrayPlanes"; +import Starfield from "../components/MainScene/SyncedComponents/Starfield"; +import Site from "../components/MainScene/SyncedComponents/Site"; +import Lain from "../components/MainScene/Lain"; const MainScene = () => { - const currentSubscene = useStore((state) => state.mainSubscene); - const shouldIntro = useStore((state) => state.intro); + const [paused, setPaused] = useState(false); + const subscene = useStore((state) => state.mainSubscene); - const isPaused = useMemo(() => currentSubscene === "pause", [ - currentSubscene, - ]); + const wordSelected = useStore((state) => state.wordSelected); + const setWordSelected = useStore((state) => state.setWordSelected); useEffect(() => { - return () => { - document.getElementsByTagName("canvas")[0].className = ""; - }; - }, []); + if (subscene === "pause") { + setTimeout(() => { + setPaused(true); + }, 3400); + } else { + setPaused(false); + } + }, [subscene]); + + useEffect(() => { + if (wordSelected) { + setTimeout(() => { + setWordSelected(false); + }, 3100); + } + }, [setWordSelected, wordSelected]); + return ( - + + + + + + + + + + + + diff --git a/src/store.ts b/src/store.ts index 573cd19..4ae1bc4 100644 --- a/src/store.ts +++ b/src/store.ts @@ -53,6 +53,7 @@ type State = { rightSideIdx: 0 | 1 | 2; }; mediaWordPosStateIdx: number; + wordSelected: boolean; // idle scene idleMedia: string; @@ -114,7 +115,7 @@ export const useStore = create( combine( { // scene data - currentScene: "media", + currentScene: "main", // game progress gameProgress: game_progress, @@ -198,6 +199,7 @@ export const useStore = create( rightSideIdx: 0, }, mediaWordPosStateIdx: 1, + wordSelected: false, // idle scene idleMedia: "INS01.STR", @@ -350,6 +352,7 @@ export const useStore = create( rightSideIdx: 0, }, })), + setWordSelected: (to: boolean) => set(() => ({ wordSelected: to })), // idle media setters setIdleMedia: (to: any) => set(() => ({ idleMedia: to })), diff --git a/src/utils/media-utils.ts b/src/utils/media-utils.ts index 8c89386..3ff98b5 100644 --- a/src/utils/media-utils.ts +++ b/src/utils/media-utils.ts @@ -46,7 +46,9 @@ export const findNodeFromWord = ( const matrixIndices = Object.entries(node_matrices).flatMap((matrixData) => matrixData[1].flatMap((row, idx) => - row[0] === pos ? { matrixIdx: matrixData[0], rowIdx: idx, colIdx: 0 } : [] + row[0] === pos + ? { matrixIdx: parseInt(matrixData[0]), rowIdx: idx, colIdx: 0 } + : [] ) )[0]; @@ -66,7 +68,8 @@ export const findNodeFromWord = ( ...chosenNode, matrixIndices: matrixIndices, }, - siteRotY: rotValues[matrixIndices.matrixIdx as keyof typeof rotValues], + siteRotY: + rotValues[matrixIndices.matrixIdx.toString() as keyof typeof rotValues], level: chosenNode.id.substr(0, 2), }; };