From 2c4dff77b35e03eac4bb24b1e7b27c1b12581a12 Mon Sep 17 00:00:00 2001 From: ad044 Date: Thu, 7 Jan 2021 20:47:26 +0400 Subject: [PATCH] node explosion almost done, imported node rip anim --- src/components/MainScene/Lain.tsx | 15 ++- .../MainScene/SyncedComponents/Site/Node.tsx | 27 +--- .../SyncedComponents/Site/NodeExplosion.tsx | 66 +++++++--- .../Site/NodeExplosion/ExplosionLine.tsx | 2 +- .../Site/NodeExplosion/GoldNode.tsx | 121 ++++++++++++++++++ src/components/Preloader.tsx | 4 + .../MainSceneManagers/NodeManager.tsx | 18 ++- .../node_explosion_line_positions.json | 6 - src/scenes/MainScene.tsx | 2 +- src/store.ts | 8 +- 10 files changed, 214 insertions(+), 55 deletions(-) create mode 100644 src/components/MainScene/SyncedComponents/Site/NodeExplosion/GoldNode.tsx diff --git a/src/components/MainScene/Lain.tsx b/src/components/MainScene/Lain.tsx index 51ee399..9dd4e40 100644 --- a/src/components/MainScene/Lain.tsx +++ b/src/components/MainScene/Lain.tsx @@ -13,6 +13,7 @@ import ripMiddleRingSpriteSheet from "../../static/sprite/rip_middle_ring.png"; import knockSpriteSheet from "../../static/sprite/knock.png"; import knockAndFallSpriteSheet from "../../static/sprite/knock_and_fall.png"; import touchAndScareSpriteSheet from "../../static/sprite/touch_and_scare.png"; +import ripNodeSpriteSheet from "../../static/sprite/rip_node.png"; import { useLainStore, useMainSceneStore } from "../../store"; type LainConstructorProps = { @@ -162,6 +163,18 @@ export const LainTouchAndScare = () => { ); }; +export const LainRipNode = () => { + return ( + + ); +}; + type LainProps = { shouldIntro: boolean; }; @@ -179,7 +192,7 @@ const Lain = (props: LainProps) => { select_level_up: , throw_node: , pause_game: , - test: , + test: , }; const [introFinished, setIntroFinished] = useState(false); diff --git a/src/components/MainScene/SyncedComponents/Site/Node.tsx b/src/components/MainScene/SyncedComponents/Site/Node.tsx index 4be2318..e4bc270 100644 --- a/src/components/MainScene/SyncedComponents/Site/Node.tsx +++ b/src/components/MainScene/SyncedComponents/Site/Node.tsx @@ -74,17 +74,14 @@ const Node = (props: NodeContructorProps) => { const nonActiveTexture = useLoader(THREE.TextureLoader, sprite[0]); const activeTexture = useLoader(THREE.TextureLoader, sprite[1]); - const goldTexture = useLoader(THREE.TextureLoader, sprite[2]); const uniforms = useMemo( () => ({ tex1: { type: "t", value: nonActiveTexture }, tex2: { type: "t", value: activeTexture }, - tex3: { type: "t", value: goldTexture }, - goldTextureBias: { value: 0 }, timeMSeconds: { value: (Date.now() % (Math.PI * 2000)) / 1000.0 }, }), - [nonActiveTexture, activeTexture, goldTexture] + [nonActiveTexture, activeTexture] ); const vertexShader = ` @@ -101,9 +98,7 @@ const Node = (props: NodeContructorProps) => { uniform sampler2D tex1; uniform sampler2D tex2; - uniform sampler2D tex3; uniform float timeMSeconds; - uniform float goldTextureBias; varying vec2 vUv; @@ -112,9 +107,8 @@ const Node = (props: NodeContructorProps) => { void main() { vec4 t1 = texture2D(tex1,vUv); vec4 t2 = texture2D(tex2,vUv); - vec4 t3 = texture2D(tex3,vUv); float bias = abs(sin(timeMSeconds / (1.6 / M_PI))); - gl_FragColor = mix(mix(t1, t2, bias), t3, goldTextureBias); + gl_FragColor = mix(t1, t2, bias); } `; @@ -127,8 +121,7 @@ const Node = (props: NodeContructorProps) => { activeNodePosY, activeNodePosZ, activeNodeRotZ, - activeNodeRotY, - goldTextureBias, + activeNodeVisible, }, set, ] = useSpring(() => ({ @@ -145,10 +138,7 @@ const Node = (props: NodeContructorProps) => { activeNodeRotZ: useNodeStore.getState().activeNodeState.interactedWith ? useNodeStore.getState().activeNodeState.rotZ : 0, - activeNodeRotY: useNodeStore.getState().activeNodeState.interactedWith - ? useNodeStore.getState().activeNodeState.rotY - : props.rotation[1], - goldTextureBias: useNodeStore.getState().activeNodeState.goldTextureBias, + activeNodeVisible: true, config: { duration: 800 }, })); @@ -166,10 +156,7 @@ const Node = (props: NodeContructorProps) => { activeNodeRotZ: useNodeStore.getState().activeNodeState.interactedWith ? state.activeNodeState.rotZ : 0, - activeNodeRotY: useNodeStore.getState().activeNodeState.interactedWith - ? state.activeNodeState.rotY - : props.rotation[1], - goldTextureBias: useNodeStore.getState().activeNodeState.goldTextureBias, + activeNodeVisible: useNodeStore.getState().activeNodeState.visible, })); }, [ props.level, @@ -185,7 +172,6 @@ const Node = (props: NodeContructorProps) => { if (materialRef.current) { materialRef.current.uniforms.timeMSeconds.value = (Date.now() % (Math.PI * 2000)) / 1000.0; - materialRef.current.uniforms.goldTextureBias.value = goldTextureBias.get(); } }); @@ -203,7 +189,8 @@ const Node = (props: NodeContructorProps) => { position-y={activeNodePosY} position-z={activeNodePosZ} rotation-z={activeNodeRotZ} - rotation-y={activeNodeRotY} + rotation-y={props.rotation[1]} + visible={activeNodeVisible} scale={[0.36, 0.18, 0.36]} renderOrder={1} > diff --git a/src/components/MainScene/SyncedComponents/Site/NodeExplosion.tsx b/src/components/MainScene/SyncedComponents/Site/NodeExplosion.tsx index d236751..a7e9a04 100644 --- a/src/components/MainScene/SyncedComponents/Site/NodeExplosion.tsx +++ b/src/components/MainScene/SyncedComponents/Site/NodeExplosion.tsx @@ -1,9 +1,18 @@ -import React, { useMemo, useRef, useState } from "react"; +import React, { useEffect, useMemo, useRef, useState } from "react"; import ExplosionLine from "./NodeExplosion/ExplosionLine"; import node_explosion_line_positions from "../../../../resources/node_explosion_line_positions.json"; + import { useFrame } from "react-three-fiber"; +import GoldNode from "./NodeExplosion/GoldNode"; +import { useNodeStore } from "../../../../store"; const NodeExplosion = () => { + const explosionVisible = useNodeStore( + (state) => state.activeNodeState.exploding + ); + + const [shouldAnimate, setShouldAnimate] = useState(false); + const [shouldRotate, setShouldRotate] = useState(false); const [currentFrame, setCurrentFrame] = useState(1); const linePoses = useMemo( @@ -17,26 +26,53 @@ const NodeExplosion = () => { const lastTime = useRef(0); useFrame(() => { - const now = Date.now(); - if (now > lastTime.current + 2400) { - if (currentFrame < 6) { - setCurrentFrame(currentFrame + 1); - lastTime.current = now; + if (shouldAnimate) { + const now = Date.now(); + if (now > lastTime.current + 100) { + if (currentFrame < 6) { + setCurrentFrame(currentFrame + 1); + lastTime.current = now; + } } } }); - return ( + useEffect(() => { + if (explosionVisible) { + setTimeout(() => { + setShouldRotate(true); + }, 300); + setTimeout(() => { + setShouldAnimate(true); + }, 1100); + } else { + setShouldAnimate(false); + setShouldRotate(false); + setCurrentFrame(1); + } + }, [explosionVisible]); + + return explosionVisible ? ( - {Object.values(linePoses).map((entry) => ( - - ))} + + {Object.values(linePoses).map((entry, idx) => ( + + ))} + + + ) : ( + <> ); }; diff --git a/src/components/MainScene/SyncedComponents/Site/NodeExplosion/ExplosionLine.tsx b/src/components/MainScene/SyncedComponents/Site/NodeExplosion/ExplosionLine.tsx index 8ea6761..4cf78d7 100644 --- a/src/components/MainScene/SyncedComponents/Site/NodeExplosion/ExplosionLine.tsx +++ b/src/components/MainScene/SyncedComponents/Site/NodeExplosion/ExplosionLine.tsx @@ -44,7 +44,7 @@ const ExplosionLine = (props: LineProps) => { float alpha = smoothstep(1.0, 0.0, vUv.y); float colorMix = smoothstep(1.0, 2.0, 1.8); - gl_FragColor = vec4(mix(color1, color2, colorMix), alpha) * 0.8; + gl_FragColor = vec4(mix(color1, color2, colorMix), alpha) * 0.7; } `; diff --git a/src/components/MainScene/SyncedComponents/Site/NodeExplosion/GoldNode.tsx b/src/components/MainScene/SyncedComponents/Site/NodeExplosion/GoldNode.tsx new file mode 100644 index 0000000..379db2f --- /dev/null +++ b/src/components/MainScene/SyncedComponents/Site/NodeExplosion/GoldNode.tsx @@ -0,0 +1,121 @@ +import React, { useEffect, useMemo, useRef, useState } from "react"; +import { GLTF, GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader"; +import * as THREE from "three"; +import { useFrame, useLoader } from "react-three-fiber"; +import Cou from "../../../../../static/sprite/Cou.png"; +import CouGold from "../../../../../static/sprite/Cou_gold.png"; +import Dc from "../../../../../static/sprite/Dc.png"; +import DcGold from "../../../../../static/sprite/Dc_gold.png"; +import SSkn from "../../../../../static/sprite/SSkn.png"; +import SSKnGold from "../../../../../static/sprite/SSkn_gold.png"; +import Tda from "../../../../../static/sprite/Tda.png"; +import TdaGold from "../../../../../static/sprite/Tda_gold.png"; +import Dia from "../../../../../static/sprite/Dia.png"; +import DiaGold from "../../../../../static/sprite/Dia_gold.png"; +import Lda from "../../../../../static/sprite/Lda.png"; +import LdaGold from "../../../../../static/sprite/Lda_gold.png"; +import MULTI from "../../../../../static/sprite/MULTI.png"; +import MULTIGold from "../../../../../static/sprite/MULTI_gold.png"; +import { + useLevelStore, + useNodeStore, + useSiteStore, +} from "../../../../../store"; +import site_a from "../../../../../resources/site_a.json"; +import site_b from "../../../../../resources/site_b.json"; +import { SiteType } from "../../Site"; + +type GLTFResult = GLTF & { + nodes: { + Cube: THREE.Mesh; + }; + materials: { + Material: THREE.MeshStandardMaterial; + }; +}; + +type GoldNodeProps = { + visible: boolean; + goldTexture: boolean; +}; + +const GoldNode = (props: GoldNodeProps) => { + const { nodes } = useLoader(GLTFLoader, "models/goldNode.glb"); + const activeNodeId = useNodeStore((state) => state.activeNodeState.id); + const activeLevel = useLevelStore((state) => state.activeLevel); + + const currentSite = useSiteStore((state) => state.currentSite); + + const siteData = currentSite === "a" ? site_a : site_b; + + const activeNodeData = (siteData as SiteType)[activeLevel][activeNodeId]; + const activeNodeName = activeNodeData.node_name; + + const activeNodeNameToPath = useMemo(() => { + if (activeNodeName.includes("S")) { + return [SSkn, SSKnGold]; + } else if ( + activeNodeName.startsWith("P") || + activeNodeName.startsWith("G") || + activeNodeName.includes("?") + ) { + return [MULTI, MULTIGold]; + } else if (activeNodeName.includes("Dc")) { + return [Dc, DcGold]; + } else { + const activeNodeNameAssocs = { + Tda: [Tda, TdaGold], + Cou: [Cou, CouGold], + Dia: [Dia, DiaGold], + Lda: [Lda, LdaGold], + Ere: [MULTI, MULTIGold], + Ekm: [MULTI, MULTIGold], + Eda: [MULTI, MULTIGold], + TaK: [MULTI, MULTIGold], + Env: [MULTI, MULTIGold], + }; + + return activeNodeNameAssocs[ + activeNodeName.substr(0, 3) as keyof typeof activeNodeNameAssocs + ]; + } + }, [activeNodeName]); + + const r = useRef(); + + const regularTex = useLoader(THREE.TextureLoader, activeNodeNameToPath[0]); + const goldTex = useLoader(THREE.TextureLoader, activeNodeNameToPath[1]); + + useEffect(() => { + if (r.current && !props.visible) { + r.current.rotation.y = -1.2; + r.current.rotation.z = 0; + } + }, [props.visible]); + + useFrame(() => { + if (r.current && props.visible) { + r.current.rotation.y -= 0.01; + r.current.rotation.z += 0.01; + } + }); + + return ( + + + + + ); +}; + +export default GoldNode; diff --git a/src/components/Preloader.tsx b/src/components/Preloader.tsx index 7fcc2e4..678a898 100644 --- a/src/components/Preloader.tsx +++ b/src/components/Preloader.tsx @@ -12,6 +12,7 @@ import boringHudSpriteSheet from "../static/sprite/long_hud_boring.png"; import boringHudMirroredSpriteSheet from "../static/sprite/long_hud_boring_mirrored.png"; import throwNodeSpriteSheet from "../static/sprite/throw_node.png"; import ripMiddleRingSpriteSheet from "../static/sprite/rip_middle_ring.png"; +import ripNodeSpriteSheet from "../static/sprite/rip_node.png"; import * as THREE from "three"; import { useLoader, useThree } from "react-three-fiber"; @@ -46,6 +47,7 @@ const Preloader = () => { THREE.TextureLoader, ripMiddleRingSpriteSheet ); + const ripNode = useLoader(THREE.TextureLoader, ripNodeSpriteSheet); const { gl } = useThree(); useLayoutEffect(() => { @@ -63,6 +65,7 @@ const Preloader = () => { gl.initTexture(boringHudMirrored); gl.initTexture(throwNode); gl.initTexture(ripMiddleRing); + gl.initTexture(ripNode); }, [ moveDown, moveUp, @@ -79,6 +82,7 @@ const Preloader = () => { intro, throwNode, ripMiddleRing, + ripNode, ]); return null; }; diff --git a/src/core/StateManagers/MainSceneManagers/NodeManager.tsx b/src/core/StateManagers/MainSceneManagers/NodeManager.tsx index 85dea84..d250241 100644 --- a/src/core/StateManagers/MainSceneManagers/NodeManager.tsx +++ b/src/core/StateManagers/MainSceneManagers/NodeManager.tsx @@ -101,19 +101,23 @@ const NodeManager = (props: StateManagerProps) => { setActiveNodeState(0, "posY"); setTimeout(() => { - setActiveNodeState(Math.PI, "rotZ"); - setActiveNodeState(Math.PI, "rotY"); - setActiveNodeState(Math.PI, "rotX"); - setActiveNodeState(1, "goldTextureBias"); + setActiveNodeState(true, "exploding"); }, 1200); setTimeout(() => { + setActiveNodeState(false, "visible"); setActiveNodeState(false, "interactedWith"); setActiveNodeState(0, "rotZ"); - setActiveNodeState(0, "rotY"); setActiveNodeState(0, "rotX"); - setActiveNodeState(0, "goldTextureBias"); - }, 2500); + }, 1400); + + setTimeout(() => { + setActiveNodeState(false, "exploding"); + }, 3150); + + setTimeout(() => { + setActiveNodeState(true, "visible"); + }, 3500); }, [setActiveNodeState] ); diff --git a/src/resources/node_explosion_line_positions.json b/src/resources/node_explosion_line_positions.json index 8660bab..455596c 100644 --- a/src/resources/node_explosion_line_positions.json +++ b/src/resources/node_explosion_line_positions.json @@ -128,12 +128,6 @@ "length": 0.9, "color": "yellow" }, - { - "position": [-0.5, -0.1, 0], - "rotation": [0, 0, -0.65], - "length": 0.8, - "color": "yellow" - }, { "position": [0.4, -0.25, 0], "rotation": [0, 0, -1.15], diff --git a/src/scenes/MainScene.tsx b/src/scenes/MainScene.tsx index db5d7ec..bf4913e 100644 --- a/src/scenes/MainScene.tsx +++ b/src/scenes/MainScene.tsx @@ -39,7 +39,7 @@ const MainScene = () => { - {/**/} + ); diff --git a/src/store.ts b/src/store.ts index 6d34430..9dc5617 100644 --- a/src/store.ts +++ b/src/store.ts @@ -62,10 +62,10 @@ type NodeState = { posX: number; posZ: number; posY: number; - rotY: number; rotZ: number; interactedWith: boolean; - goldTextureBias: number; + exploding: boolean; + visible: boolean; }; nodeMatrixIndices: { matrixIdx: number; rowIdx: number; colIdx: number }; gameProgress: typeof game_progress; @@ -295,10 +295,10 @@ export const useNodeStore = create( posX: 0, posZ: 0, rotZ: 0, - rotY: 0, posY: 0, interactedWith: false, - goldTextureBias: 0, + exploding: false, + visible: true, }, nodeMatrixIndices: { matrixIdx: 7, rowIdx: 0, colIdx: 0 }, gameProgress: game_progress,