fixed some bugs, porting recoil stuff to zustand. this is a mess for now.

This commit is contained in:
ad044 2020-10-14 23:33:32 +04:00
parent 4b4f5ebc7a
commit ba9a16ea74
21 changed files with 322 additions and 303 deletions

5
package-lock.json generated
View file

@ -13946,6 +13946,11 @@
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz",
"integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q=="
},
"zustand": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/zustand/-/zustand-3.1.3.tgz",
"integrity": "sha512-Otuzh3r0GsatvsUWeXEwdYjZEw1TItWcAXwDGEHdXE4/k6WbAdVDxC21t/Poq4ZMB+2VaQNKICWu7eCBUJ65tQ=="
}
}
}

View file

@ -21,7 +21,8 @@
"three": "^0.119.1",
"three-plain-animator": "^1.0.2",
"ts-node": "^9.0.0",
"typescript": "^3.7.5"
"typescript": "^3.7.5",
"zustand": "^3.1.3"
},
"scripts": {
"start": "react-scripts start",

View file

@ -4,7 +4,7 @@ import "./static/css/hub.css";
import "./static/css/main.css";
import { Canvas } from "react-three-fiber";
import { RecoilRoot } from "recoil";
import Intro from "./components/Intro";
import Boot from "./components/Boot";
const App = () => {
const [moveToGame, setMoveToGame] = useState(false);
@ -19,8 +19,8 @@ const App = () => {
return (
<div id="game-root" className="game">
{/*<Intro setMoveToGame={setMoveToGame} />*/}
{/* {moveToGame ? <MainScene /> : <Intro setMoveToGame={setMoveToGame} />} */}
{/*<Boot setMoveToGame={setMoveToGame} />*/}
{/* {moveToGame ? <MainScene /> : <Boot setMoveToGame={setMoveToGame} />} */}
<Canvas concurrent>
<RecoilRoot>
<MainScene />

View file

@ -50,7 +50,7 @@ type IntroProps = {
setMoveToGame: React.Dispatch<React.SetStateAction<boolean>>;
};
const Intro = (props: IntroProps) => {
const Boot = (props: IntroProps) => {
const [looping, setLooping] = useState(true);
const [isArrowUp, setIsArrowUp] = useState(true);
@ -283,4 +283,4 @@ const Intro = (props: IntroProps) => {
);
};
export default Intro;
export default Boot;

View file

@ -1,5 +1,5 @@
import React, { memo } from "react";
import { useFrame, useLoader } from "react-three-fiber";
import { useLoader } from "react-three-fiber";
import * as THREE from "three";
import bigHud from "../../static/sprites/big_hud.png";
import bigHudMirrored from "../../static/sprites/big_hud_mirrored.png";
@ -7,27 +7,68 @@ import longHud from "../../static/sprites/long_hud.png";
import longHudMirrored from "../../static/sprites/long_hud_mirrored.png";
import boringHud from "../../static/sprites/long_hud_boring.png";
import boringHudMirrored from "../../static/sprites/long_hud_boring_mirrored.png";
import { a, useSpring } from "@react-spring/three";
import { a, useSpring, useTrail } from "@react-spring/three";
import { useRecoilValue } from "recoil";
import {
bigHudTextAtom,
hudActiveAtom,
mediumHudTextAtom,
} from "./HUDElementAtom";
import { currentHUDAtom } from "./HUDElementAtom";
import HUDText from "./HUDText";
import { useBlueOrbStore } from "../store";
import blue_orb_huds from "../../resources/blue_orb_huds.json";
import site_a from "../../resources/site_a.json";
import { BigLetter, MediumLetter } from "../TextRenderer/TextRenderer";
import { isSiteYChangingAtom } from "../Site/SiteAtom";
export type HUDElementProps = {
hudVisibility: boolean;
};
const HUDElement = memo((props: HUDElementProps) => {
const currentHud = useRecoilValue(currentHUDAtom);
const hudActive = useBlueOrbStore((state) => state.hudActive);
const currentBigHudText = useRecoilValue(bigHudTextAtom);
const currentMediumHudText = useRecoilValue(mediumHudTextAtom);
const currentBlueOrbId = useBlueOrbStore((state) => state.blueOrbId);
const currentHudId = useBlueOrbStore((state) => state.hudId);
const hudActive = useRecoilValue(hudActiveAtom);
const yellowHudTextPosY = useBlueOrbStore((state) => state.yellowHudTextPosY);
const yellowHudTextPosX = useBlueOrbStore((state) => state.yellowHudTextPosX);
const currentHud = blue_orb_huds[currentHudId as keyof typeof blue_orb_huds];
const currentYellowHudText = useBlueOrbStore((state) => state.yellowHudText);
const currentGreenHudText =
site_a[currentBlueOrbId as keyof typeof site_a].green_text;
const yellowTextArr = currentYellowHudText.split("");
const greenTextArr = currentGreenHudText.split("");
const yellowLetterPosY = yellowHudTextPosY;
const yellowLetterPosX = yellowHudTextPosX;
const isSiteChangingY = useRecoilValue(isSiteYChangingAtom);
// this one is used for letter actions
const letterTrail = useTrail(currentYellowHudText.length, {
yellowLetterPosX: yellowLetterPosX,
yellowLetterPosY: yellowLetterPosY,
config: { duration: 280 },
});
// this one is used when the site moves up/down and
// the text has to stay stationary
const letterStaticState = useSpring({
yellowLetterPosX: yellowLetterPosX,
yellowLetterPosY: yellowLetterPosY,
config: { duration: 1200 },
});
const { greenTextHUDPositionX } = useSpring({
greenTextHUDPositionX: hudActive,
config: { duration: 500 },
});
const mediumHudPosX = greenTextHUDPositionX.to(
[0, 1],
[
currentHud["medium_text"]["initial_position"][0],
currentHud["medium_text"]["position"][0],
]
);
const hudElementState = useSpring({
bigHUDPositionX: hudActive,
@ -137,7 +178,54 @@ const HUDElement = memo((props: HUDElementProps) => {
depthTest={false}
/>
</a.sprite>
<HUDText bigText={currentBigHudText} mediumText={currentMediumHudText} />
{isSiteChangingY
? yellowTextArr.map((letter, idx) => (
<a.group
key={idx}
position-x={letterStaticState.yellowLetterPosX}
position-y={letterStaticState.yellowLetterPosY}
position-z={-8.7}
scale={[0.04, 0.06, 0.04]}
>
<BigLetter
color={"yellow"}
letter={yellowTextArr[idx]}
kerningOffset={idx}
key={idx}
/>
</a.group>
))
: letterTrail.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"}
letter={yellowTextArr[idx]}
kerningOffset={idx}
key={idx}
/>
</a.group>
))}
<a.group
position-x={mediumHudPosX}
position-y={currentHud["medium_text"]["position"][1]}
position-z={-8.7}
scale={[0.02, 0.035, 0.02]}
>
{greenTextArr.map((letter, idx) => (
<MediumLetter
color={"yellow"}
letter={letter}
kerningOffset={idx}
key={idx}
/>
))}
</a.group>
</group>
);
});

View file

@ -1,11 +1,6 @@
import { atom } from "recoil";
import blue_orb_huds from "../../resources/blue_orb_huds.json";
export const hudActiveAtom = atom({
key: "hudActiveAtom",
default: 1,
});
export const hudVisibilityAtom = atom({
key: "hudVisibilityAtom",
default: true,
@ -16,13 +11,13 @@ export const currentHUDAtom = atom({
default: blue_orb_huds.fg_hud_1,
});
export const bigLetterPosYAtom = atom({
key: "bigLetterPosYAtom",
export const yellowLetterPosYAtom = atom({
key: "yellowLetterPosYAtom",
default: blue_orb_huds.fg_hud_1.big_text[1],
});
export const bigLetterPosXAtom = atom({
key: "bigLetterPosXAtom",
export const yellowLetterPosXAtom = atom({
key: "yellowLetterPosXAtom",
default: blue_orb_huds.fg_hud_1.big_text[0],
});

View file

@ -1,112 +0,0 @@
import React from "react";
import { BigLetter, MediumLetter } from "../TextRenderer/TextRenderer";
import { a, useSpring, useTrail } from "@react-spring/three";
import { useRecoilValue } from "recoil";
import {
bigLetterPosXAtom,
bigLetterPosYAtom, currentHUDAtom,
hudActiveAtom,
} from "./HUDElementAtom";
import { isSiteYChangingAtom } from "../Site/SiteAtom";
type HUDTextProps = {
bigText: string;
mediumText: string;
};
const HUDText = (props: HUDTextProps) => {
const bigLetterPosX = useRecoilValue(bigLetterPosXAtom);
const bigLetterPosY = useRecoilValue(bigLetterPosYAtom);
const currentHud = useRecoilValue(currentHUDAtom);
const isSiteChangingY = useRecoilValue(isSiteYChangingAtom);
const hudActive = useRecoilValue(hudActiveAtom);
const { mediumTextHUDPositionX } = useSpring({
mediumTextHUDPositionX: hudActive,
config: { duration: 500 },
});
const mediumHudPosX = mediumTextHUDPositionX.to(
[0, 1],
[
currentHud["medium_text"]["initial_position"][0],
currentHud["medium_text"]["position"][0],
]
);
const bigTextArr = props.bigText.split("");
const mediumTextArr = props.mediumText.split("");
// this one is used for letter animations
const letterTrail = useTrail(bigTextArr.length, {
bigLetterPosX: bigLetterPosX,
bigLetterPosY: bigLetterPosY,
config: { duration: 280 },
});
// this one is used when the site moves up/down and
// the text has to stay stationary
const letterStaticState = useSpring({
bigLetterPosX: bigLetterPosX,
bigLetterPosY: bigLetterPosY,
config: { duration: 1200 },
});
return (
<>
{isSiteChangingY
? bigTextArr.map((letter, idx) => (
<a.group
key={idx}
position-x={letterStaticState.bigLetterPosX}
position-y={letterStaticState.bigLetterPosY}
position-z={-8.7}
scale={[0.04, 0.06, 0.04]}
>
<BigLetter
color={"yellow"}
letter={bigTextArr[idx]}
kerningOffset={idx}
key={idx}
/>
</a.group>
))
: letterTrail.map(({ bigLetterPosX, bigLetterPosY }, idx) => (
<a.group
key={idx}
position-x={bigLetterPosX}
position-y={bigLetterPosY}
position-z={-8.7}
scale={[0.04, 0.06, 0.04]}
>
<BigLetter
color={"yellow"}
letter={bigTextArr[idx]}
kerningOffset={idx}
key={idx}
/>
</a.group>
))}
<a.group
position-x={mediumHudPosX}
position-y={currentHud["medium_text"]["position"][1]}
position-z={-8.7}
scale={[0.02, 0.035, 0.02]}
>
{mediumTextArr.map((letter, idx) => (
<MediumLetter
color={"yellow"}
letter={letter}
kerningOffset={idx}
key={idx}
/>
))}
</a.group>
</>
);
};
export default HUDText;

View file

@ -2,13 +2,14 @@ import React, { useEffect, useMemo } from "react";
import { useSetRecoilState } from "recoil";
import {
currentHUDAtom,
hudActiveAtom,
mediumHudTextAtom,
} from "../HUD/HUDElementAtom";
import blue_orb_huds from "../../resources/blue_orb_huds.json";
import { useBlueOrbStore } from "../store";
const BlueOrbHUDStateManager = (props: any) => {
const setHudActive = useSetRecoilState(hudActiveAtom);
const setCurrentHudId = useBlueOrbStore((state) => state.setCurrentHudId);
const toggleHud = useBlueOrbStore((state) => state.toggleHud);
const setCurrentHUDElement = useSetRecoilState(currentHUDAtom);
const setMediumHudText = useSetRecoilState(mediumHudTextAtom);
@ -16,8 +17,8 @@ const BlueOrbHUDStateManager = (props: any) => {
() => ({
moveUp: { duration: 3903.704 },
moveDown: { duration: 3903.704 },
rotateLeft: { duration: 3903.704 },
rotateRight: { duration: 3903.704 },
moveLeft: { duration: 3903.704 },
moveRight: { duration: 3903.704 },
changeBlueOrbUp: { duration: 500 },
changeBlueOrbDown: { duration: 500 },
changeBlueOrbLeft: { duration: 500 },
@ -29,21 +30,18 @@ const BlueOrbHUDStateManager = (props: any) => {
useEffect(() => {
if (props.eventState) {
const targetBlueOrbHudId = props.targetBlueOrbHudId;
const targetBlueOrbGreenText = props.targetBlueOrbGreenText;
const targetBlueOrbHudData =
blue_orb_huds[targetBlueOrbHudId as keyof typeof blue_orb_huds];
const dispatchedAction =
dispatcherObjects[props.eventState as keyof typeof dispatcherObjects];
// setHudActive((prev: boolean) => !prev);
setHudActive((prev: number) => Number(!prev));
toggleHud();
setTimeout(() => {
setCurrentHUDElement(targetBlueOrbHudData);
setMediumHudText(targetBlueOrbGreenText);
setHudActive((prev: number) => Number(!prev));
setCurrentHudId(targetBlueOrbHudId);
// setCurrentHUDElement(targetBlueOrbHudData);
// setMediumHudText(targetBlueOrbGreenText);
toggleHud();
}, dispatchedAction.duration);
}
}, [
@ -52,8 +50,9 @@ const BlueOrbHUDStateManager = (props: any) => {
props.targetBlueOrbGreenText,
props.targetBlueOrbHudId,
setCurrentHUDElement,
setHudActive,
setCurrentHudId,
setMediumHudText,
toggleHud,
]);
return null;
};

View file

@ -2,95 +2,112 @@ import React, { useCallback, useEffect, useMemo } from "react";
import blue_orb_huds from "../../resources/blue_orb_huds.json";
import site_a from "../../resources/site_a.json";
import { useSetRecoilState } from "recoil";
import { bigLetterOffsetXCoeffAtom } from "../TextRenderer/TextRendererAtom";
import {
bigHudTextAtom,
bigLetterPosXAtom,
bigLetterPosYAtom,
} from "../HUD/HUDElementAtom";
import { bigHudTextAtom } from "../HUD/HUDElementAtom";
import { useBlueOrbStore } from "../store";
const BlueOrbHUDTextStateManager = (props: any) => {
const setBigLetterOffSetXCoeff = useSetRecoilState(bigLetterOffsetXCoeffAtom);
const setBigLetterPosY = useSetRecoilState(bigLetterPosYAtom);
const setBigLetterPosX = useSetRecoilState(bigLetterPosXAtom);
const setBigHudText = useSetRecoilState(bigHudTextAtom);
const currentBlueOrbHudId = useBlueOrbStore((state) => state.hudId);
const currentBlueOrbId = useBlueOrbStore((state) => state.blueOrbId);
const setYellowHudText = useBlueOrbStore((state) => state.setYellowHudText);
const setYellowHudTextOffsetXCoeff = useBlueOrbStore(
(state) => state.setYellowHudTextOffsetXCoeff
);
const animateBigTextWithMove = useCallback(
const incrementYellowHudTextPosY = useBlueOrbStore(
(state) => state.incrementYellowHudTextPosY
);
const setYellowHudTextPosY = useBlueOrbStore(
(state) => state.setYellowHudTextPosY
);
const setYellowHudTextPosX = useBlueOrbStore(
(state) => state.setYellowHudTextPosX
);
const animateYellowTextWithMove = useCallback(
(
targetBlueOrbHudId: string,
targetBlueOrbId: string,
bigLetterPosYOffset: number
yellowLetterPosYOffset: number
) => {
// animate the letters to match that of site's
// to create an illusion of not moving
setTimeout(() => {
setBigLetterPosY((prev: number) => prev + bigLetterPosYOffset);
incrementYellowHudTextPosY(yellowLetterPosYOffset);
}, 1300);
setTimeout(() => {
// make current hud big text shrink
setBigLetterOffSetXCoeff(-1);
setYellowHudTextOffsetXCoeff(-1);
}, 2500);
setTimeout(() => {
// animate it to new pos x/y
setBigLetterPosX(
blue_orb_huds[targetBlueOrbHudId as keyof typeof blue_orb_huds]
setYellowHudTextPosX(
blue_orb_huds[currentBlueOrbHudId as keyof typeof blue_orb_huds]
.big_text[0]
);
setBigLetterPosY(
blue_orb_huds[targetBlueOrbHudId as keyof typeof blue_orb_huds]
setYellowHudTextPosY(
blue_orb_huds[currentBlueOrbHudId as keyof typeof blue_orb_huds]
.big_text[1]
);
// set new text according to the node name
setBigHudText(site_a[targetBlueOrbId as keyof typeof site_a].node_name);
setYellowHudText(
site_a[currentBlueOrbId as keyof typeof site_a].node_name
);
}, 3000);
// unshrink text
setTimeout(() => {
setBigLetterOffSetXCoeff(0);
setYellowHudTextOffsetXCoeff(0);
}, 3900);
},
[
setBigHudText,
setBigLetterOffSetXCoeff,
setBigLetterPosX,
setBigLetterPosY,
currentBlueOrbHudId,
currentBlueOrbId,
incrementYellowHudTextPosY,
setYellowHudText,
setYellowHudTextOffsetXCoeff,
setYellowHudTextPosX,
setYellowHudTextPosY,
]
);
const animateBigTextWithoutMove = useCallback(
const animateYellowTextWithoutMove = useCallback(
(targetBlueOrbHudId: string, targetBlueOrbId: string) => {
// make current hud big text shrink
setBigLetterOffSetXCoeff(-1);
setYellowHudTextOffsetXCoeff(-1);
setTimeout(() => {
// animate it to new pos x/y
setBigLetterPosX(
blue_orb_huds[targetBlueOrbHudId as keyof typeof blue_orb_huds]
setYellowHudTextPosX(
blue_orb_huds[currentBlueOrbHudId as keyof typeof blue_orb_huds]
.big_text[0]
);
setBigLetterPosY(
blue_orb_huds[targetBlueOrbHudId as keyof typeof blue_orb_huds]
setYellowHudTextPosY(
blue_orb_huds[currentBlueOrbHudId as keyof typeof blue_orb_huds]
.big_text[1]
);
}, 400);
setTimeout(() => {
// set new text according to the node name
setBigHudText(site_a[targetBlueOrbId as keyof typeof site_a].node_name);
setYellowHudText(
site_a[currentBlueOrbId as keyof typeof site_a].node_name
);
}, 1000);
setTimeout(() => {
// unshrink text
setBigLetterOffSetXCoeff(0);
setYellowHudTextOffsetXCoeff(0);
}, 1200);
},
[
setBigHudText,
setBigLetterOffSetXCoeff,
setBigLetterPosX,
setBigLetterPosY,
currentBlueOrbHudId,
currentBlueOrbId,
setYellowHudText,
setYellowHudTextOffsetXCoeff,
setYellowHudTextPosX,
setYellowHudTextPosY,
]
);
@ -98,46 +115,46 @@ const BlueOrbHUDTextStateManager = (props: any) => {
() => ({
moveUp: {
action: "animateWithMove",
animation: animateBigTextWithMove,
bigLetterPosYOffset: -1.5,
actionFunction: animateYellowTextWithMove,
yellowLetterPosYOffset: -1.5,
},
moveDown: {
action: "animateWithMove",
animation: animateBigTextWithMove,
bigLetterPosYOffset: 1.5,
actionFunction: animateYellowTextWithMove,
yellowLetterPosYOffset: 1.5,
},
rotateLeft: {
moveLeft: {
action: "animateWithMove",
animation: animateBigTextWithMove,
bigLetterPosYOffset: 0,
actionFunction: animateYellowTextWithMove,
yellowLetterPosYOffset: 0,
},
rotateRight: {
moveRight: {
action: "animateWithMove",
animation: animateBigTextWithMove,
bigLetterPosYOffset: 0,
actionFunction: animateYellowTextWithMove,
yellowLetterPosYOffset: 0,
},
changeBlueOrbUp: {
action: "animateWithMove",
animation: animateBigTextWithoutMove,
bigLetterPosYOffset: 0,
action: "animateWithoutMove",
actionFunction: animateYellowTextWithoutMove,
yellowLetterPosYOffset: 0,
},
changeBlueOrbDown: {
action: "animateWithMove",
animation: animateBigTextWithoutMove,
bigLetterPosYOffset: 0,
action: "animateWithoutMove",
actionFunction: animateYellowTextWithoutMove,
yellowLetterPosYOffset: 0,
},
changeBlueOrbLeft: {
action: "animateWithMove",
animation: animateBigTextWithoutMove,
bigLetterPosYOffset: 0,
action: "animateWithoutMove",
actionFunction: animateYellowTextWithoutMove,
yellowLetterPosYOffset: 0,
},
changeBlueOrbRight: {
action: "animateWithMove",
animation: animateBigTextWithoutMove,
bigLetterPosYOffset: 0,
action: "animateWithoutMove",
actionFunction: animateYellowTextWithoutMove,
yellowLetterPosYOffset: 0,
},
}),
[animateBigTextWithMove, animateBigTextWithoutMove]
[animateYellowTextWithMove, animateYellowTextWithoutMove]
);
useEffect(() => {
@ -149,26 +166,22 @@ const BlueOrbHUDTextStateManager = (props: any) => {
dispatcherObjects[props.eventState as keyof typeof dispatcherObjects];
if (dispatchedAction.action === "animateWithMove") {
animateBigTextWithMove(
animateYellowTextWithMove(
targetBlueOrbHudId,
targetBlueOrbId,
dispatchedAction.bigLetterPosYOffset
dispatchedAction.yellowLetterPosYOffset
);
} else {
animateBigTextWithoutMove(targetBlueOrbHudId, targetBlueOrbId);
animateYellowTextWithoutMove(targetBlueOrbHudId, targetBlueOrbId);
}
}
}, [
animateBigTextWithMove,
animateBigTextWithoutMove,
animateYellowTextWithMove,
animateYellowTextWithoutMove,
dispatcherObjects,
props.eventState,
props.targetBlueOrbHudId,
props.targetBlueOrbId,
setBigHudText,
setBigLetterOffSetXCoeff,
setBigLetterPosX,
setBigLetterPosY,
]);
return null;

View file

@ -1,9 +1,13 @@
import React, { useEffect, useMemo } from "react";
import { useSetRecoilState } from "recoil";
import { currentBlueOrbAtom } from "../BlueOrb/CurrentBlueOrbAtom";
import { useBlueOrbStore } from "../store";
const BlueOrbStateManager = (props: any) => {
const setCurrentBlueOrb = useSetRecoilState(currentBlueOrbAtom);
// const setCurrentBlueOrb = useSetRecoilState(currentBlueOrbAtom);
const setCurrentBlueOrb = useBlueOrbStore(
(state) => state.setCurrentBlueOrbId
);
// this one is repetitive for now but ill leave them separated
// in case it comes in handy later on
@ -11,8 +15,8 @@ const BlueOrbStateManager = (props: any) => {
() => ({
moveUp: { duration: 3903.704 },
moveDown: { duration: 3903.704 },
rotateLeft: { duration: 3903.704 },
rotateRight: { duration: 3903.704 },
moveLeft: { duration: 3903.704 },
moveRight: { duration: 3903.704 },
changeBlueOrbUp: { duration: 0 },
changeBlueOrbDown: { duration: 0 },
changeBlueOrbLeft: { duration: 0 },
@ -26,10 +30,7 @@ const BlueOrbStateManager = (props: any) => {
const dispatchedAction =
dispatcherObjects[props.eventState as keyof typeof dispatcherObjects];
// disable glow on current blue orb
setCurrentBlueOrb("");
// set new one after animation ends
// set new one after action ends
setTimeout(() => {
setCurrentBlueOrb(props.targetBlueOrbId);
}, dispatchedAction.duration);

View file

@ -1,8 +1,7 @@
import React, { useCallback, useEffect, useMemo, useState } from "react";
import { useRecoilValue, useSetRecoilState } from "recoil";
import { useSetRecoilState } from "recoil";
import {
currentBlueOrbAnimatingAtom,
currentBlueOrbAtom,
currentBlueOrbPosXAtom,
currentBlueOrbPosYAtom,
currentBlueOrbPosZAtom,
@ -11,13 +10,13 @@ import blue_orb_directions from "../../resources/blue_orb_directions.json";
import blue_orb_positions from "../../resources/blue_orb_positions.json";
import level_y_values from "../../resources/level_y_values.json";
import site_a from "../../resources/site_a.json";
import { lainMovingAtom } from "../Lain/LainAtom";
import SiteStateManager from "./SiteStateManager";
import MiddleRingStateManager from "./MiddleRingStateManager";
import LainStateManager from "./LainStateManager";
import BlueOrbStateManager from "./BlueOrbStateManager";
import BlueOrbHUDStateManager from "./BlueOrbHUDStateManager";
import BlueOrbHUDTextStateManager from "./BlueOrbHUDTextStateManager";
import { useBlueOrbStore } from "../store";
type KeyCodeAssociations = {
[keyCode: number]: string;
@ -41,7 +40,7 @@ type BlueOrbStateData = {
const InputHandler = () => {
const [eventState, setEventState] = useState<string>();
const currentBlueOrb = useRecoilValue(currentBlueOrbAtom);
const currentBlueOrb = useBlueOrbStore((state) => state.blueOrbId);
const setCurrentBlueOrbAnimating = useSetRecoilState(
currentBlueOrbAnimatingAtom
);
@ -54,12 +53,12 @@ const InputHandler = () => {
const [inputCooldown, setInputCooldown] = useState(false);
const moveAndRotationEvents = useMemo(
const moveEvents = useMemo(
() => ({
up: "moveUp",
down: "moveDown",
left: "rotateLeft",
right: "rotateRight",
left: "moveLeft",
right: "moveRight",
}),
[]
);
@ -117,10 +116,7 @@ const InputHandler = () => {
});
if (moveOrRotate) {
const event =
moveAndRotationEvents[
keyPress as keyof typeof moveAndRotationEvents
];
const event = moveEvents[keyPress as keyof typeof moveEvents];
setEventState(event);
} else {
@ -160,7 +156,7 @@ const InputHandler = () => {
[
inputCooldown,
currentBlueOrb,
moveAndRotationEvents,
moveEvents,
blueOrbChangeEvents,
setCurrentBlueOrbPosX,
setCurrentBlueOrbPosY,

View file

@ -1,6 +1,6 @@
import React, { useEffect, useMemo } from "react";
import { useSetRecoilState } from "recoil";
import { lainMoveStateAtom, lainMovingAtom } from "../Lain/LainAtom";
import { lainMoveStateAtom } from "../Lain/LainAtom";
import {
LainMoveDown,
LainMoveLeft,
@ -11,15 +11,14 @@ import {
} from "../Lain/Lain";
const LainStateManager = (props: any) => {
const setLainMoving = useSetRecoilState(lainMovingAtom);
const setLainMoveState = useSetRecoilState(lainMoveStateAtom);
const dispatcherObjects = useMemo(
() => ({
moveUp: { animation: <LainMoveUp />, duration: 3903.704 },
moveDown: { animation: <LainMoveDown />, duration: 3903.704 },
rotateLeft: { animation: <LainMoveLeft />, duration: 3903.704 },
rotateRight: { animation: <LainMoveRight />, duration: 3903.704 },
moveUp: { action: <LainMoveUp />, duration: 3903.704 },
moveDown: { action: <LainMoveDown />, duration: 3903.704 },
moveLeft: { action: <LainMoveLeft />, duration: 3903.704 },
moveRight: { action: <LainMoveRight />, duration: 3903.704 },
}),
[]
);
@ -30,14 +29,14 @@ const LainStateManager = (props: any) => {
dispatcherObjects[props.eventState as keyof typeof dispatcherObjects];
if (dispatchedAction) {
setLainMoveState(dispatchedAction.animation);
setLainMoveState(dispatchedAction.action);
setTimeout(() => {
setLainMoveState(<LainStanding />);
}, dispatchedAction.duration);
}
}
}, [dispatcherObjects, props.eventState, setLainMoveState, setLainMoving]);
}, [dispatcherObjects, props.eventState, setLainMoveState]);
return null;
};

View file

@ -178,10 +178,10 @@ const MiddleRingStateManager = (props: any) => {
const dispatcherObjects = useMemo(
() => ({
moveUp: { animation: moveMiddleRingUp },
moveDown: { animation: moveMiddleRingDown },
rotateLeft: { animation: rotateMiddleRingLeft },
rotateRight: { animation: rotateMiddleRingRight },
moveUp: { action: moveMiddleRingUp },
moveDown: { action: moveMiddleRingDown },
moveLeft: { action: rotateMiddleRingLeft },
moveRight: { action: rotateMiddleRingRight },
}),
[
moveMiddleRingDown,
@ -197,7 +197,7 @@ const MiddleRingStateManager = (props: any) => {
dispatcherObjects[props.eventState as keyof typeof dispatcherObjects];
if (dispatchedAction) {
dispatchedAction.animation();
dispatchedAction.action();
}
}
}, [

View file

@ -13,12 +13,16 @@ const SiteStateManager = (props: any) => {
const dispatcherObjects = useMemo(
() => ({
moveUp: { action: "move", value: -1.5 },
moveDown: { action: "move", value: 1.5 },
rotateLeft: { action: "rotate", value: Math.PI / 4 },
rotateRight: { action: "rotate", value: -Math.PI / 4 },
moveUp: { action: setSitePosY, value: -1.5, actionDelay: 1300 },
moveDown: { action: setSitePosY, value: 1.5, actionDelay: 1300 },
moveLeft: { action: setSiteRotY, value: Math.PI / 4, actionDelay: 1100 },
moveRight: {
action: setSiteRotY,
value: -Math.PI / 4,
actionDelay: 1100,
},
}),
[]
[setSitePosY, setSiteRotY]
);
useEffect(() => {
@ -27,20 +31,14 @@ const SiteStateManager = (props: any) => {
dispatcherObjects[props.eventState as keyof typeof dispatcherObjects];
if (dispatchedAction) {
switch (dispatchedAction.action) {
case "rotate":
setTimeout(() => {
setSiteRotY((prev: number) => prev + dispatchedAction.value);
}, 1100);
break;
case "move":
setTimeout(() => {
setSitePosY((prev: number) => prev + dispatchedAction.value);
}, 1300);
break;
default:
break;
}
setIsSiteYChanging(true);
setTimeout(() => {
dispatchedAction.action(
(prev: number) => prev + dispatchedAction.value
);
}, dispatchedAction.actionDelay);
setTimeout(() => {
setIsSiteYChanging(false);
}, 3000);

View file

@ -10,7 +10,7 @@ import standingSpriteSheet from "../../static/sprites/standing.png";
import introSpriteSheet from "../../static/sprites/intro.png";
import throwBlueOrbSpriteSheet from "../../static/sprites/throw_blue_orb.png";
import { useRecoilValue } from "recoil";
import { lainMoveStateAtom, lainMovingAtom } from "./LainAtom";
import { lainMoveStateAtom } from "./LainAtom";
type LainConstructorProps = {
sprite: string;

View file

@ -1,11 +1,6 @@
import { atom } from "recoil";
import React from "react";
export const lainMovingAtom = atom({
key: "lainMovingAtom",
default: false,
});
export const lainMoveStateAtom = atom({
key: "lainMoveStateAtom",
default: <></>,

View file

@ -2,12 +2,12 @@ import { a, useSpring } from "@react-spring/three";
import { OrbitControls } from "drei";
import React, { Suspense, useEffect } from "react";
import Site from "../Site/Site";
import Lain from "../Lain/Lain";
import Lain, { LainStanding } from "../Lain/Lain";
import Lights from "../Lights";
import OrthoCamera from "../OrthoCamera/OrthoCamera";
import Preloader from "../Preloader";
import { useRecoilValue, useSetRecoilState } from "recoil";
import { lainMoveStateAtom, lainMovingAtom } from "../Lain/LainAtom";
import { lainMoveStateAtom } from "../Lain/LainAtom";
import InputHandler from "../InputHandler/InputHandler";
import MainSceneIntro from "./MainSceneIntro";
import {
@ -20,7 +20,6 @@ import MiddleRing from "../MiddleRing/MiddleRing";
import Starfield from "../Starfield/Starfield";
const MainScene = () => {
const setLainMoving = useSetRecoilState(lainMovingAtom);
const setLainMoveState = useSetRecoilState(lainMoveStateAtom);
const mainGroupPosY = useRecoilValue(mainGroupPosYAtom);
const mainGroupPosZ = useRecoilValue(mainGroupPosZAtom);
@ -37,11 +36,14 @@ const MainScene = () => {
config: { duration: 1500 },
});
useEffect(() => {
setLainMoveState(<LainStanding />);
}, [setLainMoveState]);
// set lain intro spritesheet before the page loads fully
useEffect(() => {
// setLainMoving(true);
// setLainMoveState(<LainIntro />);
}, [setLainMoveState, setLainMoving]);
}, [setLainMoveState]);
return (
<perspectiveCamera position-z={3}>

View file

@ -1,13 +1,13 @@
import React, { memo, useEffect } from "react";
import { useSetRecoilState } from "recoil";
import { hudActiveAtom, hudVisibilityAtom } from "../HUD/HUDElementAtom";
import { hudVisibilityAtom } from "../HUD/HUDElementAtom";
import {
mainGroupPosYAtom,
mainGroupPosZAtom,
mainGroupRotXAtom,
} from "./MainGroupAtom";
import { LainStanding } from "../Lain/Lain";
import { lainMoveStateAtom, lainMovingAtom } from "../Lain/LainAtom";
import { lainMoveStateAtom } from "../Lain/LainAtom";
import { orbVisibilityAtom } from "../Orb/OrbAtom";
import {
introStarfieldVisibilityAtom,
@ -15,19 +15,19 @@ import {
mainStarfieldVisibilityAtom,
} from "../Starfield/StarfieldAtom";
import { grayPlanesVisibleAtom } from "../GrayPlanes/GrayPlanesAtom";
import { useBlueOrbStore } from "../store";
// ghost component to manipulate the intro animation for the main scene.
// ghost component to manipulate the intro action for the main scene.
// we separate this file because having something like this
// inside <Suspense> tags makes it behave in a more stable manner
// by waiting for the components to load and synchronously calling the functions.
const MainSceneIntro = memo(() => {
const setHudActive = useSetRecoilState(hudActiveAtom);
const toggleHud = useBlueOrbStore((state) => state.toggleHud);
const setHudVisible = useSetRecoilState(hudVisibilityAtom);
const setOrbVisible = useSetRecoilState(orbVisibilityAtom);
const setLainMoving = useSetRecoilState(lainMovingAtom);
const setLainMoveState = useSetRecoilState(lainMoveStateAtom);
const setIntroStarfieldVisible = useSetRecoilState(
@ -60,10 +60,9 @@ const MainSceneIntro = memo(() => {
setMainStarfieldBoostVal(0);
}, 2800);
setHudActive((prev: number) => Number(!prev));
toggleHud();
setTimeout(() => {
setLainMoving(false);
setLainMoveState(<LainStanding />);
setOrbVisible(true);
@ -71,8 +70,7 @@ const MainSceneIntro = memo(() => {
setIntroStarfieldVisible(false);
setHudActive((prev: number) => Number(!prev));
toggleHud();
setTimeout(() => {
document.getElementsByTagName("canvas")[0].className = "hub-background";
}, 300);
@ -84,12 +82,11 @@ const MainSceneIntro = memo(() => {
setHudVisible,
setOrbVisible,
setIntroStarfieldVisible,
setHudActive,
setMainGroupRotX,
setMainGroupPosZ,
setMainGroupPosY,
setLainMoving,
setLainMoveState,
toggleHud,
]);
return <></>;

View file

@ -5,12 +5,12 @@ import level_y_values from "../../resources/level_y_values.json";
import blue_orb_positions from "../../resources/blue_orb_positions.json";
import BlueOrb from "../BlueOrb/BlueOrb";
import { useRecoilValue } from "recoil";
import { currentBlueOrbAtom } from "../BlueOrb/CurrentBlueOrbAtom";
import { useSpring, a } from "@react-spring/three";
import { a, useSpring } from "@react-spring/three";
import { sitePosYAtom, siteRotYAtom } from "./SiteAtom";
import { useBlueOrbStore } from "../store";
const Site = memo(() => {
const currentBlueOrb = useRecoilValue(currentBlueOrbAtom);
const currentBlueOrbId = useBlueOrbStore((state) => state.blueOrbId);
const siteRotY = useRecoilValue(siteRotYAtom);
const sitePosY = useRecoilValue(sitePosYAtom);
@ -51,7 +51,7 @@ const Site = memo(() => {
]
}
key={(blueOrb as any)[1]["node_name"]}
active={(blueOrb as any)[0] === currentBlueOrb}
active={(blueOrb as any)[0] === currentBlueOrbId}
level={(blueOrb as any)[0].substr(0, 2)}
/>
);

View file

@ -9,6 +9,7 @@ import { a, useSpring } from "@react-spring/three";
import React from "react";
import { useRecoilValue } from "recoil";
import { bigLetterOffsetXCoeffAtom } from "./TextRendererAtom";
import { useBlueOrbStore } from "../store";
type LetterProps = {
color: string;
@ -36,7 +37,9 @@ type FontData = {
};
export const BigLetter = (props: LetterProps) => {
const bigLetterOffsetXCoeff = useRecoilValue(bigLetterOffsetXCoeffAtom);
const yellowTextOffsetXCoeff = useBlueOrbStore(
(state) => state.yellowHudTextOffsetXCoeff
);
const colorToTexture = (color: string) => {
return ({ orange: orangeFont, yellow: yellowFont } as ColorToTexture)[
@ -105,10 +108,10 @@ export const BigLetter = (props: LetterProps) => {
const textRendererState = useSpring({
letterOffsetXCoeff:
props.kerningOffset === 0
? props.kerningOffset + props.kerningOffset * bigLetterOffsetXCoeff
? props.kerningOffset + props.kerningOffset * yellowTextOffsetXCoeff
: props.kerningOffset +
0.3 +
(props.kerningOffset + 0.3) * bigLetterOffsetXCoeff,
(props.kerningOffset + 0.3) * yellowTextOffsetXCoeff,
config: { duration: 200 },
});
@ -167,7 +170,7 @@ export const MediumLetter = (props: LetterProps) => {
2: 0.297,
3: 0.238,
4: 0.18,
5: 1
5: 1,
};
const letterData = (medium_font_json as FontData)["glyphs"][props.letter];

39
src/components/store.ts Normal file
View file

@ -0,0 +1,39 @@
import create from "zustand";
type HUDState = {
blueOrbId: string;
hudId: string;
hudActive: number;
yellowHudText: string;
yellowHudTextPosY: number;
yellowHudTextPosX: number;
yellowHudTextOffsetXCoeff: number;
setCurrentBlueOrbId: (to: string) => void;
setCurrentHudId: (to: string) => void;
toggleHud: () => void;
setYellowHudText: (to: string) => void;
incrementYellowHudTextPosY: (by: number) => void;
setYellowHudTextPosY: (to: number) => void;
setYellowHudTextPosX: (to: number) => void;
setYellowHudTextOffsetXCoeff: (to: number) => void;
};
export const useBlueOrbStore = create<HUDState>((set) => ({
blueOrbId: "0422",
hudId: "fg_hud_1",
hudActive: 1,
yellowHudText: "",
yellowHudTextPosY: 0,
yellowHudTextPosX: 0,
yellowHudTextOffsetXCoeff: 0,
setCurrentBlueOrbId: (to) => set(() => ({ blueOrbId: to })),
setCurrentHudId: (to) => set(() => ({ hudId: to })),
toggleHud: () => set((state) => ({ hudActive: Number(!state.hudActive) })),
setYellowHudText: (to) => set(() => ({ yellowHudText: to })),
incrementYellowHudTextPosY: (by) =>
set((state) => ({ yellowHudTextPosY: state.yellowHudTextPosY + by })),
setYellowHudTextPosY: (to) => set(() => ({ yellowHudTextPosY: to })),
setYellowHudTextPosX: (to) => set(() => ({ yellowHudTextPosY: to })),
setYellowHudTextOffsetXCoeff: (to) =>
set(() => ({ yellowHudTextOffsetXCoeff: to })),
}));