more progress on the pause animation

This commit is contained in:
ad044 2020-12-02 20:50:12 +04:00
parent 00ffcdc710
commit 7db4906db1
9 changed files with 455 additions and 135 deletions

View file

@ -1,11 +1,16 @@
import React, { useCallback, useMemo, useRef, useState } from "react";
import pauseGrayBoxes from "../../static/sprite/pause_gray_boxes.png";
import React, { useCallback, useMemo } from "react";
import * as THREE from "three";
import { useFrame, useLoader } from "react-three-fiber";
import BigLetter from "../TextRenderer/BigLetter";
import PauseSquare from "./PauseSquare";
import StaticBigLetter from "../TextRenderer/StaticBigLetter";
import { usePauseStore } from "../../store";
const Pause = () => {
const grayBoxesTex = useLoader(THREE.TextureLoader, pauseGrayBoxes);
const componentMatrixIdx = usePauseStore((state) => state.componentMatrixIdx);
const activeComponent = usePauseStore(
useCallback((state) => state.componentMatrix[componentMatrixIdx], [
componentMatrixIdx,
])
);
const generateSqaureGeom = useCallback((row: number, square: number) => {
const geometry = new THREE.PlaneBufferGeometry();
@ -34,147 +39,178 @@ const Pause = () => {
<group position={[-1, -0.8, 0]} scale={[0.9, 0.9, 0]}>
{[0, 1, 2, 3, 2, 1, 0].map((row: number, rowIdx: number) =>
[0, 1, 2, 3, 4, 5, 6].map((col: number) => {
if (rowIdx === 5 && col > 0) {
if (rowIdx === 5 && col > 0 && col < 5) {
return col === 1 ? (
<>
<group scale={[0.2, 0.2, 0]} position={[0.1, 1.8, 0]}>
<BigLetter
color={"white"}
letter={"L"}
letterIdx={col}
yellowTextOffsetXCoeff={col / 7}
key={col}
/>
</group>
)
</>
) : (
<mesh
geometry={squareGeoms[row][col]}
position={[col / 2.8, rowIdx / 2.8, 0]}
scale={[col > 3 ? -0.25 : 0.25, rowIdx <= 3 ? -0.25 : 0.25, 0]}
<StaticBigLetter
color={"white"}
letter={"L"}
letterIdx={col}
position={[0.35, 1.8, 0]}
scale={[0.25, 0.25, 0.25]}
active={!(activeComponent === "load")}
key={col}
>
<meshBasicMaterial
attach="material"
map={grayBoxesTex}
side={
(col > 3 && rowIdx <= 3) || (col <= 3 && rowIdx > 3)
? THREE.FrontSide
: THREE.BackSide
}
/>
</mesh>
/>
) : (
<PauseSquare
geometry={squareGeoms[row][col]}
rowIdx={rowIdx}
colIdx={col}
active={!(activeComponent === "load")}
key={col}
/>
);
} else if (rowIdx === 4 && col === 4) {
return (
<>
<group scale={[0.2, 0.2, 0]} position={[0.1, 1.45, 0]}>
<BigLetter
color={"white"}
letter={"A"}
letterIdx={col}
yellowTextOffsetXCoeff={col / 7}
key={col}
/>
</group>
</>
} else if (rowIdx === 4 && col > 4 && col < 7) {
return col === 5 ? (
<StaticBigLetter
color={"white"}
letter={"A"}
letterIdx={col}
position={[1.78, 1.43, 0]}
scale={[0.25, 0.25, 0]}
active={!(activeComponent === "about")}
key={col}
/>
) : (
<PauseSquare
geometry={squareGeoms[row][col]}
rowIdx={rowIdx}
colIdx={col}
active={!(activeComponent === "about")}
key={col}
/>
);
} else if (rowIdx === 3 && col === 3) {
return (
<>
<group scale={[0.2, 0.2, 0]} position={[0.12, 1.05, 0]}>
<BigLetter
color={"white"}
letter={"C"}
letterIdx={col}
yellowTextOffsetXCoeff={col / 7}
key={col}
/>
</group>
</>
} else if (rowIdx === 3 && col > 2 && col < 7) {
return col === 3 ? (
<StaticBigLetter
color={"white"}
letter={"C"}
letterIdx={col}
position={[1.05, 1.07, 0]}
scale={[0.25, 0.25, 0]}
active={!(activeComponent === "change")}
key={col}
/>
) : (
<PauseSquare
geometry={squareGeoms[row][col]}
rowIdx={rowIdx}
colIdx={col}
active={!(activeComponent === "change")}
key={col}
/>
);
} else if (rowIdx === 1 && col > 0 && col < 5) {
return col === 1 ? (
<StaticBigLetter
color={"white"}
letter={"S"}
letterIdx={col}
position={[0.35, 0.35, 0]}
scale={[0.25, 0.25, 0]}
active={!(activeComponent === "save")}
key={col}
/>
) : (
<PauseSquare
geometry={squareGeoms[row][col]}
rowIdx={rowIdx}
colIdx={col}
active={!(activeComponent === "save")}
key={col}
/>
);
} else if (rowIdx === 0 && col > 4 && col < 7) {
return col === 5 ? (
<StaticBigLetter
color={"white"}
letter={"E"}
letterIdx={col}
position={[1.78, 0, 0]}
scale={[0.25, 0.25, 0]}
active={!(activeComponent === "exit")}
key={col}
/>
) : (
<PauseSquare
geometry={squareGeoms[row][col]}
rowIdx={rowIdx}
colIdx={col}
active={!(activeComponent === "exit")}
key={col}
/>
);
} else {
return (
<mesh
<PauseSquare
geometry={squareGeoms[row][col]}
position={[col / 2.8, rowIdx / 2.8, 0]}
scale={[col > 3 ? -0.25 : 0.25, rowIdx <= 3 ? -0.25 : 0.25, 0]}
rowIdx={rowIdx}
colIdx={col}
key={col}
>
<meshBasicMaterial
attach="material"
map={grayBoxesTex}
side={
(col > 3 && rowIdx <= 3) || (col <= 3 && rowIdx > 3)
? THREE.FrontSide
: THREE.BackSide
}
/>
</mesh>
active={true}
/>
);
}
})
)}
{/*{"Load".split("").map((letter, idx) => (*/}
{/* <group scale={[0.2, 0.2, 0]} position={[0.35 + idx / 8, 1.8, 0]}>*/}
{/* <BigLetter*/}
{/* color={idx > 0 ? "yellow" : "orange"}*/}
{/* letter={letter}*/}
{/* letterIdx={idx}*/}
{/* yellowTextOffsetXCoeff={0}*/}
{/* key={idx}*/}
{/* />*/}
{/* </group>*/}
{/*))}*/}
{"Load".split("").map((letter, idx) => (
<StaticBigLetter
color={idx > 0 ? "yellow" : "orange"}
letter={letter}
letterIdx={idx}
key={idx}
position={[0.35 + idx / 2.8, 1.8, 0]}
scale={[0.25, 0.25, 0.25]}
active={activeComponent === "load"}
/>
))}
{/*{"About".split("").map((letter, idx) => (*/}
{/* <group scale={[0.2, 0.2, 0]} position={[1.4 + idx / 8, 1.45, 0]}>*/}
{/* <BigLetter*/}
{/* color={idx > 0 ? "yellow" : "orange"}*/}
{/* letter={letter}*/}
{/* letterIdx={idx}*/}
{/* yellowTextOffsetXCoeff={0}*/}
{/* key={idx}*/}
{/* />*/}
{/* </group>*/}
{/*))}*/}
{"About".split("").map((letter, idx) => (
<StaticBigLetter
color={idx > 0 ? "yellow" : "orange"}
letter={letter}
letterIdx={idx}
position={[1.78 + idx / 2.8, 1.43, 0]}
scale={[0.25, 0.25, 0]}
active={activeComponent === "about"}
key={idx}
/>
))}
{/*{"Change".split("").map((letter, idx) => (*/}
{/* <group scale={[0.2, 0.2, 0]} position={[1 + idx / 6, 1.05, 0]}>*/}
{/* <BigLetter*/}
{/* color={idx > 0 ? "yellow" : "orange"}*/}
{/* letter={letter}*/}
{/* letterIdx={idx}*/}
{/* yellowTextOffsetXCoeff={0}*/}
{/* key={idx}*/}
{/* />*/}
{/* </group>*/}
{/*))}*/}
{"Change".split("").map((letter, idx) => (
<StaticBigLetter
color={idx > 0 ? "yellow" : "orange"}
letter={letter}
letterIdx={idx}
position={[1.05 + idx / 2.8, 1.07, 0]}
scale={[0.25, 0.25, 0]}
active={activeComponent === "change"}
key={idx}
/>
))}
{/*{"Save".split("").map((letter, idx) => (*/}
{/* <group scale={[0.2, 0.2, 0]} position={[0.3 + idx / 7, 0.35, 0]}>*/}
{/* <BigLetter*/}
{/* color={idx > 0 ? "yellow" : "orange"}*/}
{/* letter={letter}*/}
{/* letterIdx={idx}*/}
{/* yellowTextOffsetXCoeff={0}*/}
{/* key={idx}*/}
{/* />*/}
{/* </group>*/}
{/*))}*/}
{"Save".split("").map((letter, idx) => (
<StaticBigLetter
color={idx > 0 ? "yellow" : "orange"}
letter={letter}
letterIdx={idx}
position={[0.35 + idx / 2.8, 0.35, 0]}
scale={[0.25, 0.25, 0]}
active={activeComponent === "save"}
key={idx}
/>
))}
{/*{"Exit".split("").map((letter, idx) => (*/}
{/* <group scale={[0.2, 0.2, 0]} position={[1.75 + idx / 8, 0, 0]}>*/}
{/* <BigLetter*/}
{/* color={idx > 0 ? "yellow" : "orange"}*/}
{/* letter={letter}*/}
{/* letterIdx={idx}*/}
{/* yellowTextOffsetXCoeff={0}*/}
{/* key={idx}*/}
{/* />*/}
{/* </group>*/}
{/*))}*/}
{"Exit".split("").map((letter, idx) => (
<StaticBigLetter
color={idx > 0 ? "yellow" : "orange"}
letter={letter}
letterIdx={idx}
position={[1.78 + idx / 2.8, 0, 0]}
scale={[0.25, 0.25, 0]}
key={idx}
active={activeComponent === "exit"}
/>
))}
</group>
);
};

View file

@ -0,0 +1,86 @@
import React, { useEffect, useMemo, useState } from "react";
import * as THREE from "three";
import { useLoader } from "react-three-fiber";
import pauseGrayBoxes from "../../static/sprite/pause_gray_boxes.png";
import { a, useSpring } from "@react-spring/three";
type PauseSquareProps = {
colIdx: number;
rowIdx: number;
geometry: THREE.PlaneBufferGeometry;
active: boolean;
};
const PauseSquare = (props: PauseSquareProps) => {
const grayBoxesTex = useLoader(THREE.TextureLoader, pauseGrayBoxes);
const [intro, setIntro] = useState(true);
const [introAnimToggle, setIntroAnimToggle] = useState(false);
const { introToggle } = useSpring({
introToggle: Number(introAnimToggle),
config: { duration: 200 },
});
const { toggle } = useSpring({
toggle: Number(props.active),
config: { duration: 200 },
});
const rotX = toggle.to([0, 1], [-Math.PI, 0]);
const rotY = toggle.to([0, 1], [Math.PI / 2, 0]);
const introRotX = introToggle.to([0, 1], [0, 2 * Math.PI]);
const introRotY = introToggle.to([0, 1], [0, 2 * Math.PI]);
useEffect(() => {
setTimeout(() => {
setIntroAnimToggle(true);
}, (props.rowIdx + props.colIdx) * 100);
setTimeout(() => {
setIntro(false);
}, 5000);
}, [props.colIdx, props.rowIdx]);
const side = useMemo(() => {
if (intro) return THREE.DoubleSide;
else {
if (
(props.colIdx > 3 && props.rowIdx <= 3) ||
(props.colIdx <= 3 && props.rowIdx > 3)
) {
return THREE.FrontSide;
} else {
return THREE.BackSide;
}
}
}, [intro, props.colIdx, props.rowIdx]);
return (
<a.mesh
geometry={props.geometry}
position={[props.colIdx / 2.8, props.rowIdx / 2.8, 0]}
scale={[
props.colIdx > 3 ? -0.25 : 0.25,
props.rowIdx <= 3 ? -0.25 : 0.25,
0,
]}
rotation-x={intro ? introRotX : rotX}
rotation-y={intro ? introRotY : rotY}
>
<meshBasicMaterial
attach="material"
map={grayBoxesTex}
side={
(props.colIdx > 3 && props.rowIdx <= 3) ||
(props.colIdx <= 3 && props.rowIdx > 3)
? THREE.FrontSide
: THREE.BackSide
}
/>
</a.mesh>
);
};
export default PauseSquare;

View file

@ -11,7 +11,7 @@ const BigLetter = (props: {
color: string;
letter: string;
letterIdx: number;
yellowTextOffsetXCoeff: number;
xOffsetCoeff: number;
}) => {
const colorToTexture = (color: string) => {
const colorTexture = {
@ -93,7 +93,7 @@ const BigLetter = (props: {
letterOffsetXCoeff:
props.letterIdx +
0.3 +
(props.letterIdx + 0.3) * props.yellowTextOffsetXCoeff,
(props.letterIdx + 0.3) * props.xOffsetCoeff,
config: { duration: 200 },
});

View file

@ -0,0 +1,123 @@
import orangeFont from "../../static/sprite/orange_font_texture.png";
import yellowFont from "../../static/sprite/yellow_font_texture.png";
import whiteFont from "../../static/sprite/white_and_green_texture.png";
import * as THREE from "three";
import { useLoader } from "react-three-fiber";
import orange_font_json from "../../resources/font_data/big_font.json";
import { a, Interpolation, SpringValue, useSpring } from "@react-spring/three";
import React, { useMemo } from "react";
const StaticBigLetter = (props: {
color: string;
letter: string;
letterIdx: number;
position: number[];
scale: number[];
active: boolean;
}) => {
const { toggle } = useSpring({
toggle: Number(props.active),
config: { duration: 200 },
});
const rotX = toggle.to([0, 1], [-Math.PI, 0]);
const rotY = toggle.to([0, 1], [Math.PI / 2, 0]);
const colorToTexture = (color: string) => {
const colorTexture = {
orange: orangeFont,
yellow: yellowFont,
white: whiteFont,
};
return colorTexture[color as keyof typeof colorTexture];
};
// first letter in big font is always orange in this case so make it orange if so. else,
// run through the function.
const color =
props.letterIdx === 0 ? orangeFont : colorToTexture(props.color);
const colorTexture: THREE.Texture = useLoader(THREE.TextureLoader, color);
// i have yet to figure out a genrealizable way of
// calculating the y offset, this shit will do for now
// also, we dont have all the lines since i dont need them yet.
// also, baseline offsets dont work properly since i dont need them yet either
// should be trivial to calculate though, im just lazy
const getLineNum = (letter: string) => {
const lineOne = "ABCDEFGHIJKLMNOPQ";
const lineTwo = "RSTUVWXYZ01234567";
const lineThree = "89abcdefghijklmnopqrs";
if (letter === " ") return 5;
if (lineOne.includes(letter)) {
return 1;
} else if (lineTwo.includes(letter)) {
return 2;
} else if (lineThree.includes(letter)) {
return 3;
} else {
return 4;
}
};
const lineYOffsets = useMemo(
() => ({
1: 0.884,
2: 0.765,
3: 0.648,
4: 0.47,
5: 1,
}),
[]
);
const letterData =
orange_font_json.glyphs[
props.letter as keyof typeof orange_font_json.glyphs
];
const geom = useMemo(() => {
const geometry = new THREE.PlaneBufferGeometry();
const uvAttribute = geometry.attributes.uv;
for (let i = 0; i < uvAttribute.count; i++) {
let u = uvAttribute.getX(i);
let v = uvAttribute.getY(i);
u = (u * letterData[2]) / 256 + letterData[0] / 256;
v =
(v * letterData[3]) / 136 +
lineYOffsets[getLineNum(props.letter)] -
letterData[4] / 136;
uvAttribute.setXY(i, u, v);
}
return geometry;
}, [letterData, lineYOffsets, props.letter]);
return (
<a.mesh
position={[
props.position[0],
-letterData[4] / 50 + props.position[1],
props.position[2],
]}
scale={props.scale as [number, number, number]}
geometry={geom}
rotation-x={rotX}
rotation-y={rotY}
>
<meshBasicMaterial
map={colorTexture}
attach="material"
transparent={true}
/>
</a.mesh>
);
};
export default StaticBigLetter;

View file

@ -52,7 +52,7 @@ const YellowTextRenderer = (props: { visible?: boolean }) => {
>
<BigLetter
color={color}
yellowTextOffsetXCoeff={0}
xOffsetCoeff={0}
letter={textArrRef.current[idx]}
letterIdx={idx}
key={idx}
@ -69,7 +69,7 @@ const YellowTextRenderer = (props: { visible?: boolean }) => {
>
<BigLetter
color={color}
yellowTextOffsetXCoeff={transformRef.current.xOffset}
xOffsetCoeff={transformRef.current.xOffset}
letter={textArrRef.current[idx]}
letterIdx={idx}
key={idx}

View file

@ -13,6 +13,7 @@ import {
useMediaStore,
useMediaWordStore,
useNodeStore,
usePauseStore,
useSceneStore,
useSiteStore,
useSSknStore,
@ -32,6 +33,7 @@ import handleSSknSceneEvent from "../ssknSceneEventHandler";
import BootAuthorizeUserManager from "./BootAuthorizeUserManager";
import LevelSelectionManager from "./LevelSelectionManager";
import SubsceneManager from "./SubsceneManager";
import PauseComponentManager from "./PauseComponentManager";
const getKeyCodeAssociation = (keyCode: number): string => {
const keyCodeAssocs = {
@ -62,6 +64,7 @@ const EventManager = () => {
const levelSelectionIdx = useLevelSelectionStore(
(state) => state.selectedLevelIdx
);
const pauseMatrixIdx = usePauseStore((state) => state.componentMatrixIdx);
// media scene
const mediaComponentMatrixIndices = useMediaStore(
@ -142,6 +145,7 @@ const EventManager = () => {
nodeMatrixIndices: nodeMatrixIndices,
activeLevel: activeLevel,
levelSelectionIdx: levelSelectionIdx,
pauseMatrixIdx: pauseMatrixIdx,
});
break;
case "media":
@ -189,6 +193,7 @@ const EventManager = () => {
levelSelectionIdx,
mainSubscene,
nodeMatrixIndices,
pauseMatrixIdx,
rightSideComponentIdx,
siteTransformState,
wordPosStateIdx,
@ -221,6 +226,7 @@ const EventManager = () => {
<BootAuthorizeUserManager eventState={eventState!} />
<LevelSelectionManager eventState={eventState!} />
<SubsceneManager eventState={eventState!} />
<PauseComponentManager eventState={eventState!} />
</>
);
};

View file

@ -0,0 +1,42 @@
import { useCallback, useEffect } from "react";
import { StateManagerProps } from "./EventManager";
import { usePauseStore } from "../../store";
const PauseComponentManager = (props: StateManagerProps) => {
const setComponentMatrixIdx = usePauseStore(
(state) => state.setComponentMatrixIdx
);
const dispatchObject = useCallback(
(event: string, newComponentMatrixIdx: number) => {
switch (event) {
case "pause_up":
case "pause_down":
return {
action: setComponentMatrixIdx,
value: newComponentMatrixIdx,
};
}
},
[setComponentMatrixIdx]
);
useEffect(() => {
if (props.eventState) {
const eventAction = props.eventState.event;
const newComponentMatrixIdx = props.eventState.newPauseMatrixIdx;
const dispatchedObject = dispatchObject(
eventAction,
newComponentMatrixIdx
);
if (dispatchedObject) {
dispatchedObject.action(dispatchedObject.value as never);
}
}
}, [dispatchObject, props.eventState]);
return null;
};
export default PauseComponentManager;

View file

@ -23,6 +23,7 @@ const handleMainSceneEvent = (gameContext: any) => {
const keyPress = gameContext.keyPress;
const subscene = gameContext.mainSubscene;
const levelSelectionIdx = gameContext.levelSelectionIdx;
const pauseMatrixIdx = gameContext.pauseMatrixIdx;
const nodeColIdx = gameContext.nodeMatrixIndices.colIdx;
const nodeRowIdx = gameContext.nodeMatrixIndices.rowIdx;
@ -198,6 +199,21 @@ const handleMainSceneEvent = (gameContext: any) => {
};
}
}
} else if (subscene === "pause") {
switch (keyPress) {
case "UP":
if (pauseMatrixIdx - 1 < 0) break;
return {
event: "pause_up",
newPauseMatrixIdx: pauseMatrixIdx - 1,
};
case "DOWN":
if (pauseMatrixIdx + 1 > 4) break;
return {
event: "pause_down",
newPauseMatrixIdx: pauseMatrixIdx + 1,
};
}
}
};

View file

@ -3,6 +3,12 @@ import { combine } from "zustand/middleware";
import * as THREE from "three";
import authorize_user_letters from "./resources/authorize_user_letters.json";
type PauseState = {
componentMatrix: string[];
componentMatrixIdx: number;
setComponentMatrixIdx: (to: number) => void;
};
type LevelSelectionState = {
availableLevels: number[];
selectedLevelIdx: number;
@ -397,7 +403,7 @@ export const useAuthorizeUserStore = create<AuthorizeUserState>((set) => ({
}));
export const useMainSceneStore = create<MainSceneState>((set) => ({
subscene: "site",
subscene: "pause",
setSubscene: (to) => set(() => ({ subscene: to })),
}));
@ -470,4 +476,9 @@ export const useLevelSelectionStore = create<LevelSelectionState>((set) => ({
})),
}));
export const usePauseStore = create<any>((set) => ({}));
export const usePauseStore = create<PauseState>((set) => ({
componentMatrix: ["load", "about", "change", "save", "exit"],
componentMatrixIdx: 2,
setComponentMatrixIdx: (to: number) =>
set(() => ({ componentMatrixIdx: to })),
}));