From 7b67f441355cca287863c0709faaabd9e11fbe7e Mon Sep 17 00:00:00 2001 From: ad044 Date: Sat, 9 Jan 2021 21:30:42 +0400 Subject: [PATCH] all node interaction animations finished --- src/components/MainScene/Lain.tsx | 2 +- .../MainScene/SyncedComponents/Site/Node.tsx | 53 +++++++---- .../NodeExplosion/ExplosionLine.tsx | 3 +- .../Site/NodeAnimations/NodeRip.tsx | 92 ++++++++++++++++++- .../Site/NodeAnimations/NodeRip/RipLine.tsx | 31 +++++++ .../NodeAnimations/NodeRip/TriangleNode.tsx | 15 ++- .../MainSceneManagers/LainManager.tsx | 16 ++-- .../MainSceneManagers/NodeManager.tsx | 58 +++++++++++- src/core/StateManagers/SceneManager.tsx | 11 +++ src/core/mainSceneEventHandler.ts | 12 +-- src/store.ts | 2 + 11 files changed, 247 insertions(+), 48 deletions(-) create mode 100644 src/components/MainScene/SyncedComponents/Site/NodeAnimations/NodeRip/RipLine.tsx diff --git a/src/components/MainScene/Lain.tsx b/src/components/MainScene/Lain.tsx index 9dd4e40..26f5294 100644 --- a/src/components/MainScene/Lain.tsx +++ b/src/components/MainScene/Lain.tsx @@ -192,7 +192,7 @@ const Lain = (props: LainProps) => { select_level_up: , throw_node: , pause_game: , - test: , + rip_node: , }; const [introFinished, setIntroFinished] = useState(false); diff --git a/src/components/MainScene/SyncedComponents/Site/Node.tsx b/src/components/MainScene/SyncedComponents/Site/Node.tsx index e4bc270..b3a6ee3 100644 --- a/src/components/MainScene/SyncedComponents/Site/Node.tsx +++ b/src/components/MainScene/SyncedComponents/Site/Node.tsx @@ -122,6 +122,7 @@ const Node = (props: NodeContructorProps) => { activeNodePosZ, activeNodeRotZ, activeNodeVisible, + activeNodeScale, }, set, ] = useSpring(() => ({ @@ -138,6 +139,9 @@ const Node = (props: NodeContructorProps) => { activeNodeRotZ: useNodeStore.getState().activeNodeState.interactedWith ? useNodeStore.getState().activeNodeState.rotZ : 0, + activeNodeScale: useNodeStore.getState().activeNodeState.shrinking + ? 0 + : 1, activeNodeVisible: true, config: { duration: 800 }, })); @@ -156,6 +160,9 @@ const Node = (props: NodeContructorProps) => { activeNodeRotZ: useNodeStore.getState().activeNodeState.interactedWith ? state.activeNodeState.rotZ : 0, + activeNodeScale: useNodeStore.getState().activeNodeState.shrinking + ? 0 + : 1, activeNodeVisible: useNodeStore.getState().activeNodeState.visible, })); }, [ @@ -184,27 +191,33 @@ const Node = (props: NodeContructorProps) => { ]} > {props.active ? ( - - - - + + + + + ) : ( { renderOrder={2} > - { + const nodeShrinking = useNodeStore( + (state) => state.activeNodeState.shrinking + ); + const [shouldAnimate, setShouldAnimate] = useState(false); + + const LCG = (a: number, c: number, m: number, s: number) => () => + (s = (s * a + c) % m); + + const lcgInstance = LCG(1664525, 1013904223, 2 ** 32, 2); + + const firstLineSet = Array.from({ length: 25 }, (_, idx) => { + let coordSet = [lcgInstance() / 7000000000, lcgInstance() / 7000000000]; + if (coordSet[0] > 0.45) coordSet[0] = coordSet[0] * -1; + if (coordSet[1] > 0.45) coordSet[1] = coordSet[1] * -1; + + const color = idx % 2 === 0 ? "red" : "yellow"; + + return { coordinates: coordSet, color: color }; + }); + + const sndLineSet = Array.from({ length: 25 }, (_, idx) => { + let coordSet = [lcgInstance() / 6000000000, lcgInstance() / 6000000000]; + if (coordSet[0] > 0.65) coordSet[0] = coordSet[0] * -1; + if (coordSet[1] > 0.65) coordSet[1] = coordSet[1] * -1; + + const color = idx % 2 === 0 ? "yellow" : "red"; + + return { coordinates: coordSet, color: color }; + }); + + const [currentFrame, setCurrentFrame] = useState(0); + + const lastTime = useRef(0); + + useFrame(() => { + if (shouldAnimate) { + const now = Date.now(); + if (currentFrame < 3) { + if (now > lastTime.current + 200) { + setCurrentFrame(currentFrame + 1); + lastTime.current = now; + } + } + } + }); + + useEffect(() => { + if (nodeShrinking) { + setTimeout(() => { + setShouldAnimate(true); + }, 1150); + } else { + setShouldAnimate(false); + setCurrentFrame(1); + } + }, [nodeShrinking]); + return ( - <> + - + + + {firstLineSet.map((data, idx) => ( + + ))} + + + + {sndLineSet.map((data, idx) => ( + + ))} + + + ); }; diff --git a/src/components/MainScene/SyncedComponents/Site/NodeAnimations/NodeRip/RipLine.tsx b/src/components/MainScene/SyncedComponents/Site/NodeAnimations/NodeRip/RipLine.tsx new file mode 100644 index 0000000..6848380 --- /dev/null +++ b/src/components/MainScene/SyncedComponents/Site/NodeAnimations/NodeRip/RipLine.tsx @@ -0,0 +1,31 @@ +import React, { useMemo } from "react"; +import * as THREE from "three"; + +type RipLineProps = { + color: string; + endPoints: number[]; +}; + +const RipLine = (props: RipLineProps) => { + const horizontalPoints = useMemo( + () => [ + new THREE.Vector3(0, 0, 0), + new THREE.Vector3(props.endPoints[0], props.endPoints[1], 0), + ], + [props.endPoints] + ); + + return ( + + + + + ); +}; + +export default RipLine; diff --git a/src/components/MainScene/SyncedComponents/Site/NodeAnimations/NodeRip/TriangleNode.tsx b/src/components/MainScene/SyncedComponents/Site/NodeAnimations/NodeRip/TriangleNode.tsx index 5b8ab2b..29b94c4 100644 --- a/src/components/MainScene/SyncedComponents/Site/NodeAnimations/NodeRip/TriangleNode.tsx +++ b/src/components/MainScene/SyncedComponents/Site/NodeAnimations/NodeRip/TriangleNode.tsx @@ -1,4 +1,4 @@ -import React, { useRef } from "react"; +import React, { useEffect, useRef } from "react"; import MULTI from "../../../../../../static/sprite/MULTI.png"; import { useFrame, useLoader } from "react-three-fiber"; import * as THREE from "three"; @@ -6,6 +6,7 @@ import * as THREE from "three"; type TriangleNodeProps = { rotation: number[]; pivotRotation: number[]; + shouldAnimate: boolean; }; const TriangleNode = (props: TriangleNodeProps) => { @@ -14,15 +15,21 @@ const TriangleNode = (props: TriangleNodeProps) => { const triangleNodeRef = useRef(); useFrame(() => { - if (triangleNodeRef.current) { - triangleNodeRef.current.position.z += 0.01; + if (triangleNodeRef.current && props.shouldAnimate) { + triangleNodeRef.current.position.z += 0.05; } }); + useEffect(() => { + if (triangleNodeRef.current && !props.shouldAnimate) { + triangleNodeRef.current.position.z = 0; + } + }, [props.shouldAnimate]); + return ( { case "select_level_up": case "select_level_down": case "pause_game": + case "knock_node": return { action: setLainMoveState, value: eventState.event, @@ -29,11 +30,14 @@ const LainManager = (props: StateManagerProps) => { value: "throw_node", duration: 3900, }; - case "knock_node": + case "rip_node_media": + case "rip_node_gate": + case "rip_node_sskn": + case "rip_node_tak": return { action: setLainMoveState, - value: "knock_node", - duration: 3900, + value: "rip_node", + duration: 6000, }; case "knock_node_and_fall": return { @@ -41,12 +45,6 @@ const LainManager = (props: StateManagerProps) => { value: "knock_node_and_fall", duration: 6000, }; - case "test": - return { - action: setLainMoveState, - value: "test", - duration: 3900, - }; } }, [setLainMoveState] diff --git a/src/core/StateManagers/MainSceneManagers/NodeManager.tsx b/src/core/StateManagers/MainSceneManagers/NodeManager.tsx index 439d411..b87b858 100644 --- a/src/core/StateManagers/MainSceneManagers/NodeManager.tsx +++ b/src/core/StateManagers/MainSceneManagers/NodeManager.tsx @@ -122,6 +122,55 @@ const NodeManager = (props: StateManagerProps) => { [setActiveNodeState] ); + const animateShrinkAndRip = useCallback( + (siteRotY: number) => { + setActiveNodeState(true, "interactedWith"); + + const fstCoordSet = calculateCoordsBasedOnRotation(0.9, 0.3, siteRotY); + const sndCoordSet = calculateCoordsBasedOnRotation(0.5, 0.2, siteRotY); + const thirdCoordSet = calculateCoordsBasedOnRotation(0, 0.2, siteRotY); + + setActiveNodeState(fstCoordSet.x, "posX"); + setActiveNodeState(fstCoordSet.z, "posZ"); + setActiveNodeState(0, "posY"); + + setTimeout(() => { + setActiveNodeState(sndCoordSet.x, "posX"); + setActiveNodeState(sndCoordSet.z, "posZ"); + }, 800); + + setTimeout(() => { + setActiveNodeState(thirdCoordSet.x, "posX"); + setActiveNodeState(thirdCoordSet.z, "posZ"); + setActiveNodeState(-0.4, "posY"); + }, 2800); + + setTimeout(() => { + setActiveNodeState(true, "shrinking"); + }, 3000); + + setTimeout(() => { + setActiveNodeState(-1.5, "posY"); + }, 3200); + + setTimeout(() => { + setActiveNodeState(false, "visible"); + }, 3500); + + setTimeout(() => { + setActiveNodeState(false, "interactedWith"); + setActiveNodeState(false, "shrinking"); + setActiveNodeState(0, "rotZ"); + setActiveNodeState(0, "rotX"); + }, 6400); + + setTimeout(() => { + setActiveNodeState(true, "visible"); + }, 7500); + }, + [setActiveNodeState] + ); + const updateActiveNode = useCallback( ( newActiveNodeId: string, @@ -181,14 +230,17 @@ const NodeManager = (props: StateManagerProps) => { action: animateActiveNodeThrow, value: [eventState.siteRotY], }; - case "test": + case "rip_node_media": + case "rip_node_gate": + case "rip_node_sskn": + case "rip_node_tak": return { - action: animateNodeTouchAndScare, + action: animateShrinkAndRip, value: [eventState.siteRotY], }; } }, - [animateActiveNodeThrow, animateNodeKnock, updateActiveNode] + [animateActiveNodeThrow, animateShrinkAndRip, updateActiveNode] ); useEffect(() => { diff --git a/src/core/StateManagers/SceneManager.tsx b/src/core/StateManagers/SceneManager.tsx index 2664df9..cb9f865 100644 --- a/src/core/StateManagers/SceneManager.tsx +++ b/src/core/StateManagers/SceneManager.tsx @@ -19,6 +19,17 @@ const SceneManager = (props: StateManagerProps) => { delay: 3450, setMainSceneIntro: false, }; + case "rip_node_media": + case "rip_node_gate": + case "rip_node_sskn": + case "rip_node_tak": + return { + action: setScene, + value: eventState.scene, + delay: 6000, + setMainSceneIntro: false, + }; + case "media_exit_select": case "exit_gate": case "sskn_cancel_select": diff --git a/src/core/mainSceneEventHandler.ts b/src/core/mainSceneEventHandler.ts index 64cc658..a72fc9c 100644 --- a/src/core/mainSceneEventHandler.ts +++ b/src/core/mainSceneEventHandler.ts @@ -67,7 +67,7 @@ const handleMainSceneEvent = (gameContext: any) => { ]; const nodeType = nodeData.type; - const eventAnimation = "throw_node_"; + const eventAnimation = Math.random() < 0.4 ? "rip_node" : "throw_node"; switch (nodeType) { case 0: @@ -75,24 +75,24 @@ const handleMainSceneEvent = (gameContext: any) => { case 4: case 3: case 5: - event = eventAnimation + "media"; + event = `${eventAnimation}_media`; scene = "media"; break; case 6: if (nodeData.node_name.substr(0, 3) === "TaK") { - event = eventAnimation + "tak"; + event = `${eventAnimation}_tak`; scene = "tak"; } else { - event = eventAnimation + "media"; + event = `${eventAnimation}_media`; scene = "media"; } break; case 8: - event = eventAnimation + "gate"; + event = `${eventAnimation}_gate`; scene = "gate"; break; case 7: - event = eventAnimation + "sskn"; + event = `${eventAnimation}_sskn`; scene = "sskn"; break; } diff --git a/src/store.ts b/src/store.ts index 9dc5617..50d1854 100644 --- a/src/store.ts +++ b/src/store.ts @@ -65,6 +65,7 @@ type NodeState = { rotZ: number; interactedWith: boolean; exploding: boolean; + shrinking: boolean; visible: boolean; }; nodeMatrixIndices: { matrixIdx: number; rowIdx: number; colIdx: number }; @@ -298,6 +299,7 @@ export const useNodeStore = create( posY: 0, interactedWith: false, exploding: false, + shrinking: false, visible: true, }, nodeMatrixIndices: { matrixIdx: 7, rowIdx: 0, colIdx: 0 },