cleaning up state

This commit is contained in:
ad044 2020-11-25 01:24:35 +04:00
parent 339962fec4
commit a2c3e77e1f
26 changed files with 711 additions and 956 deletions

View file

@ -5,17 +5,17 @@ import site_a from "../../resources/site_a.json";
import { useNodeStore, useLevelStore, useSiteStore } from "../../store"; import { useNodeStore, useLevelStore, useSiteStore } from "../../store";
import { a, useSpring } from "@react-spring/three"; import { a, useSpring } from "@react-spring/three";
const CurrentLevelNodes = () => { const ActiveLevelNodes = () => {
const activeNodeId = useNodeStore((state) => state.activeNodeId); const activeNodeState = useNodeStore((state) => state.activeNodeState);
const currentLevel = useLevelStore((state) => state.currentLevel); const activeLevel = useLevelStore((state) => state.activeLevel);
const currentLevelNodes = useMemo( const activeLevelNodes = useMemo(
() => site_a[currentLevel as keyof typeof site_a], () => site_a[activeLevel as keyof typeof site_a],
[currentLevel] [activeLevel]
); );
const siteRotY = useSiteStore((state) => state.siteRotY);
const sitePosY = useSiteStore((state) => state.sitePosY); const sitePosY = useSiteStore((state) => state.sitePosY);
const siteRotY = useSiteStore((state) => state.siteRotY);
const siteState = useSpring({ const siteState = useSpring({
siteRotY: siteRotY, siteRotY: siteRotY,
@ -25,22 +25,20 @@ const CurrentLevelNodes = () => {
return ( return (
<a.group rotation-y={siteState.siteRotY} position-y={siteState.sitePosY}> <a.group rotation-y={siteState.siteRotY} position-y={siteState.sitePosY}>
{Object.entries(currentLevelNodes).map((node: [string, any]) => { {Object.entries(activeLevelNodes).map((node: [string, any]) => {
return ( return (
<Node <Node
sprite={node[1].node_name} sprite={node[1].node_name}
position={ position={
node_positions[ node_positions[node[0].substr(2) as keyof typeof node_positions]
node[0].substr(2) as keyof typeof node_positions .position
].position
} }
rotation={ rotation={
node_positions[ node_positions[node[0].substr(2) as keyof typeof node_positions]
node[0].substr(2) as keyof typeof node_positions .rotation
].rotation
} }
key={node[1].node_name} key={node[1].node_name}
active={node[0] === activeNodeId} active={node[0] === activeNodeState.id}
level={node[0].substr(0, 2)} level={node[0].substr(0, 2)}
/> />
); );
@ -49,4 +47,4 @@ const CurrentLevelNodes = () => {
); );
}; };
export default CurrentLevelNodes; export default ActiveLevelNodes;

View file

@ -8,21 +8,20 @@ import longHudMirrored from "../../static/sprite/long_hud_mirrored.png";
import boringHud from "../../static/sprite/long_hud_boring.png"; import boringHud from "../../static/sprite/long_hud_boring.png";
import boringHudMirrored from "../../static/sprite/long_hud_boring_mirrored.png"; import boringHudMirrored from "../../static/sprite/long_hud_boring_mirrored.png";
import { a, useSpring } from "@react-spring/three"; import { a, useSpring } from "@react-spring/three";
import {useNodeStore, useHudStore} from "../../store"; import { useHudStore } from "../../store";
import node_huds from "../../resources/node_huds.json"; import node_huds from "../../resources/node_huds.json";
const HUD = memo(() => { const HUD = memo(() => {
const hudActive = useHudStore((state) => state.hudActive); const active = useHudStore((state) => state.active);
const currentHudId = useHudStore((state) => state.activeHudId); const id = useHudStore((state) => state.id);
const visible = useHudStore((state) => state.visible);
const hudVisible = useHudStore((state) => state.hudVisible); const currentHud = node_huds[id as keyof typeof node_huds];
const currentHud = node_huds[currentHudId as keyof typeof node_huds];
const hudElementState = useSpring({ const hudElementState = useSpring({
bigHUDPositionX: hudActive, bigHUDPositionX: active,
longHUDPositionX: hudActive, longHUDPositionX: active,
boringHUDPositionX: hudActive, boringHUDPositionX: active,
config: { duration: 500 }, config: { duration: 500 },
}); });
@ -84,7 +83,7 @@ const HUD = memo(() => {
); );
return ( return (
<group visible={hudVisible} position={[0, 0, 10]}> <group visible={visible} position={[0, 0, 10]}>
<a.sprite <a.sprite
position-x={longHUDPosX} position-x={longHUDPosX}
position-y={currentHud!.long.position[1]} position-y={currentHud!.long.position[1]}

View file

@ -8,35 +8,24 @@ import { useMiddleRingStore } from "../../store";
const MiddleRing = () => { const MiddleRing = () => {
const middleRingTex = useLoader(THREE.TextureLoader, middleRingTexture); const middleRingTex = useLoader(THREE.TextureLoader, middleRingTexture);
const middleRingWobbleStrength = useMiddleRingStore( const transformState = useMiddleRingStore((state) => state.transformState);
(state) => state.middleRingWobbleStrength const rotating = useMiddleRingStore((state) => state.isRotating);
); const animDuration = useMiddleRingStore((state) => state.animDuration);
const middleRingRotating = useMiddleRingStore(
(state) => state.middleRingRotating
);
const middleRingNoise = useMiddleRingStore((state) => state.middleRingNoise);
const middleRingPosY = useMiddleRingStore((state) => state.middleRingPosY);
const middleRingRotX = useMiddleRingStore((state) => state.middleRingRotX);
const middleRingRotZ = useMiddleRingStore((state) => state.middleRingRotZ);
const middleRingAnimDuration = useMiddleRingStore( const wobbleState = useSpring({
(state) => state.middleRingAnimDuration wobbleStrength: transformState.wobbleStrength,
); noiseStrength: transformState.noiseStrength,
const middleRingWobbleState = useSpring({
middleRingWobbleStrength: middleRingWobbleStrength,
middleRingNoise: middleRingNoise,
config: { duration: 200 }, config: { duration: 200 },
}); });
const middleRingPosState = useSpring({ const posState = useSpring({
middleRingPosY: middleRingPosY, posY: transformState.posY,
config: { duration: middleRingAnimDuration }, config: { duration: animDuration },
}); });
const middleRingRotState = useSpring({ const rotState = useSpring({
middleRingRotX: middleRingRotX, rotX: transformState.rotX,
middleRingRotZ: middleRingRotZ, rotZ: transformState.rotZ,
config: { duration: 1000 }, config: { duration: 1000 },
}); });
@ -199,24 +188,24 @@ const MiddleRing = () => {
useFrame(() => { useFrame(() => {
if (middleRingMaterialRef.current) { if (middleRingMaterialRef.current) {
middleRingMaterialRef.current.uniforms.uTime.value = clock.getElapsedTime(); middleRingMaterialRef.current.uniforms.uTime.value = clock.getElapsedTime();
middleRingMaterialRef.current.uniforms.wobbleStrength.value = middleRingWobbleState.middleRingWobbleStrength.get(); middleRingMaterialRef.current.uniforms.wobbleStrength.value = wobbleState.wobbleStrength.get();
middleRingMaterialRef.current.uniforms.noiseAmp.value = middleRingWobbleState.middleRingNoise.get(); middleRingMaterialRef.current.uniforms.noiseAmp.value = wobbleState.noiseStrength.get();
middleRingMaterialRef.current.needsUpdate = true; middleRingMaterialRef.current.needsUpdate = true;
} }
if (middleRingRotating) { if (rotating) {
middleRingRef.current!.rotation.y += 0.05; middleRingRef.current!.rotation.y += 0.05;
} }
}); });
return ( return (
<a.group rotation-z={middleRingRotState.middleRingRotZ}> <a.group rotation-z={rotState.rotZ}>
<a.mesh <a.mesh
position={[0, 0, 0.3]} position={[0, 0, 0.3]}
position-y={middleRingPosState.middleRingPosY} position-y={posState.posY}
ref={middleRingRef} ref={middleRingRef}
rotation={[0, 0.9, 0]} rotation={[0, 0.9, 0]}
rotation-x={middleRingRotState.middleRingRotX} rotation-x={rotState.rotX}
> >
<cylinderBufferGeometry <cylinderBufferGeometry
args={[0.75, 0.75, 0.027, 64, 64, true]} args={[0.75, 0.75, 0.027, 64, 64, true]}

View file

@ -115,46 +115,37 @@ const Node = (props: NodeContructorProps) => {
// these pieces of state get updated transiently rather than reactively // these pieces of state get updated transiently rather than reactively
// to avoid excess unnecessary renders (this is absolutely crucial for performance). // to avoid excess unnecessary renders (this is absolutely crucial for performance).
const [ const [
{ { activeNodePosX, activeNodePosY, activeNodePosZ, activeNodeRotZ },
activeNodePosX,
activeNodePosY,
activeNodePosZ,
activeNodeRotZ,
},
set, set,
] = useSpring(() => ({ ] = useSpring(() => ({
activeNodePosX: useNodeStore.getState().isActiveNodeInteractedWith activeNodePosX: useNodeStore.getState().activeNodeState.interactedWith
? useNodeStore.getState().activeNodePosX ? useNodeStore.getState().activeNodeState.posX
: props.position[0], : props.position[0],
activeNodePosY: useNodeStore.getState().isActiveNodeInteractedWith activeNodePosY: useNodeStore.getState().activeNodeState.interactedWith
? level_y_values[props.level as keyof typeof level_y_values] ? level_y_values[props.level as keyof typeof level_y_values]
: props.position[1], : props.position[1],
activeNodePosZ: useNodeStore.getState().isActiveNodeInteractedWith activeNodePosZ: useNodeStore.getState().activeNodeState.interactedWith
? useNodeStore.getState().activeNodePosZ ? useNodeStore.getState().activeNodeState.posZ
: props.position[2], : props.position[2],
activeNodeRotZ: useNodeStore.getState().isActiveNodeInteractedWith activeNodeRotZ: useNodeStore.getState().activeNodeState.interactedWith
? useNodeStore.getState().activeNodeRotZ ? useNodeStore.getState().activeNodeState.rotZ
: 0, : 0,
config: { duration: 800 }, config: { duration: 800 },
})); }));
useEffect(() => { useEffect(() => {
useNodeStore.subscribe(set, (state) => ({ useNodeStore.subscribe(set, (state) => ({
activeNodePosX: useNodeStore.getState() activeNodePosX: useNodeStore.getState().activeNodeState.interactedWith
.isActiveNodeInteractedWith ? state.activeNodeState.posX
? state.activeNodePosX
: props.position[0], : props.position[0],
activeNodePosY: useNodeStore.getState() activeNodePosY: useNodeStore.getState().activeNodeState.interactedWith
.isActiveNodeInteractedWith
? level_y_values[props.level as keyof typeof level_y_values] ? level_y_values[props.level as keyof typeof level_y_values]
: props.position[1], : props.position[1],
activeNodePosZ: useNodeStore.getState() activeNodePosZ: useNodeStore.getState().activeNodeState.interactedWith
.isActiveNodeInteractedWith ? state.activeNodeState.posZ
? state.activeNodePosZ
: props.position[2], : props.position[2],
activeNodeRotZ: useNodeStore.getState() activeNodeRotZ: useNodeStore.getState().activeNodeState.interactedWith
.isActiveNodeInteractedWith ? state.activeNodeState.rotZ
? state.activeNodeRotZ
: 0, : 0,
})); }));
}, [ }, [

View file

@ -37,15 +37,23 @@ export type SiteType = {
}; };
const Site = memo(() => { const Site = memo(() => {
const activeLevels = useLevelStore((state) => state.activeLevels); const activeLevel = useLevelStore((state) => state.activeLevel);
const visibleNodes = useMemo(() => { const visibleNodes = useMemo(() => {
const obj = {}; const obj = {};
activeLevels.forEach((level) => { const activeLevelNr = parseInt(activeLevel);
const visibleLevels = [
(activeLevelNr - 2).toString().padStart(2, "0"),
(activeLevelNr - 1).toString().padStart(2, "0"),
(activeLevelNr + 1).toString().padStart(2, "0"),
(activeLevelNr + 2).toString().padStart(2, "0"),
];
visibleLevels.forEach((level) => {
Object.assign(obj, site_a[level as keyof typeof site_a]); Object.assign(obj, site_a[level as keyof typeof site_a]);
}); });
return obj; return obj;
}, [activeLevels]); }, [activeLevel]);
const siteRotY = useSiteStore((state) => state.siteRotY); const siteRotY = useSiteStore((state) => state.siteRotY);
const sitePosY = useSiteStore((state) => state.sitePosY); const sitePosY = useSiteStore((state) => state.sitePosY);
@ -70,14 +78,12 @@ const Site = memo(() => {
<Node <Node
sprite={node[1].node_name} sprite={node[1].node_name}
position={ position={
node_positions[ node_positions[node[0].substr(2) as keyof typeof node_positions]
node[0].substr(2) as keyof typeof node_positions .position
].position
} }
rotation={ rotation={
node_positions[ node_positions[node[0].substr(2) as keyof typeof node_positions]
node[0].substr(2) as keyof typeof node_positions .rotation
].rotation
} }
key={node[1].node_name} key={node[1].node_name}
level={node[0].substr(0, 2)} level={node[0].substr(0, 2)}

View file

@ -3,7 +3,6 @@ import {
useGrayPlanesStore, useGrayPlanesStore,
useHudStore, useHudStore,
useLainStore, useLainStore,
useMainGroupStore,
useStarfieldStore, useStarfieldStore,
useYellowOrbStore, useYellowOrbStore,
} from "../store"; } from "../store";
@ -14,7 +13,13 @@ import {
// inside <Suspense> tags makes it behave in a more stable manner // inside <Suspense> tags makes it behave in a more stable manner
// by waiting for the components to load and synchronously calling the functions. // by waiting for the components to load and synchronously calling the functions.
const MainSceneIntro = memo(() => { const MainSceneIntro = memo(() => {
const toggleHud = useHudStore((state) => state.toggleHud); // todo component
// -2.5 - intro val
//-9.5 - intro val
//1.5 - intro val
const toggleHud = useHudStore((state) => state.toggleActive);
//const setHudVisible = useSetRecoilState(hudVisibilityAtom); //const setHudVisible = useSetRecoilState(hudVisibilityAtom);
const setOrbVisible = useYellowOrbStore((state) => state.setYellowOrbVisible); const setOrbVisible = useYellowOrbStore((state) => state.setYellowOrbVisible);
@ -31,21 +36,11 @@ const MainSceneIntro = memo(() => {
(state) => state.setMainStarfieldBoostVal (state) => state.setMainStarfieldBoostVal
); );
const setMainGroupPosY = useMainGroupStore((state) => state.setMainGroupPosY);
const setMainGroupPosZ = useMainGroupStore((state) => state.setMainGroupPosZ);
const setMainGroupRotX = useMainGroupStore((state) => state.setMainGroupRotX);
const setGrayPlanesVisible = useGrayPlanesStore( const setGrayPlanesVisible = useGrayPlanesStore(
(state) => state.setGrayPlanesVisible (state) => state.setGrayPlanesVisible
); );
useEffect(() => { useEffect(() => {
setMainGroupPosY(0);
setMainGroupPosZ(0);
setTimeout(() => {
setMainGroupRotX(0);
}, 2400);
setTimeout(() => { setTimeout(() => {
setGrayPlanesVisible(true); setGrayPlanesVisible(true);
}, 2500); }, 2500);
@ -77,9 +72,6 @@ const MainSceneIntro = memo(() => {
setMainStarfieldVisible, setMainStarfieldVisible,
setOrbVisible, setOrbVisible,
setIntroStarfieldVisible, setIntroStarfieldVisible,
setMainGroupRotX,
setMainGroupPosZ,
setMainGroupPosY,
setLainMoveState, setLainMoveState,
toggleHud, toggleHud,
]); ]);

View file

@ -1,16 +1,17 @@
import React, { useEffect, useState } from "react"; import React, { useEffect, useMemo, useState } from "react";
import { useLoader } from "react-three-fiber"; import { useLoader } from "react-three-fiber";
import { useImageStore, useMediaStore } from "../../store"; import { useLevelStore, useMediaStore, useNodeStore } from "../../store";
import * as THREE from "three";
import sex from "../../static/sprite/gray_ring_lof.png";
import { a, useSpring } from "@react-spring/three"; import { a, useSpring } from "@react-spring/three";
import image_table from "../../resources/image_table.json";
import { LevelType } from "../MainScene/Site";
import site_a from "../../resources/site_a.json";
import * as THREE from "three";
const Images = () => { const Images = () => {
const activeNodeId = useNodeStore((state) => state.activeNodeState.id);
const [imageScaleY, setImageScaleY] = useState(3.75); const [imageScaleY, setImageScaleY] = useState(3.75);
const images = useImageStore((state) => state.images); const [sceneImages, setSceneImages] = useState([] as any);
const [activeImage, setActiveImage] = useState<any>(sex); const [activeImage, setActiveImage] = useState<THREE.Texture>();
const activeImageTex = useLoader(THREE.TextureLoader, activeImage);
const mediaPercentageElapsed = useMediaStore( const mediaPercentageElapsed = useMediaStore(
(state) => state.mediaPercentageElapsed (state) => state.mediaPercentageElapsed
@ -21,28 +22,49 @@ const Images = () => {
config: { duration: 300 }, config: { duration: 300 },
}); });
useEffect(() => { const activeLevel = useLevelStore((state) => state.activeLevel);
if (images[1]) { const activeLevelData: LevelType = useMemo(
setActiveImage(images[1].default); () => site_a[activeLevel as keyof typeof site_a],
} [activeLevel]
}, [images]); );
useEffect(() => { useEffect(() => {
if (mediaPercentageElapsed === 35 && images[2]) { const nodeName = activeLevelData[activeNodeId].node_name;
const images = image_table[nodeName as keyof typeof image_table];
const imgArr: { default: string }[] = [];
Object.values(images).forEach((img) => {
import("../../static/media_images/site_a/" + img + ".png").then(
(imageSrc: { default: string }) => {
// images are unordered by default so we insert them into the arr
// according to their last char
imgArr.splice(parseInt(img.substr(img.length - 1)), 0, imageSrc);
if (imgArr.length === 3) {
setSceneImages(imgArr);
new THREE.TextureLoader().load(imgArr[0].default, setActiveImage);
}
}
);
});
}, [activeLevelData, activeNodeId]);
useEffect(() => {
if (mediaPercentageElapsed === 35 && sceneImages[1]) {
setImageScaleY(0); setImageScaleY(0);
setTimeout(() => { setTimeout(() => {
setActiveImage(images[2]!.default); new THREE.TextureLoader().load(sceneImages[1].default, setActiveImage);
setImageScaleY(3.75); setImageScaleY(3.75);
}, 300); }, 300);
} }
if (mediaPercentageElapsed === 70 && images[3]) { if (mediaPercentageElapsed === 70 && sceneImages[2]) {
setImageScaleY(0); setImageScaleY(0);
setTimeout(() => { setTimeout(() => {
setActiveImage(images[3]!.default); new THREE.TextureLoader().load(sceneImages[2].default, setActiveImage);
setImageScaleY(3.75); setImageScaleY(3.75);
}, 300); }, 300);
} }
}, [images, mediaPercentageElapsed]); }, [mediaPercentageElapsed, sceneImages]);
return ( return (
<a.sprite <a.sprite
@ -50,7 +72,11 @@ const Images = () => {
scale={[5, 3.75, 0]} scale={[5, 3.75, 0]}
scale-y={imageScaleState.imageScaleY} scale-y={imageScaleState.imageScaleY}
> >
<spriteMaterial attach="material" map={activeImageTex} /> {sceneImages.length === 3 ? (
<spriteMaterial attach="material" map={activeImage} />
) : (
<></>
)}
</a.sprite> </a.sprite>
); );
}; };

View file

@ -35,6 +35,7 @@ const MediaPlayer = () => {
<video <video
width="800" width="800"
height="600" height="600"
controls
id="media" id="media"
ref={videoRef} ref={videoRef}
style={{ display: currentScene === "media" ? "block" : "none" }} style={{ display: currentScene === "media" ? "block" : "none" }}

View file

@ -4,14 +4,14 @@ import * as THREE from "three";
import { useLoader } from "react-three-fiber"; import { useLoader } from "react-three-fiber";
import orange_font_json from "../../resources/font_data/big_font.json"; import orange_font_json from "../../resources/font_data/big_font.json";
import { a, useSpring } from "@react-spring/three"; import { a, useSpring } from "@react-spring/three";
import React, {useEffect, useMemo} from "react"; import React, { useMemo } from "react";
import { LetterProps } from "./TextRenderer";
interface BigLetterProps extends LetterProps { const BigLetter = (props: {
color: string;
letter: string;
letterIdx: number;
yellowTextOffsetXCoeff: number; yellowTextOffsetXCoeff: number;
} }) => {
const BigLetter = (props: BigLetterProps) => {
const colorToTexture = (color: string) => { const colorToTexture = (color: string) => {
const colorTexture = { orange: orangeFont, yellow: yellowFont }; const colorTexture = { orange: orangeFont, yellow: yellowFont };
return colorTexture[color as keyof typeof colorTexture]; return colorTexture[color as keyof typeof colorTexture];

View file

@ -0,0 +1,57 @@
import { a, useSpring } from "@react-spring/three";
import React, { useEffect, useRef } from "react";
import { GreenTextState, useGreenTextStore } from "../../store";
import MediumLetter from "./MediumLetter";
const GreenTextRenderer = () => {
const greenTextActive = useGreenTextStore((state) => state.active);
const transformRef = useRef(useGreenTextStore.getState().transformState);
const textArrRef = useRef(useGreenTextStore.getState().text.split(""));
const { greenTextPosXToggle } = useSpring({
greenTextPosXToggle: greenTextActive,
config: { duration: 500 },
});
const greenTextPosX = greenTextPosXToggle.to(
[0, 1],
[transformRef.current.posX.initial, transformRef.current.posX.final]
);
// subscribing to state and updating transiently
useEffect(
() =>
useGreenTextStore.subscribe(
(state) => {
transformRef.current = (state as GreenTextState).transformState;
textArrRef.current = (state as GreenTextState).text.split("");
},
(state) => state
),
[]
);
return (
<group position={[0, 0, 10]}>
<a.group
position-x={greenTextPosX}
position-y={transformRef.current.posY}
position-z={-8.7}
scale={[0.02, 0.035, 0.02]}
>
{textArrRef.current.map((letter, idx) => (
<MediumLetter
color={"yellow"}
letter={letter}
letterIdx={idx}
key={idx}
/>
))}
</a.group>
</group>
);
};
export default GreenTextRenderer;

View file

@ -4,9 +4,12 @@ import greenFont from "../../static/sprite/white_and_green_texture.png";
import medium_font_json from "../../resources/font_data/medium_font.json"; import medium_font_json from "../../resources/font_data/medium_font.json";
import { a } from "@react-spring/three"; import { a } from "@react-spring/three";
import React, { useMemo } from "react"; import React, { useMemo } from "react";
import { LetterProps } from "./TextRenderer";
const MediumLetter = (props: LetterProps) => { const MediumLetter = (props: {
color: string;
letter: string;
letterIdx: number;
}) => {
const colorTexture = useLoader(THREE.TextureLoader, greenFont); const colorTexture = useLoader(THREE.TextureLoader, greenFont);
// i have yet to figure out a genrealizable way of // i have yet to figure out a genrealizable way of
// calculating the y offset, this shit will do for now // calculating the y offset, this shit will do for now

View file

@ -1,162 +0,0 @@
import { a, useSpring, useTrail } from "@react-spring/three";
import React, { useEffect, useRef } from "react";
import {
TextRendererState,
useSiteStore,
useTextRendererStore,
} from "../../store";
import BigLetter from "./BigLetter";
import MediumLetter from "./MediumLetter";
export type LetterProps = {
color: string;
letter: string;
letterIdx: number;
};
const TextRenderer = () => {
const isSiteChangingY = useSiteStore((state) => state.isSiteChangingY);
// ======================================= YELLOW TEXT ======================================
// yellow text posx and posy need to be updated reactively aswell when changing site rotation/y value
const yellowTextPosX = useTextRendererStore((state) => state.yellowTextPosX);
const yellowTextPosY = useTextRendererStore((state) => state.yellowTextPosY);
const yellowTextOffsetXCoeff = useTextRendererStore(
(state) => state.yellowTextOffsetXCoeff
);
const yellowTextArrRef = useRef(
useTextRendererStore.getState().yellowText.split("")
);
const yellowTextPosXRef = useRef(
useTextRendererStore.getState().yellowTextPosX
);
const yellowTextPosYRef = useRef(
useTextRendererStore.getState().yellowTextPosY
);
// this is used to animate the letters moving one after another
const yellowLetterTrail = useTrail(yellowTextArrRef.current.length, {
yellowLetterPosX: yellowTextPosXRef.current,
yellowLetterPosY: yellowTextPosYRef.current,
config: { duration: 280 },
});
// this is used when the whole GROUP itself needs to be animated
const yellowLetterSpring = useSpring({
yellowLetterPosX: yellowTextPosX,
yellowLetterPosY: yellowTextPosY,
config: { duration: 1200 },
});
// ==================================== GREEN TEXT ============================================
const greenTextActive = useTextRendererStore(
(state) => state.greenTextActive
);
const greenTextPosYRef = useRef(
useTextRendererStore.getState().greenTextPosY
);
const greenTextPosXRef = useRef(
useTextRendererStore.getState().greenTextPosX
);
const greenTextArrRef = useRef(
useTextRendererStore.getState().greenText.split("")
);
const { greenTextPosXToggle } = useSpring({
greenTextPosXToggle: greenTextActive,
config: { duration: 500 },
});
const greenTextPosX = greenTextPosXToggle.to(
[0, 1],
[greenTextPosXRef.current.initial, greenTextPosXRef.current.final]
);
// subscribing to state and updating transiently
useEffect(
() =>
useTextRendererStore.subscribe(
(state) => {
yellowTextPosXRef.current = (state as TextRendererState).yellowTextPosX;
yellowTextPosYRef.current = (state as TextRendererState).yellowTextPosY;
yellowTextArrRef.current = (state as TextRendererState).yellowText.split(
""
);
greenTextPosYRef.current = (state as TextRendererState).greenTextPosY;
greenTextPosXRef.current = (state as TextRendererState).greenTextPosX;
greenTextArrRef.current = (state as TextRendererState).greenText.split(
""
);
},
(state) => state
),
[]
);
return (
<group position={[0, 0, 10]}>
{isSiteChangingY
? yellowTextArrRef.current.map((letter, idx) => (
<a.group
key={idx}
position-x={yellowLetterSpring.yellowLetterPosX}
position-y={yellowLetterSpring.yellowLetterPosY}
position-z={-8.7}
scale={[0.04, 0.06, 0.04]}
>
<BigLetter
color={"yellow"}
yellowTextOffsetXCoeff={0}
letter={yellowTextArrRef.current[idx]}
letterIdx={idx}
key={idx}
/>
</a.group>
))
: yellowLetterTrail.map(
({ yellowLetterPosX, yellowLetterPosY }, idx) => (
<a.group
key={idx}
position-x={yellowLetterPosX}
position-y={yellowLetterPosY}
position-z={-8.7}
scale={[0.04, 0.06, 0.04]}
>
<BigLetter
color={"yellow"}
yellowTextOffsetXCoeff={yellowTextOffsetXCoeff}
letter={yellowTextArrRef.current[idx]}
letterIdx={idx}
key={idx}
/>
</a.group>
)
)}
<a.group
position-x={greenTextPosX}
position-y={greenTextPosYRef.current}
position-z={-8.7}
scale={[0.02, 0.035, 0.02]}
>
{greenTextArrRef.current.map((letter, idx) => (
<MediumLetter
color={"yellow"}
letter={letter}
letterIdx={idx}
key={idx}
/>
))}
</a.group>
</group>
);
};
export default TextRenderer;

View file

@ -0,0 +1,81 @@
import React, { useEffect, useRef } from "react";
import { useYellowTextStore, YellowTextState } from "../../store";
import { a, useSpring, useTrail } from "@react-spring/three";
import BigLetter from "./BigLetter";
const YellowTextRenderer = () => {
const disableTrail = useYellowTextStore((state) => state.disableTrail);
const transformState = useYellowTextStore((state) => state.transformState);
const textArrRef = useRef(useYellowTextStore.getState().text.split(""));
const transformRef = useRef(useYellowTextStore.getState().transformState);
// this is used to animate the letters moving one after another
const trail = useTrail(textArrRef.current.length, {
posX: transformRef.current.posX,
posY: transformRef.current.posY,
config: { duration: 280 },
});
// this is used when the whole GROUP itself needs to be animated
const spring = useSpring({
posX: transformState.posX,
posY: transformState.posY,
config: { duration: 1200 },
});
useEffect(
() =>
useYellowTextStore.subscribe(
(state) => {
transformRef.current = (state as YellowTextState).transformState;
textArrRef.current = (state as YellowTextState).text.split("");
},
(state) => state
),
[]
);
return (
<group position={[0, 0, 10]}>
{disableTrail
? textArrRef.current.map((letter, idx) => (
<a.group
key={idx}
position-x={spring.posX}
position-y={spring.posY}
position-z={-8.7}
scale={[0.04, 0.06, 0.04]}
>
<BigLetter
color={"yellow"}
yellowTextOffsetXCoeff={0}
letter={textArrRef.current[idx]}
letterIdx={idx}
key={idx}
/>
</a.group>
))
: trail.map(({ posX, posY }, idx) => (
<a.group
key={idx}
position-x={posX}
position-y={posY}
position-z={-8.7}
scale={[0.04, 0.06, 0.04]}
>
<BigLetter
color={"yellow"}
yellowTextOffsetXCoeff={transformRef.current.xOffset}
letter={textArrRef.current[idx]}
letterIdx={idx}
key={idx}
/>
</a.group>
))}
</group>
);
};
export default YellowTextRenderer;

View file

@ -18,7 +18,6 @@ import MediaComponentManager from "./MediaComponentManager";
import MediaWordManager from "./MediaWordManager"; import MediaWordManager from "./MediaWordManager";
import SceneManager from "./SceneManager"; import SceneManager from "./SceneManager";
import YellowTextManager from "./YellowTextManager"; import YellowTextManager from "./YellowTextManager";
import MediaImageManager from "./MediaImageManager";
import computeAction from "../computeAction"; import computeAction from "../computeAction";
import LevelManager from "./LevelManager"; import LevelManager from "./LevelManager";
import BootManager from "./BootManager"; import BootManager from "./BootManager";
@ -53,9 +52,14 @@ export type GameContext = {
keyPress?: string; keyPress?: string;
scene: string; scene: string;
bootSubscene: string; bootSubscene: string;
nodeMatrixIndices: { rowIdx: number; colIdx: number }; nodeMatrixIndices: {
currentLevel: string; matrixIdx: number;
siteRotIdx: string; rowIdx: number;
colIdx: number;
};
activeLevel: string;
siteRotY: number;
sitePosY: number;
activeMediaComponent: string; activeMediaComponent: string;
activeBootElement: string; activeBootElement: string;
activeSSknComponent: string; activeSSknComponent: string;
@ -66,8 +70,9 @@ const EventManager = () => {
// main scene // main scene
const nodeMatrixIndices = useNodeStore((state) => state.nodeMatrixIndices); const nodeMatrixIndices = useNodeStore((state) => state.nodeMatrixIndices);
const siteRotIdx = useSiteStore((state) => state.siteRotIdx); const sitePosY = useSiteStore((state) => state.sitePosY);
const currentLevel = useLevelStore((state) => state.currentLevel); const siteRotY = useSiteStore((state) => state.siteRotY);
const activeLevel = useLevelStore((state) => state.activeLevel);
// media scene // media scene
const mediaComponentMatrixIndices = useMediaStore( const mediaComponentMatrixIndices = useMediaStore(
@ -116,9 +121,10 @@ const EventManager = () => {
() => ({ () => ({
scene: currentScene, scene: currentScene,
bootSubscene: currentBootSubscene, bootSubscene: currentBootSubscene,
siteRotIdx: siteRotIdx, siteRotY: siteRotY,
sitePosY: sitePosY,
nodeMatrixIndices: nodeMatrixIndices, nodeMatrixIndices: nodeMatrixIndices,
currentLevel: currentLevel, activeLevel: activeLevel,
activeMediaComponent: activeMediaComponent, activeMediaComponent: activeMediaComponent,
activeBootElement: activeBootElement, activeBootElement: activeBootElement,
activeSSknComponent: activeSSknComponent, activeSSknComponent: activeSSknComponent,
@ -126,9 +132,10 @@ const EventManager = () => {
[ [
currentScene, currentScene,
currentBootSubscene, currentBootSubscene,
siteRotIdx, siteRotY,
sitePosY,
nodeMatrixIndices, nodeMatrixIndices,
currentLevel, activeLevel,
activeMediaComponent, activeMediaComponent,
activeBootElement, activeBootElement,
activeSSknComponent, activeSSknComponent,
@ -170,7 +177,6 @@ const EventManager = () => {
<MediaWordManager eventState={eventState!} /> <MediaWordManager eventState={eventState!} />
<SceneManager eventState={eventState!} /> <SceneManager eventState={eventState!} />
<YellowTextManager eventState={eventState!} /> <YellowTextManager eventState={eventState!} />
<MediaImageManager eventState={eventState!} />
<LevelManager eventState={eventState!} /> <LevelManager eventState={eventState!} />
<BootManager eventState={eventState!} /> <BootManager eventState={eventState!} />
<SSknComponentManager eventState={eventState!} /> <SSknComponentManager eventState={eventState!} />

View file

@ -1,20 +1,15 @@
import { useCallback, useEffect } from "react"; import { useCallback, useEffect } from "react";
import { useTextRendererStore } from "../../store";
import { StateManagerProps } from "./EventManager"; import { StateManagerProps } from "./EventManager";
import node_huds from "../../resources/node_huds.json"; import node_huds from "../../resources/node_huds.json";
import site_a from "../../resources/site_a.json"; import site_a from "../../resources/site_a.json";
import { SiteType } from "../../components/MainScene/Site"; import { SiteType } from "../../components/MainScene/Site";
import { useGreenTextStore } from "../../store";
const GreenTextManager = (props: StateManagerProps) => { const GreenTextManager = (props: StateManagerProps) => {
const setGreenText = useTextRendererStore((state) => state.setGreenText); const setGreenText = useGreenTextStore((state) => state.setText);
const setGreenTextPosY = useTextRendererStore( const toggleActive = useGreenTextStore((state) => state.toggleActive);
(state) => state.setGreenTextPosY const setTransformState = useGreenTextStore(
); (state) => state.setTransformState
const setGreenTextPosX = useTextRendererStore(
(state) => state.setGreenTextPosX
);
const toggleGreenText = useTextRendererStore(
(state) => state.toggleGreenText
); );
const toggleAndSetGreenText = useCallback( const toggleAndSetGreenText = useCallback(
@ -30,30 +25,39 @@ const GreenTextManager = (props: StateManagerProps) => {
const targetGreenTextPosData = const targetGreenTextPosData =
node_huds[newActiveHudId as keyof typeof node_huds].medium_text; node_huds[newActiveHudId as keyof typeof node_huds].medium_text;
toggleGreenText(); toggleActive();
setTimeout(() => { setTimeout(() => {
setGreenTextPosX({ setTransformState(
{
initial: targetGreenTextPosData.initial_position[0], initial: targetGreenTextPosData.initial_position[0],
final: targetGreenTextPosData.position[0], final: targetGreenTextPosData.position[0],
}); },
setGreenTextPosY(targetGreenTextPosData.position[1]); "posX"
);
setTransformState(targetGreenTextPosData.position[1], "posY");
setGreenText(targetGreenText); setGreenText(targetGreenText);
toggleGreenText(); toggleActive();
}, delay); }, delay);
}, },
[setGreenText, setGreenTextPosX, setGreenTextPosY, toggleGreenText] [setGreenText, setTransformState, toggleActive]
); );
const initializeGreenTextForMediaScene = useCallback( const initializeGreenTextForMediaScene = useCallback(
(activeNodeId: string, level: string) => { (activeNodeId: string, level: string) => {
setTimeout(() => { setTimeout(() => {
setGreenText((site_a as SiteType)[level][activeNodeId].node_name); setGreenText((site_a as SiteType)[level][activeNodeId].node_name);
setGreenTextPosX({ initial: 0.0, final: 0.009 }); setTransformState(
setGreenTextPosY(0.675); {
initial: 0,
final: 0.009,
},
"posX"
);
setTransformState(0.675, "posY");
}, 3950); }, 3950);
}, },
[setGreenText, setGreenTextPosX, setGreenTextPosY] [setGreenText, setTransformState]
); );
const dispatchObject = useCallback( const dispatchObject = useCallback(

View file

@ -3,35 +3,20 @@ import { StateManagerProps } from "./EventManager";
import { useLevelStore } from "../../store"; import { useLevelStore } from "../../store";
const LevelManager = (props: StateManagerProps) => { const LevelManager = (props: StateManagerProps) => {
const setCurrentLevel = useLevelStore((state) => state.setCurrentLevel); const setActiveLevel = useLevelStore((state) => state.setActiveLevel);
const setActiveLevels = useLevelStore((state) => state.setActiveLevels);
const updateLevel = useCallback(
(newLevel: string) => {
setTimeout(() => {
setCurrentLevel(newLevel);
setActiveLevels([
(parseInt(newLevel) - 2).toString().padStart(2, "0"),
(parseInt(newLevel) - 1).toString().padStart(2, "0"),
(parseInt(newLevel) + 1).toString().padStart(2, "0"),
(parseInt(newLevel) + 2).toString().padStart(2, "0"),
]);
}, 1500);
},
[setActiveLevels, setCurrentLevel]
);
const dispatchObject = useCallback( const dispatchObject = useCallback(
(event: string, newLevel: string) => { (event: string, newLevel: string) => {
switch (event) { switch (event) {
case "move_up": case "move_up":
case "move_down": case "move_down":
return { return {
action: updateLevel, action: setActiveLevel,
value: newLevel, value: newLevel,
}; };
} }
}, },
[updateLevel] [setActiveLevel]
); );
useEffect(() => { useEffect(() => {

View file

@ -1,83 +0,0 @@
import { useCallback, useEffect, useMemo } from "react";
import { StateManagerProps } from "./EventManager";
import site_a from "../../resources/site_a.json";
import image_table from "../../resources/image_table.json";
import { ImageSrc, useImageStore, useLevelStore } from "../../store";
import { LevelType } from "../../components/MainScene/Site";
const MediaImageManager = (props: StateManagerProps) => {
const setImages = useImageStore((state) => state.setImages);
const currentLevel = useLevelStore((state) => state.currentLevel);
const currentLevelData: LevelType = useMemo(
() => site_a[currentLevel as keyof typeof site_a],
[currentLevel]
);
const updateSceneImages = useCallback(
(newActiveNodeId: string) => {
const nodeName = currentLevelData[newActiveNodeId].node_name;
const images = image_table[nodeName as keyof typeof image_table];
Object.values(images).forEach((img) => {
switch (img.substr(img.length - 1)) {
case "0":
import("../../static/media_images/site_a/" + img + ".png").then(
(imageSrc: ImageSrc) => {
setImages(imageSrc, 1);
}
);
break;
case "1":
import("../../static/media_images/site_a/" + img + ".png").then(
(imageSrc: ImageSrc) => {
setImages(imageSrc, 2);
}
);
break;
case "2":
import("../../static/media_images/site_a/" + img + ".png").then(
(imageSrc: ImageSrc) => {
setImages(imageSrc, 3);
}
);
break;
default:
break;
}
});
},
[currentLevelData, setImages]
);
const dispatchObject = useCallback(
(event: string, newActiveNodeId: string) => {
const dispatcherObjects = {
throw_node_media: {
action: updateSceneImages,
value: newActiveNodeId,
},
};
return dispatcherObjects[event as keyof typeof dispatcherObjects];
},
[updateSceneImages]
);
useEffect(() => {
if (props.eventState) {
const eventAction = props.eventState.event;
const newActiveNodeId = props.eventState.newActiveNodeId;
const dispatchedObject = dispatchObject(eventAction, newActiveNodeId);
if (dispatchedObject) {
dispatchedObject.action(dispatchedObject.value);
}
}
}, [props.eventState, dispatchObject]);
return null;
};
export default MediaImageManager;

View file

@ -2,217 +2,169 @@ import { useCallback, useEffect, useMemo } from "react";
import { useMiddleRingStore } from "../../store"; import { useMiddleRingStore } from "../../store";
const MiddleRingManager = (props: any) => { const MiddleRingManager = (props: any) => {
const setMiddleRingWobbleStrength = useMiddleRingStore( const setTransformState = useMiddleRingStore(
(state) => state.setMiddleRingWobbleStrength (state) => state.setTransformState
);
const setMiddleRingRotating = useMiddleRingStore(
(state) => state.setMiddleRingRotating
);
const setMiddleRingNoise = useMiddleRingStore(
(state) => state.setMiddleRingNoise
);
const addToMiddleRingPosY = useMiddleRingStore(
(state) => state.addToMiddleRingPosY
);
const setMiddleRingRotX = useMiddleRingStore(
(state) => state.setMiddleRingRotX
);
const setMiddleRingRotZ = useMiddleRingStore(
(state) => state.setMiddleRingRotZ
);
const setMiddleRingAnimDuration = useMiddleRingStore(
(state) => state.setMiddleRingAnimDuration
); );
const setAnimDuration = useMiddleRingStore((state) => state.setAnimDuration);
const setRotating = useMiddleRingStore((state) => state.setRotating);
const rotate = useCallback(
(direction: string) => {
const rotValues = direction === "right" ? [-0.07, 0.03] : [0.07, -0.03];
const rotateMiddleRingRight = useCallback(() => {
setTimeout(() => { setTimeout(() => {
setMiddleRingRotZ(-0.07); setTransformState(rotValues[0], "rotZ");
}, 2300); }, 2300);
setTimeout(() => { setTimeout(() => {
setMiddleRingRotZ(0.03); setTransformState(rotValues[1], "rotZ");
}, 3500); }, 3500);
setTimeout(() => { setTimeout(() => {
setMiddleRingRotZ(0); setTransformState(0, "rotZ");
}, 4500); }, 4500);
}, [setMiddleRingRotZ]); },
[setTransformState]
);
const rotateMiddleRingLeft = useCallback(() => { const moveDown = useCallback(() => {
setTimeout(() => {
setMiddleRingRotZ(0.07);
}, 2300);
setTimeout(() => {
setMiddleRingRotZ(-0.03);
}, 3500);
setTimeout(() => {
setMiddleRingRotZ(0);
}, 4500);
}, [setMiddleRingRotZ]);
const moveMiddleRingDown = useCallback(() => {
// set the anim duration value to match that of the site's // set the anim duration value to match that of the site's
setMiddleRingAnimDuration(1200); setAnimDuration(1200);
// make noise appear again // make noise appear again
setTimeout(() => { setTimeout(() => {
setMiddleRingNoise(0.06); setTransformState(0.06, "noiseStrength");
}, 800); }, 800);
// disable rotation of the ring // disable rotation of the ring
setTimeout(() => { setTimeout(() => {
setMiddleRingRotating(false); setRotating(false);
}, 700); }, 700);
setTimeout(() => { setTimeout(() => {
addToMiddleRingPosY(1.5); setTransformState(1.39, "posY");
}, 1300); }, 1300);
// set ring rotation on x axis to craete motion effect // set ring rotation on x axis to craete motion effect
setTimeout(() => { setTimeout(() => {
setMiddleRingRotX(0.3); setTransformState(0.3, "rotX");
}, 1500); }, 1500);
setTimeout(() => { setTimeout(() => {
setMiddleRingAnimDuration(600); setAnimDuration(600);
}, 2900); }, 2900);
setTimeout(() => { setTimeout(() => {
addToMiddleRingPosY(-1.7); setTransformState(-0.31, "posY");
}, 3000); }, 3000);
setTimeout(() => { setTimeout(() => {
addToMiddleRingPosY(0.2); setTransformState(-0.11, "posY");
}, 3150); }, 3150);
// rotate it again, set ring noise to 0 // rotate it again, set ring noise to 0
setTimeout(() => { setTimeout(() => {
setMiddleRingRotX(-0.1); setTransformState(-0.1, "rotX");
setMiddleRingNoise(0); setTransformState(0, "noiseStrength");
}, 3500); }, 3500);
// rotate it back AGAIN (holy fuk psx game) // rotate it back AGAIN (holy fuk psx game)
setTimeout(() => { setTimeout(() => {
setMiddleRingRotX(0.05); setTransformState(0.05, "rotX");
}, 4500); }, 4500);
// reset value, set noise to 0 // reset value, set noise to 0
setTimeout(() => { setTimeout(() => {
setMiddleRingRotX(0); setTransformState(0, "rotX");
setMiddleRingRotating(true); setRotating(true);
}, 4800); }, 4800);
// enable noise again in about 11-12 secs // enable noise again in about 11-12 secs
setTimeout(() => { setTimeout(() => {
setMiddleRingNoise(0.03); setTransformState(0.03, "noiseStrength");
}, 11600); }, 11600);
}, [ }, [setAnimDuration, setRotating, setTransformState]);
addToMiddleRingPosY,
setMiddleRingAnimDuration,
setMiddleRingNoise,
setMiddleRingRotX,
setMiddleRingRotating,
]);
const moveMiddleRingUp = useCallback(() => { const moveUp = useCallback(() => {
// change noise to 0, make the ring bend downwards // change noise to 0, make the ring bend downwards
setTimeout(() => { setTimeout(() => {
setMiddleRingNoise(0); setTransformState(0, "noiseStrength");
setMiddleRingWobbleStrength(0.2); setTransformState(0.2, "wobbleStrength");
}, 300); }, 300);
// disable rotation of the ring // disable rotation of the ring
setTimeout(() => { setTimeout(() => {
setMiddleRingRotating(false); setRotating(false);
}, 700); }, 700);
// make the ring bend upwards // make the ring bend upwards
setTimeout(() => { setTimeout(() => {
setMiddleRingWobbleStrength(-0.3); setTransformState(-0.3, "wobbleStrength");
// the middle ring stays in place, therefore we animate it // the middle ring stays in place, therefore we animate it
// in the same direction as the site, creating that illusion. // in the same direction as the site, creating that illusion.
// set the anim duration value to match that of the site's // set the anim duration value to match that of the site's
setMiddleRingAnimDuration(1200); setAnimDuration(1200);
// animate it after // animate it after
addToMiddleRingPosY(-1.5); setTransformState(-1.39, "posY");
}, 1300); }, 1300);
// reset the ring bend, set the rotation to slightly curve // reset the ring bend, set the rotation to slightly curve
// to replicate a motion effect (since its moving upwards) // to replicate a motion effect (since its moving upwards)
// and enable rotation again // and enable rotation again
setTimeout(() => { setTimeout(() => {
setMiddleRingWobbleStrength(0.0); setTransformState(0, "wobbleStrength");
setMiddleRingRotX(-0.2); setTransformState(-0.2, "rotX");
setMiddleRingRotating(true); setRotating(true);
}, 1500); }, 1500);
// reset anim duration back to default // reset anim duration back to default
setTimeout(() => { setTimeout(() => {
setMiddleRingAnimDuration(600); setAnimDuration(600);
}, 2300); }, 2300);
setTimeout(() => { setTimeout(() => {
addToMiddleRingPosY(1.7); setTransformState(0.09, "posY");
}, 2400); }, 2900);
// reset the rotation value to 0 // reset the rotation value to 0
setTimeout(() => { setTimeout(() => {
setMiddleRingRotX(0); setTransformState(0, "rotX");
addToMiddleRingPosY(-0.2); setTransformState(-0.11, "posY");
}, 2650); }, 3150);
// enable noise again in about 8~ secs // enable noise again in about 8~ secs
setTimeout(() => { setTimeout(() => {
setMiddleRingNoise(0.03); setTransformState(0.03, "noiseStrength");
}, 7800); }, 7800);
}, [ }, [setAnimDuration, setRotating, setTransformState]);
addToMiddleRingPosY,
setMiddleRingAnimDuration,
setMiddleRingNoise,
setMiddleRingRotX,
setMiddleRingRotating,
setMiddleRingWobbleStrength,
]);
const dispatcherObjects = useMemo( const dispatchObject = useCallback(
() => ({ (event: string) => {
move_up: { action: moveMiddleRingUp }, switch (event) {
move_down: { action: moveMiddleRingDown }, case "move_up":
move_left: { action: rotateMiddleRingLeft }, return { action: moveUp };
move_right: { action: rotateMiddleRingRight }, case "move_down":
}), return { action: moveDown };
[ case "move_left":
moveMiddleRingDown, return { action: rotate, value: ["left"] };
moveMiddleRingUp, case "move_right":
rotateMiddleRingLeft, return { action: rotate, value: ["right"] };
rotateMiddleRingRight, }
] },
[moveDown, moveUp, rotate]
); );
useEffect(() => { useEffect(() => {
if (props.eventState) { if (props.eventState) {
const eventAction = props.eventState.event; const eventAction = props.eventState.event;
const dispatchedObject = const dispatchedObject = dispatchObject(eventAction);
dispatcherObjects[eventAction as keyof typeof dispatcherObjects];
if (dispatchedObject) { if (dispatchedObject) {
dispatchedObject.action(); dispatchedObject.action.apply(null, dispatchedObject.value as any);
} }
} }
}, [ }, [dispatchObject, props.eventState]);
dispatcherObjects,
props.eventState,
setMiddleRingAnimDuration,
setMiddleRingNoise,
setMiddleRingRotX,
setMiddleRingRotZ,
setMiddleRingRotating,
setMiddleRingWobbleStrength,
]);
return null; return null;
}; };

View file

@ -3,10 +3,8 @@ import { useHudStore } from "../../store";
import { StateManagerProps } from "./EventManager"; import { StateManagerProps } from "./EventManager";
const NodeHUDManager = (props: StateManagerProps) => { const NodeHUDManager = (props: StateManagerProps) => {
const setActiveNodeHudId = useHudStore( const setId = useHudStore((state) => state.setId);
(state) => state.setActiveNodeHudId const toggleActive = useHudStore((state) => state.toggleActive);
);
const toggleHud = useHudStore((state) => state.toggleHud);
const dispatchObject = useCallback( const dispatchObject = useCallback(
(event: string, targetNodeHudId: string) => { (event: string, targetNodeHudId: string) => {
@ -16,19 +14,19 @@ const NodeHUDManager = (props: StateManagerProps) => {
case "move_left": case "move_left":
case "move_right": case "move_right":
return { return {
action: setActiveNodeHudId, action: setId,
value: targetNodeHudId, value: targetNodeHudId,
actionDelay: 3903.704, actionDelay: 3903.704,
}; };
case "change_node": case "change_node":
return { return {
action: setActiveNodeHudId, action: setId,
value: targetNodeHudId, value: targetNodeHudId,
actionDelay: 500, actionDelay: 500,
}; };
} }
}, },
[setActiveNodeHudId] [setId]
); );
useEffect(() => { useEffect(() => {
@ -39,15 +37,15 @@ const NodeHUDManager = (props: StateManagerProps) => {
const dispatchedObject = dispatchObject(eventAction, newActiveHudId); const dispatchedObject = dispatchObject(eventAction, newActiveHudId);
if (dispatchedObject) { if (dispatchedObject) {
toggleHud(); toggleActive();
setTimeout(() => { setTimeout(() => {
dispatchedObject.action(dispatchedObject.value); dispatchedObject.action(dispatchedObject.value);
toggleHud(); toggleActive();
}, dispatchedObject.actionDelay); }, dispatchedObject.actionDelay);
} }
} }
}, [props.eventState, setActiveNodeHudId, toggleHud, dispatchObject]); }, [props.eventState, toggleActive, dispatchObject]);
return null; return null;
}; };

View file

@ -2,51 +2,37 @@ import { useCallback, useEffect } from "react";
import { useNodeStore } from "../../store"; import { useNodeStore } from "../../store";
import { StateManagerProps } from "./EventManager"; import { StateManagerProps } from "./EventManager";
type SetIsActiveNodeInteractedWith = (value: boolean) => void;
const NodeManager = (props: StateManagerProps) => { const NodeManager = (props: StateManagerProps) => {
const setActiveNode = useNodeStore((state) => state.setActiveNodeId); const setActiveNodeState = useNodeStore((state) => state.setActiveNodeState);
const setNodeMatrixIndices = useNodeStore( const setNodeMatrixIndices = useNodeStore(
(state) => state.setNodeMatrixIndices (state) => state.setNodeMatrixIndices
); );
const setIsActiveNodeInteractedWith: SetIsActiveNodeInteractedWith = useNodeStore( // const animateActiveNodeThrow = useCallback(() => {
(state) => state.setIsActiveNodeInteractedWith // setIsActiveNodeInteractedWith(true);
); //
const setActiveNodePosX = useNodeStore((state) => state.setActiveNodePosX); // setActiveNodePosZ(0.3);
const setActiveNodePosZ = useNodeStore((state) => state.setActiveNodePosZ); // setActiveNodePosX(0.9);
const setActiveNodeRotZ = useNodeStore((state) => state.setActiveNodeRotZ); //
// setTimeout(() => {
const animateActiveNodeThrow = useCallback(() => { // setActiveNodePosZ(0.2);
setIsActiveNodeInteractedWith(true); // setActiveNodePosX(0.5);
// }, 800);
setActiveNodePosZ(0.3); // setTimeout(() => {
setActiveNodePosX(0.9); // setActiveNodePosX(1.55);
// setActiveNodeRotZ(-0.005);
setTimeout(() => { // }, 2600);
setActiveNodePosZ(0.2); // setTimeout(() => {
setActiveNodePosX(0.5); // setActiveNodePosZ(2);
}, 800); // setActiveNodePosX(0);
setTimeout(() => { // setActiveNodeRotZ(-0.5);
setActiveNodePosX(1.55); // }, 2700);
setActiveNodeRotZ(-0.005); //
}, 2600); // setTimeout(() => {
setTimeout(() => { // setActiveNodeRotZ(0);
setActiveNodePosZ(2); // setIsActiveNodeInteractedWith(false);
setActiveNodePosX(0); // }, 3800);
setActiveNodeRotZ(-0.5); // }, []);
}, 2700);
setTimeout(() => {
setActiveNodeRotZ(0);
setIsActiveNodeInteractedWith(false);
}, 3800);
}, [
setActiveNodePosX,
setActiveNodePosZ,
setActiveNodeRotZ,
setIsActiveNodeInteractedWith,
]);
const updateActiveNode = useCallback( const updateActiveNode = useCallback(
( (
@ -54,17 +40,19 @@ const NodeManager = (props: StateManagerProps) => {
isMoving: boolean, isMoving: boolean,
newActiveNodeId: string, newActiveNodeId: string,
newNodeColIdx: number, newNodeColIdx: number,
newNodeRowIdx: number newNodeRowIdx: number,
newNodeMatIdx: number
) => { ) => {
setTimeout(() => { setTimeout(() => {
setActiveNode(newActiveNodeId); setActiveNodeState(newActiveNodeId, "id");
setNodeMatrixIndices({ setNodeMatrixIndices({
matrixIdx: newNodeMatIdx,
rowIdx: newNodeRowIdx, rowIdx: newNodeRowIdx,
colIdx: newNodeColIdx, colIdx: newNodeColIdx,
}); });
}, delay); }, delay);
}, },
[setActiveNode, setNodeMatrixIndices] [setActiveNodeState, setNodeMatrixIndices]
); );
const dispatchObject = useCallback( const dispatchObject = useCallback(
@ -72,7 +60,8 @@ const NodeManager = (props: StateManagerProps) => {
event: string, event: string,
newActiveNodeId: string, newActiveNodeId: string,
newNodeColIdx: number, newNodeColIdx: number,
newNodeRowIdx: number newNodeRowIdx: number,
newNodeMatIdx: number
) => { ) => {
switch (event) { switch (event) {
case "move_up": case "move_up":
@ -87,23 +76,31 @@ const NodeManager = (props: StateManagerProps) => {
newActiveNodeId, newActiveNodeId,
newNodeColIdx, newNodeColIdx,
newNodeRowIdx, newNodeRowIdx,
newNodeMatIdx,
], ],
}; };
case "change_node": case "change_node":
return { return {
action: updateActiveNode, action: updateActiveNode,
value: [0, false, newActiveNodeId, newNodeColIdx, newNodeRowIdx], value: [
}; 0,
case "throw_node_media": false,
case "throw_node_gate": newActiveNodeId,
case "throw_node_sskn": newNodeColIdx,
return { newNodeRowIdx,
action: animateActiveNodeThrow, newNodeMatIdx,
value: [0, true], ],
}; };
// case "throw_node_media":
// case "throw_node_gate":
// case "throw_node_sskn":
// return {
// action: animateActiveNodeThrow,
// value: [0, true],
// };
} }
}, },
[animateActiveNodeThrow, updateActiveNode] [updateActiveNode]
); );
useEffect(() => { useEffect(() => {
@ -112,19 +109,21 @@ const NodeManager = (props: StateManagerProps) => {
const newActiveNodeId = props.eventState.newActiveNodeId; const newActiveNodeId = props.eventState.newActiveNodeId;
const newNodeRowIdx = props.eventState.newNodeRowIdx; const newNodeRowIdx = props.eventState.newNodeRowIdx;
const newNodeColIdx = props.eventState.newNodeColIdx; const newNodeColIdx = props.eventState.newNodeColIdx;
const newNodeMatIdx = props.eventState.newNodeMatIdx;
const dispatchedObject = dispatchObject( const dispatchedObject = dispatchObject(
eventAction, eventAction,
newActiveNodeId, newActiveNodeId,
newNodeColIdx, newNodeColIdx,
newNodeRowIdx newNodeRowIdx,
newNodeMatIdx
); );
if (dispatchedObject) { if (dispatchedObject) {
dispatchedObject.action.apply(null, dispatchedObject.value as never); dispatchedObject.action.apply(null, dispatchedObject.value as never);
} }
} }
}, [props.eventState, setActiveNode, dispatchObject]); }, [props.eventState, setActiveNodeState, dispatchObject]);
return null; return null;
}; };

View file

@ -3,70 +3,49 @@ import { useSiteStore } from "../../store";
import { StateManagerProps } from "./EventManager"; import { StateManagerProps } from "./EventManager";
const SiteManager = (props: StateManagerProps) => { const SiteManager = (props: StateManagerProps) => {
const addToSiteRotY = useSiteStore((state) => state.addToSiteRotY); const setSiteRotY = useSiteStore((state) => state.setSiteRotY);
const addToSitePosY = useSiteStore((state) => state.addToSitePosY); const setSitePosY = useSiteStore((state) => state.setSitePosY);
const setSiteRotIdx = useSiteStore((state) => state.setSiteRotIdx);
const setIsSiteYChanging = useSiteStore((state) => state.setIsSiteChanging);
const rotateSite = useCallback(
(value: number, newSiteRotIdx: string) => {
addToSiteRotY(value);
setSiteRotIdx(newSiteRotIdx);
},
[addToSiteRotY, setSiteRotIdx]
);
const dispatchObject = useCallback( const dispatchObject = useCallback(
(event: string, newSiteRotIdx: string) => { (event: string, newSitePosY: number, newSiteRotY: number) => {
switch (event) { switch (event) {
case "move_up": case "move_up":
return {
action: addToSitePosY,
value: [-1.5],
actionDelay: 1300,
};
case "move_down": case "move_down":
return { return {
action: addToSitePosY, action: setSitePosY,
value: [1.5], value: newSitePosY,
actionDelay: 1300, actionDelay: 1300,
}; };
case "move_left": case "move_left":
return {
action: rotateSite,
value: [Math.PI / 4, newSiteRotIdx],
actionDelay: 1100,
};
case "move_right": case "move_right":
return { return {
action: rotateSite, action: setSiteRotY,
value: [-Math.PI / 4, newSiteRotIdx], value: newSiteRotY,
actionDelay: 1100, actionDelay: 1100,
}; };
} }
}, },
[addToSitePosY, rotateSite] [setSitePosY, setSiteRotY]
); );
useEffect(() => { useEffect(() => {
if (props.eventState) { if (props.eventState) {
const eventAction = props.eventState.event; const eventAction = props.eventState.event;
const newSiteRotIdx = props.eventState.newSiteRotIdx; const newSiteRotY = props.eventState.newSiteRotY;
const newSitePosY = props.eventState.newSitePosY;
const dispatchedObject = dispatchObject(eventAction, newSiteRotIdx); const dispatchedObject = dispatchObject(
eventAction,
newSitePosY,
newSiteRotY
);
if (dispatchedObject) { if (dispatchedObject) {
setIsSiteYChanging(true);
setTimeout(() => { setTimeout(() => {
(dispatchedObject.action as any).apply(null, dispatchedObject.value); dispatchedObject.action(dispatchedObject.value);
}, dispatchedObject.actionDelay); }, dispatchedObject.actionDelay);
setTimeout(() => {
setIsSiteYChanging(false);
}, 3000);
} }
} }
}, [dispatchObject, props.eventState, setIsSiteYChanging]); }, [dispatchObject, props.eventState]);
return null; return null;
}; };

View file

@ -1,110 +1,95 @@
import { useCallback, useEffect } from "react"; import { useCallback, useEffect } from "react";
import node_huds from "../../resources/node_huds.json"; import node_huds from "../../resources/node_huds.json";
import site_a from "../../resources/site_a.json"; import site_a from "../../resources/site_a.json";
import { useTextRendererStore } from "../../store"; import { useYellowTextStore } from "../../store";
import { SiteType } from "../../components/MainScene/Site"; import { SiteType } from "../../components/MainScene/Site";
import { StateManagerProps } from "./EventManager";
const YellowTextManager = (props: any) => { const YellowTextManager = (props: StateManagerProps) => {
const setYellowText = useTextRendererStore((state) => state.setYellowText); const setTransformState = useYellowTextStore(
(state) => state.setTransformState
);
const addToTransformState = useYellowTextStore(
(state) => state.addToTransformState
);
const setText = useYellowTextStore((state) => state.setText);
const setYellowTextOffsetXCoeff = useTextRendererStore( const setDisableTrail = useYellowTextStore((state) => state.setDisableTrail);
(state) => state.setYellowTextOffsetXCoeff
);
const addToYellowTextPosY = useTextRendererStore(
(state) => state.addToYellowTextPosY
);
const addToYellowTextPosX = useTextRendererStore(
(state) => state.addToYellowTextPosX
);
const setYellowTextPosY = useTextRendererStore(
(state) => state.setYellowTextPosY
);
const setYellowTextPosX = useTextRendererStore(
(state) => state.setYellowTextPosX
);
const animateYellowTextWithMove = useCallback( const animateYellowTextWithMove = useCallback(
( (
yellowLetterPosXOffset: number, posXOffset: number,
yellowLetterPosYOffset: number, posYOffset: number,
newActiveHudId: string, newActiveHudId: string,
newActiveNodeId: string, newActiveNodeId: string,
newLevel: string, newLevel: string,
delay: number delay: number
) => { ) => {
setDisableTrail(true);
// animate the letters to match that of site's // animate the letters to match that of site's
// to create an illusion of not moving // to create an illusion of not moving
setTimeout(() => { setTimeout(() => {
addToYellowTextPosY(yellowLetterPosYOffset); addToTransformState(posXOffset, "posX");
addToYellowTextPosX(yellowLetterPosXOffset); addToTransformState(posYOffset, "posY");
}, delay); }, delay);
setTimeout(() => { setTimeout(() => {
// make current hud big text shrink // make current hud big text shrink
setYellowTextOffsetXCoeff(-1); setTransformState(-1, "xOffset");
}, 2500); }, 2500);
setTimeout(() => { setTimeout(() => {
// animate it to new pos x/y // animate it to new pos x/y
setYellowTextPosX( setTransformState(
node_huds[newActiveHudId as keyof typeof node_huds].big_text[0] node_huds[newActiveHudId as keyof typeof node_huds].big_text[0],
"posX"
); );
setYellowTextPosY( setTransformState(
node_huds[newActiveHudId as keyof typeof node_huds].big_text[1] node_huds[newActiveHudId as keyof typeof node_huds].big_text[1],
"posY"
); );
// set new text according to the node name // set new text according to the node name
setYellowText( setText((site_a as SiteType)[newLevel][newActiveNodeId].node_name);
(site_a as SiteType)[newLevel][newActiveNodeId].node_name setDisableTrail(false);
);
}, 3000); }, 3000);
// unshrink text // unshrink text
setTimeout(() => { setTimeout(() => {
setYellowTextOffsetXCoeff(0); setTransformState(0, "xOffset");
}, 3900); }, 3900);
}, },
[ [addToTransformState, setDisableTrail, setText, setTransformState]
addToYellowTextPosX,
addToYellowTextPosY,
setYellowText,
setYellowTextOffsetXCoeff,
setYellowTextPosX,
setYellowTextPosY,
]
); );
const animateYellowTextWithoutMove = useCallback( const animateYellowTextWithoutMove = useCallback(
(newActiveHudId: string, newActiveNodeId: string, level: string) => { (newActiveHudId: string, newActiveNodeId: string, level: string) => {
// make current hud big text shrink // make current hud big text shrink
setYellowTextOffsetXCoeff(-1); setTransformState(-1, "xOffset");
setTimeout(() => { setTimeout(() => {
setYellowTextPosX( // animate it to new pos x/y
node_huds[newActiveHudId as keyof typeof node_huds].big_text[0] setTransformState(
node_huds[newActiveHudId as keyof typeof node_huds].big_text[0],
"posX"
); );
setYellowTextPosY( setTransformState(
node_huds[newActiveHudId as keyof typeof node_huds].big_text[1] node_huds[newActiveHudId as keyof typeof node_huds].big_text[1],
"posY"
); );
}, 400); }, 400);
// animate it to new pos x/y
setTimeout(() => { setTimeout(() => {
// set new text according to the node name // set new text according to the node name
setYellowText((site_a as SiteType)[level][newActiveNodeId].node_name); setText((site_a as SiteType)[level][newActiveNodeId].node_name);
}, 1000); }, 1000);
setTimeout(() => { setTimeout(() => {
// unshrink text // unshrink text
setYellowTextOffsetXCoeff(0); setTransformState(0, "xOffset");
}, 1200); }, 1200);
}, },
[ [setText, setTransformState]
setYellowText,
setYellowTextOffsetXCoeff,
setYellowTextPosX,
setYellowTextPosY,
]
); );
const animateMediaYellowText = useCallback( const animateMediaYellowText = useCallback(
@ -113,49 +98,46 @@ const YellowTextManager = (props: any) => {
targetMediaComponentTextPos: number[] targetMediaComponentTextPos: number[]
) => { ) => {
// make current text shrink // make current text shrink
setYellowTextOffsetXCoeff(-1); setTransformState(-1, "xOffset");
setTimeout(() => { setTimeout(() => {
setYellowTextPosX(targetMediaComponentTextPos[0]); setTransformState(targetMediaComponentTextPos[0], "posX");
setYellowTextPosY(targetMediaComponentTextPos[1]); setTransformState(targetMediaComponentTextPos[1], "posY");
}, 400); }, 400);
setTimeout(() => { setTimeout(() => {
setYellowText(targetMediaComponentText); setText(targetMediaComponentText);
}, 1000); }, 1000);
setTimeout(() => { setTimeout(() => {
// unshrink text // unshrink text
setYellowTextOffsetXCoeff(0); setTransformState(0, "xOffset");
}, 1200); }, 1200);
}, },
[ [setText, setTransformState]
setYellowText,
setYellowTextOffsetXCoeff,
setYellowTextPosX,
setYellowTextPosY,
]
); );
const initializeYellowTextForMediaScene = useCallback(() => { const initializeYellowTextForMediaScene = useCallback(() => {
setTimeout(() => { setTimeout(() => {
setYellowText("Play"); setText("Play");
setYellowTextPosX(-0.8); setTransformState(-0.8, "posX");
setYellowTextPosY(0.05); setTransformState(0.05, "posY");
}, 3950); }, 3950);
}, [setYellowText, setYellowTextPosX, setYellowTextPosY]); }, [setText, setTransformState]);
const initializeYellowTextForMainScene = useCallback( const initializeYellowTextForMainScene = useCallback(
(activeNodeId: string, level: string) => { (activeNodeId: string, level: string) => {
setYellowText((site_a as SiteType)[level][activeNodeId].node_name); setText((site_a as SiteType)[level][activeNodeId].node_name);
setYellowTextPosX( setTransformState(
node_huds[activeNodeId as keyof typeof node_huds].big_text[0] node_huds[activeNodeId as keyof typeof node_huds].big_text[0],
"posX"
); );
setYellowTextPosY( setTransformState(
node_huds[activeNodeId as keyof typeof node_huds].big_text[1] node_huds[activeNodeId as keyof typeof node_huds].big_text[1],
"posY"
); );
}, },
[setYellowText, setYellowTextPosX, setYellowTextPosY] [setText, setTransformState]
); );
const dispatchObject = useCallback( const dispatchObject = useCallback(
@ -258,8 +240,6 @@ const YellowTextManager = (props: any) => {
animateYellowTextWithMove, animateYellowTextWithMove,
animateYellowTextWithoutMove, animateYellowTextWithoutMove,
props.eventState, props.eventState,
props.newActiveHudId,
props.newActiveNodeId,
dispatchObject, dispatchObject,
]); ]);

View file

@ -25,22 +25,23 @@ const handleMainSceneEvent = (gameContext: GameContext) => {
const nodeColIdx = gameContext.nodeMatrixIndices.colIdx; const nodeColIdx = gameContext.nodeMatrixIndices.colIdx;
const nodeRowIdx = gameContext.nodeMatrixIndices.rowIdx; const nodeRowIdx = gameContext.nodeMatrixIndices.rowIdx;
let newNodeMatIdx = gameContext.nodeMatrixIndices.matrixIdx;
let newNodeColIdx = gameContext.nodeMatrixIndices.colIdx; let newNodeColIdx = gameContext.nodeMatrixIndices.colIdx;
let newNodeRowIdx = gameContext.nodeMatrixIndices.rowIdx; let newNodeRowIdx = gameContext.nodeMatrixIndices.rowIdx;
let newLevel = gameContext.currentLevel; let newLevel = gameContext.activeLevel;
let newSiteRotIdx = gameContext.siteRotIdx; let newSiteRotY = gameContext.siteRotY;
let newSitePosY = gameContext.sitePosY;
let newScene = gameContext.scene; let newScene = gameContext.scene;
switch (keyPress) { switch (keyPress) {
case "left": case "left":
newNodeColIdx = nodeColIdx - 1; newNodeColIdx = nodeColIdx - 1;
if (newNodeColIdx < 0) { if (newNodeColIdx < 0) {
event = "move_left"; event = "move_left";
newSiteRotIdx = newNodeMatIdx = newNodeMatIdx + 1 > 8 ? 1 : newNodeMatIdx + 1;
parseInt(gameContext.siteRotIdx) + 1 > 8
? "1"
: (parseInt(gameContext.siteRotIdx) + 1).toString();
newNodeColIdx = 0; newNodeColIdx = 0;
newSiteRotY -= -Math.PI / 4;
} else { } else {
event = "change_node"; event = "change_node";
} }
@ -50,10 +51,11 @@ const handleMainSceneEvent = (gameContext: GameContext) => {
if (newNodeRowIdx > 2) { if (newNodeRowIdx > 2) {
event = "move_down"; event = "move_down";
newLevel = (parseInt(gameContext.currentLevel) - 1) newLevel = (parseInt(gameContext.activeLevel) - 1)
.toString() .toString()
.padStart(2, "0"); .padStart(2, "0");
newNodeRowIdx = 0; newNodeRowIdx = 0;
newSitePosY += 1.5;
} else { } else {
event = "change_node"; event = "change_node";
} }
@ -63,11 +65,12 @@ const handleMainSceneEvent = (gameContext: GameContext) => {
if (newNodeRowIdx < 0) { if (newNodeRowIdx < 0) {
event = "move_up"; event = "move_up";
newLevel = (parseInt(gameContext.currentLevel) + 1) newLevel = (parseInt(gameContext.activeLevel) + 1)
.toString() .toString()
.padStart(2, "0"); .padStart(2, "0");
newNodeRowIdx = 2; newNodeRowIdx = 2;
newSitePosY -= 1.5;
} else { } else {
event = "change_node"; event = "change_node";
} }
@ -76,12 +79,9 @@ const handleMainSceneEvent = (gameContext: GameContext) => {
newNodeColIdx = nodeColIdx + 1; newNodeColIdx = nodeColIdx + 1;
if (newNodeColIdx > 3) { if (newNodeColIdx > 3) {
event = "move_right"; event = "move_right";
newSiteRotIdx = newNodeMatIdx = newNodeMatIdx - 1 < 1 ? 8 : newNodeMatIdx - 1;
parseInt(gameContext.siteRotIdx) - 1 < 1
? "8"
: (parseInt(gameContext.siteRotIdx) - 1).toString();
newNodeColIdx = 3; newNodeColIdx = 3;
newSiteRotY += -Math.PI / 4;
} else { } else {
event = "change_node"; event = "change_node";
} }
@ -92,7 +92,7 @@ const handleMainSceneEvent = (gameContext: GameContext) => {
// new active blue orb here. // new active blue orb here.
const newActiveNodeId = const newActiveNodeId =
newLevel + newLevel +
node_matrices[newSiteRotIdx as keyof typeof node_matrices][ node_matrices[newNodeMatIdx.toString() as keyof typeof node_matrices][
newNodeRowIdx as number newNodeRowIdx as number
][newNodeColIdx as number]; ][newNodeColIdx as number];
@ -119,7 +119,7 @@ const handleMainSceneEvent = (gameContext: GameContext) => {
const newActiveNodeId = const newActiveNodeId =
newLevel + newLevel +
node_matrices[newSiteRotIdx as keyof typeof node_matrices][ node_matrices[newNodeMatIdx.toString() as keyof typeof node_matrices][
newNodeRowIdx as number newNodeRowIdx as number
][newNodeColIdx as number]; ][newNodeColIdx as number];
@ -130,7 +130,9 @@ const handleMainSceneEvent = (gameContext: GameContext) => {
event: event, event: event,
newNodeColIdx: newNodeColIdx, newNodeColIdx: newNodeColIdx,
newNodeRowIdx: newNodeRowIdx, newNodeRowIdx: newNodeRowIdx,
newSiteRotIdx: newSiteRotIdx, newNodeMatIdx: newNodeMatIdx,
newSitePosY: newSitePosY,
newSiteRotY: newSiteRotY,
newLevel: newLevel, newLevel: newLevel,
newScene: newScene, newScene: newScene,
newActiveNodeId: newActiveNodeId, newActiveNodeId: newActiveNodeId,

View file

@ -1,4 +1,4 @@
import { a, useSpring } from "@react-spring/three"; import { a } from "@react-spring/three";
import { OrbitControls } from "@react-three/drei"; import { OrbitControls } from "@react-three/drei";
import React, { Suspense, useEffect } from "react"; import React, { Suspense, useEffect } from "react";
import Site from "../components/MainScene/Site"; import Site from "../components/MainScene/Site";
@ -9,60 +9,33 @@ import MainSceneIntro from "../components/MainSceneIntro";
import GrayPlanes from "../components/MainScene/GrayPlanes"; import GrayPlanes from "../components/MainScene/GrayPlanes";
import MiddleRing from "../components/MainScene/MiddleRing"; import MiddleRing from "../components/MainScene/MiddleRing";
import Starfield from "../components/MainScene/Starfield"; import Starfield from "../components/MainScene/Starfield";
import { import { useHudStore, useLainStore } from "../store";
useNodeStore, import TextRenderer from "../components/TextRenderer/GreenTextRenderer";
useHudStore,
useLainStore,
useMainGroupStore,
} from "../store";
import TextRenderer from "../components/TextRenderer/TextRenderer";
import HUD from "../components/MainScene/HUD"; import HUD from "../components/MainScene/HUD";
import YellowOrb from "../components/MainScene/YellowOrb"; import YellowOrb from "../components/MainScene/YellowOrb";
import CurrentLevelNodes from "../components/MainScene/CurrentLevelNodes"; import ActiveLevelNodes from "../components/MainScene/ActiveLevelNodes";
import YellowTextRenderer from "../components/TextRenderer/YellowTextRenderer";
const MainScene = () => { const MainScene = () => {
const setLainMoveState = useLainStore((state) => state.setLainMoveState); const setLainMoveState = useLainStore((state) => state.setLainMoveState);
const setActiveNode = useNodeStore((state) => state.setActiveNodeId); const setActiveNodeHudId = useHudStore((state) => state.setId);
const setActiveNodeHudId = useHudStore(
(state) => state.setActiveNodeHudId
);
const mainGroupPosY = useMainGroupStore((state) => state.mainGroupPosY);
const mainGroupPosZ = useMainGroupStore((state) => state.mainGroupPosZ);
const mainGroupRotX = useMainGroupStore((state) => state.mainGroupRotX);
const mainGroupStatePos = useSpring({
mainGroupPosY: mainGroupPosY,
mainGroupPosZ: mainGroupPosZ,
config: { duration: 3644 },
});
const mainGroupStateRot = useSpring({
mainGroupRotX: mainGroupRotX,
config: { duration: 1500 },
});
useEffect(() => { useEffect(() => {
setLainMoveState("standing"); setLainMoveState("standing");
setActiveNode("0422");
setActiveNodeHudId("fg_hud_1"); setActiveNodeHudId("fg_hud_1");
}, [setActiveNode, setActiveNodeHudId, setLainMoveState]); }, [setActiveNodeHudId, setLainMoveState]);
// set lain intro spritesheet before the page loads fully
return ( return (
<perspectiveCamera position-z={3}> <perspectiveCamera position-z={3}>
<Suspense fallback={null}> <Suspense fallback={null}>
<MainSceneIntro /> <MainSceneIntro />
<a.group <a.group>
rotation-x={mainGroupStateRot.mainGroupRotX}
position-y={mainGroupStatePos.mainGroupPosY}
position-z={mainGroupStatePos.mainGroupPosZ}
>
<Preloader /> <Preloader />
<Site /> <Site />
<CurrentLevelNodes /> <ActiveLevelNodes />
<HUD /> <HUD />
<TextRenderer /> <TextRenderer />
<YellowTextRenderer />
<YellowOrb /> <YellowOrb />
<Starfield /> <Starfield />
<GrayPlanes /> <GrayPlanes />

View file

@ -1,6 +1,6 @@
import React, { useCallback, useEffect, useMemo } from "react"; import React, { useCallback, useEffect, useMemo } from "react";
import { useMediaStore } from "../store"; import { useMediaStore } from "../store";
import TextRenderer from "../components/TextRenderer/TextRenderer"; import TextRenderer from "../components/TextRenderer/GreenTextRenderer";
import LeftSide from "../components/MediaScene/Selectables/LeftSide"; import LeftSide from "../components/MediaScene/Selectables/LeftSide";
import RightSide from "../components/MediaScene/Selectables/RightSide"; import RightSide from "../components/MediaScene/Selectables/RightSide";
import AudioVisualizer from "../components/MediaScene/AudioVisualizer/AudioVisualizer"; import AudioVisualizer from "../components/MediaScene/AudioVisualizer/AudioVisualizer";

View file

@ -8,26 +8,22 @@ type SceneState = {
}; };
type HUDState = { type HUDState = {
activeHudId: string; id: string;
hudActive: number; active: number;
hudVisible: boolean; visible: boolean;
setActiveNodeHudId: (to: string) => void; setId: (to: string) => void;
toggleHud: () => void; toggleActive: () => void;
}; };
type NodeState = { type NodeState = {
activeNodeId: string; activeNodeState: {
isActiveNodeInteractedWith: boolean; id: string;
activeNodePosX: number; posX: number;
activeNodePosZ: number; posZ: number;
activeNodeRotZ: number; rotZ: number;
setActiveNodePosX: (to: number) => void; interactedWith: boolean;
setActiveNodePosZ: (to: number) => void; };
setActiveNodeRotZ: (to: number) => void; nodeMatrixIndices: { matrixIdx: number; rowIdx: number; colIdx: number };
setActiveNodeId: (to: string) => void;
setIsActiveNodeInteractedWith: (to: boolean) => void;
nodeMatrixIndices: { rowIdx: number; colIdx: number };
setNodeMatrixIndices: (to: { rowIdx: number; colIdx: number }) => void;
}; };
type LainState = { type LainState = {
@ -35,15 +31,6 @@ type LainState = {
setLainMoveState: (to: string) => void; setLainMoveState: (to: string) => void;
}; };
type MainGroupState = {
mainGroupPosY: number;
mainGroupPosZ: number;
mainGroupRotX: number;
setMainGroupPosY: (to: number) => void;
setMainGroupPosZ: (to: number) => void;
setMainGroupRotX: (to: number) => void;
};
type GrayPlanesState = { type GrayPlanesState = {
grayPlanesVisible: boolean; grayPlanesVisible: boolean;
setGrayPlanesVisible: (to: boolean) => void; setGrayPlanesVisible: (to: boolean) => void;
@ -66,39 +53,25 @@ type YellowOrbState = {
type SiteState = { type SiteState = {
siteRotY: number; siteRotY: number;
sitePosY: number; sitePosY: number;
isSiteChangingY: boolean;
addToSiteRotY: (by: number) => void;
addToSitePosY: (by: number) => void;
setSiteRotY: (to: number) => void; setSiteRotY: (to: number) => void;
setSitePosY: (to: number) => void; setSitePosY: (to: number) => void;
setIsSiteChanging: (to: boolean) => void;
siteRotIdx: string;
setSiteRotIdx: (to: string) => void;
}; };
type LevelState = { type LevelState = {
currentLevel: string; activeLevel: string;
activeLevels: string[]; setActiveLevel: (to: string) => void;
setActiveLevels: (to: string[]) => void;
setCurrentLevel: (to: string) => void;
}; };
type MiddleRingState = { type MiddleRingState = {
middleRingWobbleStrength: number; transformState: {
middleRingRotating: boolean; wobbleStrength: number;
middleRingNoise: number; noiseStrength: number;
middleRingPosY: number; posY: number;
middleRingRotX: number; rotX: number;
middleRingRotZ: number; rotZ: number;
middleRingAnimDuration: number; };
setMiddleRingWobbleStrength: (to: number) => void; isRotating: boolean;
setMiddleRingRotating: (to: boolean) => void; animDuration: number;
setMiddleRingNoise: (to: number) => void;
addToMiddleRingPosY: (val: number) => void;
setMiddleRingPosY: (to: number) => void;
setMiddleRingRotX: (to: number) => void;
setMiddleRingRotZ: (to: number) => void;
setMiddleRingAnimDuration: (to: number) => void;
}; };
type MediaWordState = { type MediaWordState = {
@ -115,17 +88,27 @@ type MediaWordState = {
resetWordPositionDataStructIdx: () => void; resetWordPositionDataStructIdx: () => void;
}; };
export type YellowTextState = {
disableTrail: boolean;
text: string;
transformState: {
posX: number;
posY: number;
xOffset: number;
};
};
export type GreenTextState = {
text: string;
transformState: {
posX: { initial: number; final: number };
posY: number;
xOffset: number;
};
active: number;
};
export type TextRendererState = { export type TextRendererState = {
yellowText: string;
yellowTextPosY: number;
yellowTextPosX: number;
yellowTextOffsetXCoeff: number;
setYellowText: (to: string) => void;
addToYellowTextPosY: (val: number) => void;
addToYellowTextPosX: (val: number) => void;
setYellowTextPosY: (to: number) => void;
setYellowTextPosX: (to: number) => void;
setYellowTextOffsetXCoeff: (to: number) => void;
greenTextPosY: number; greenTextPosY: number;
greenTextPosX: { initial: number; final: number }; greenTextPosX: { initial: number; final: number };
greenText: string; greenText: string;
@ -136,18 +119,6 @@ export type TextRendererState = {
toggleGreenText: () => void; toggleGreenText: () => void;
}; };
export type ImageSrc = {
default: string;
};
type ImageState = {
images: {
1: ImageSrc | undefined;
2: ImageSrc | undefined;
3: ImageSrc | undefined;
};
};
type GateState = { type GateState = {
gateLvl: number; gateLvl: number;
incrementGateLvl: () => void; incrementGateLvl: () => void;
@ -162,76 +133,101 @@ type SSknState = {
toggleLoading: () => void; toggleLoading: () => void;
}; };
export const useTextRendererStore = create<TextRendererState>((set) => ({ export const useYellowTextStore = create(
// yellow text combine(
yellowText: "Play", {
yellowTextPosY: 0.23, disableTrail: false,
yellowTextPosX: -0.35, text: "Play",
yellowTextOffsetXCoeff: 0, transformState: {
setYellowText: (to) => set(() => ({ yellowText: to })), posX: 0,
addToYellowTextPosY: (val) => posY: 0,
set((state) => ({ yellowTextPosY: state.yellowTextPosY + val })), xOffset: 0,
addToYellowTextPosX: (val) => },
set((state) => ({ yellowTextPosX: state.yellowTextPosX + val })), } as YellowTextState,
setYellowTextPosY: (to) => set(() => ({ yellowTextPosY: to })), (set) => ({
setYellowTextPosX: (to) => set(() => ({ yellowTextPosX: to })), setDisableTrail: (to: boolean) => set(() => ({ disableTrail: to })),
setYellowTextOffsetXCoeff: (to) => setText: (to: string) => set(() => ({ text: to })),
set(() => ({ yellowTextOffsetXCoeff: to })), setTransformState: (to: number, at: string) =>
// green text set((state) => ({
greenText: "TOUKO's DIARY", transformState: { ...state.transformState, [at]: to },
greenTextPosY: 0, })),
greenTextPosX: { initial: 0, final: 0 }, addToTransformState: (val: number, at: string) =>
greenTextActive: 1, set((state) => ({
setGreenTextPosY: (to) => set(() => ({ greenTextPosY: to })), transformState: {
setGreenTextPosX: (to) => set({ greenTextPosX: to }), ...state.transformState,
setGreenText: (to) => set(() => ({ greenText: to })), [at]:
toggleGreenText: () => state.transformState[at as keyof typeof state.transformState] +
set((state) => ({ greenTextActive: Number(!state.greenTextActive) })), val,
})); },
})),
})
)
);
export const useGreenTextStore = create(
combine(
{
text: "TOUKO's DIARY",
transformState: {
posX: { initial: 0, final: 0 },
posY: 0,
xOffset: 0,
},
active: 1,
} as GreenTextState,
(set) => ({
setText: (to: string) => set(() => ({ text: to })),
setTransformState: (
to: number | { initial: number; final: number },
at: string
) =>
set((state) => ({
transformState: { ...state.transformState, [at]: to },
})),
toggleActive: () => set((state) => ({ active: Number(!state.active) })),
})
)
);
export const useHudStore = create<HUDState>((set) => ({ export const useHudStore = create<HUDState>((set) => ({
activeHudId: "fg_hud_1", id: "fg_hud_1",
hudActive: 1, active: 1,
hudVisible: true, visible: true,
setActiveNodeHudId: (to) => set(() => ({ activeHudId: to })), setId: (to) => set(() => ({ id: to })),
toggleHud: () => set((state) => ({ hudActive: Number(!state.hudActive) })), toggleActive: () => set((state) => ({ active: Number(!state.active) })),
})); }));
export const useNodeStore = create<NodeState>((set) => ({ export const useNodeStore = create(
activeNodeId: "0422", combine(
isActiveNodeInteractedWith: false, {
activeNodePosX: 0, activeNodeState: {
activeNodePosZ: 0, id: "0422",
activeNodeRotZ: 0, posX: 0,
setActiveNodePosX: (to) => set(() => ({ activeNodePosX: to })), posZ: 0,
setActiveNodePosZ: (to) => set(() => ({ activeNodePosZ: to })), rotZ: 0,
setActiveNodeRotZ: (to) => set(() => ({ activeNodeRotZ: to })), interactedWith: false,
setActiveNodeId: (to) => set(() => ({ activeNodeId: to })), },
setIsActiveNodeInteractedWith: (to) => nodeMatrixIndices: { matrixIdx: 7, rowIdx: 0, colIdx: 0 },
set(() => ({ isActiveNodeInteractedWith: to })), } as NodeState,
nodeRowIdx: 0, (set) => ({
setActiveNodeState: (to: number | boolean | string, at: string) =>
nodeMatrixIndices: { rowIdx: 0, colIdx: 0 }, set((state) => ({
setNodeMatrixIndices: (to) => set(() => ({ nodeMatrixIndices: to })), activeNodeState: { ...state.activeNodeState, [at]: to },
})); })),
setNodeMatrixIndices: (to: {
matrixIdx: number;
rowIdx: number;
colIdx: number;
}) => set(() => ({ nodeMatrixIndices: to })),
})
)
);
export const useLainStore = create<LainState>((set) => ({ export const useLainStore = create<LainState>((set) => ({
lainMoveState: "standing", lainMoveState: "standing",
setLainMoveState: (to) => set(() => ({ lainMoveState: to })), setLainMoveState: (to) => set(() => ({ lainMoveState: to })),
})); }));
// -2.5 - intro val
//-9.5 - intro val
//1.5 - intro val
export const useMainGroupStore = create<MainGroupState>((set) => ({
mainGroupPosY: 0,
mainGroupPosZ: 0,
mainGroupRotX: 0,
setMainGroupPosY: (to) => set(() => ({ mainGroupPosY: to })),
setMainGroupPosZ: (to) => set(() => ({ mainGroupPosZ: to })),
setMainGroupRotX: (to) => set(() => ({ mainGroupRotX: to })),
}));
export const useGrayPlanesStore = create<GrayPlanesState>((set) => ({ export const useGrayPlanesStore = create<GrayPlanesState>((set) => ({
grayPlanesVisible: true, grayPlanesVisible: true,
setGrayPlanesVisible: (to) => set(() => ({ grayPlanesVisible: to })), setGrayPlanesVisible: (to) => set(() => ({ grayPlanesVisible: to })),
@ -254,42 +250,37 @@ export const useYellowOrbStore = create<YellowOrbState>((set) => ({
export const useSiteStore = create<SiteState>((set) => ({ export const useSiteStore = create<SiteState>((set) => ({
sitePosY: 0, sitePosY: 0,
siteRotY: 0, siteRotY: 0,
isSiteChangingY: false,
addToSitePosY: (by) => set((state) => ({ sitePosY: state.sitePosY + by })),
addToSiteRotY: (by) => set((state) => ({ siteRotY: state.siteRotY + by })),
setSitePosY: (to) => set(() => ({ sitePosY: to })), setSitePosY: (to) => set(() => ({ sitePosY: to })),
setSiteRotY: (to) => set(() => ({ siteRotY: to })), setSiteRotY: (to) => set(() => ({ siteRotY: to })),
setIsSiteChanging: (to) => set(() => ({ isSiteChangingY: to })),
siteRotIdx: "7",
setSiteRotIdx: (to) => set(() => ({ siteRotIdx: to })),
})); }));
export const useMiddleRingStore = create<MiddleRingState>((set) => ({ export const useMiddleRingStore = create(
middleRingWobbleStrength: 0, combine(
middleRingRotating: true, {
middleRingNoise: 0.03, transformState: {
middleRingPosY: -0.11, wobbleStrength: 0,
middleRingRotX: 0, noiseStrength: 0.03,
middleRingRotZ: 0, posY: -0.11,
middleRingAnimDuration: 600, rotX: 0,
setMiddleRingWobbleStrength: (to) => rotZ: 0,
set(() => ({ middleRingWobbleStrength: to })), },
setMiddleRingRotating: (to) => set(() => ({ middleRingRotating: to })), isRotating: true,
setMiddleRingNoise: (to) => set(() => ({ middleRingNoise: to })), animDuration: 600,
addToMiddleRingPosY: (by) => } as MiddleRingState,
set((state) => ({ middleRingPosY: state.middleRingPosY + by })), (set) => ({
setMiddleRingPosY: (to) => set(() => ({ middleRingPosY: to })), setTransformState: (to: number, at: string) =>
setMiddleRingRotX: (to) => set(() => ({ middleRingRotX: to })), set((state) => ({
setMiddleRingRotZ: (to) => set(() => ({ middleRingRotZ: to })), transformState: { ...state.transformState, [at]: to },
setMiddleRingAnimDuration: (to) => })),
set(() => ({ middleRingAnimDuration: to })), setRotating: (to: boolean) => ({ isRotating: to }),
})); setAnimDuration: (to: number) => ({ animDuration: to }),
})
)
);
export const useLevelStore = create<LevelState>((set) => ({ export const useLevelStore = create<LevelState>((set) => ({
currentLevel: "04", activeLevel: "04",
activeLevels: ["02", "03", "05", "06"], setActiveLevel: (to) => set(() => ({ activeLevel: to })),
setActiveLevels: (to) => set(() => ({ activeLevels: to })),
setCurrentLevel: (to) => set(() => ({ currentLevel: to })),
})); }));
export const useMediaStore = create( export const useMediaStore = create(
@ -442,7 +433,7 @@ export const useSSknStore = create<SSknState>((set) => ({
})); }));
export const useSceneStore = create<SceneState>((set) => ({ export const useSceneStore = create<SceneState>((set) => ({
currentScene: "polytan", currentScene: "media",
setScene: (to) => set(() => ({ currentScene: to })), setScene: (to) => set(() => ({ currentScene: to })),
})); }));
@ -586,18 +577,6 @@ export const useBootStore = create(
) )
); );
export const useImageStore = create(
combine(
{
images: { 1: undefined, 2: undefined, 3: undefined },
} as ImageState,
(set) => ({
setImages: (to: ImageSrc, idx: number) =>
set((state) => ({ images: { ...state.images, [idx]: to } })),
})
)
);
export const usePolytanStore = create<any>((set) => ({ export const usePolytanStore = create<any>((set) => ({
unlockedParts: { unlockedParts: {
body: true, body: true,