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,