fixed some bugs, cleaned up site

This commit is contained in:
ad044 2020-12-22 20:55:09 +04:00
parent ac5edb303f
commit 02cdfa5dfe
10 changed files with 291 additions and 128 deletions

View file

@ -1,4 +1,4 @@
import React, { memo } from "react"; import React, { memo, useMemo } from "react";
import * as THREE from "three"; import * as THREE from "three";
import lofTexture from "../../static/sprite/gray_ring_lof.png"; import lofTexture from "../../static/sprite/gray_ring_lof.png";
import holeTexture from "../../static/sprite/hole.png"; import holeTexture from "../../static/sprite/hole.png";
@ -14,11 +14,14 @@ const GrayRing = memo((props: GrayRingProps) => {
const holeTex = useLoader(THREE.TextureLoader, holeTexture); const holeTex = useLoader(THREE.TextureLoader, holeTexture);
const lifeTex = useLoader(THREE.TextureLoader, lifeTexture); const lifeTex = useLoader(THREE.TextureLoader, lifeTexture);
const uniforms = THREE.UniformsUtils.merge([THREE.UniformsLib["lights"]]); const uniforms = useMemo(() => {
const uniform = THREE.UniformsUtils.merge([THREE.UniformsLib["lights"]]);
uniform.lof = { type: "t", value: lofTex };
uniform.hole = { type: "t", value: holeTex };
uniform.life = { type: "t", value: lifeTex };
uniforms.lof = { type: "t", value: lofTex }; return uniform
uniforms.hole = { type: "t", value: holeTex }; }, [holeTex, lifeTex, lofTex]);
uniforms.life = { type: "t", value: lifeTex };
const vertexShader = ` const vertexShader = `
varying vec2 vUv; varying vec2 vUv;

View file

@ -1,14 +1,14 @@
import React, { memo, useRef } from "react"; import React, { memo, useEffect, useMemo, useRef } from "react";
import { useFrame, useLoader } from "react-three-fiber"; import { useFrame, useLoader } from "react-three-fiber";
import * as THREE from "three"; import * as THREE from "three";
import siteATex from "../../static/sprite/site_a.png"; import siteATex from "../../static/sprite/site_a.png";
import siteBTex from "../../static/sprite/site_b.png"; import siteBTex from "../../static/sprite/site_b.png";
import siteLevelTex from "../../static/sprite/site_levels.png"; import siteLevelTex from "../../static/sprite/site_levels.png";
import { useSiteStore } from "../../store";
type PurpleRingProps = { type PurpleRingProps = {
purpleRingPosY: number; purpleRingPosY: number;
level: string; level: string;
site: string;
}; };
const PurpleRing = memo((props: PurpleRingProps) => { const PurpleRing = memo((props: PurpleRingProps) => {
@ -16,8 +16,6 @@ const PurpleRing = memo((props: PurpleRingProps) => {
const siteB = useLoader(THREE.TextureLoader, siteBTex); const siteB = useLoader(THREE.TextureLoader, siteBTex);
const siteLevels = useLoader(THREE.TextureLoader, siteLevelTex); const siteLevels = useLoader(THREE.TextureLoader, siteLevelTex);
const currentSite = useSiteStore((state) => state.currentSite);
const purpleRingRef = useRef<THREE.Object3D>(); const purpleRingRef = useRef<THREE.Object3D>();
const dispatchSiteLevelTextureOffset = (level: string) => { const dispatchSiteLevelTextureOffset = (level: string) => {
@ -36,19 +34,23 @@ const PurpleRing = memo((props: PurpleRingProps) => {
return siteTextures[level as keyof typeof siteTextures]; return siteTextures[level as keyof typeof siteTextures];
}; };
const uniforms = THREE.UniformsUtils.merge([THREE.UniformsLib["lights"]]); const uniforms = useMemo(() => {
const uniform = THREE.UniformsUtils.merge([THREE.UniformsLib["lights"]]);
const formattedLevel = props.level.padStart(2, "0"); const formattedLevel = props.level.padStart(2, "0");
uniforms.tex = { type: "t", value: currentSite === "a" ? siteA : siteB }; uniform.tex = { type: "t", value: null };
uniforms.siteLevels = { type: "t", value: siteLevels }; uniform.siteLevels = { type: "t", value: siteLevels };
uniforms.siteLevelFirstCharacterOffset = { uniform.siteLevelFirstCharacterOffset = {
value: dispatchSiteLevelTextureOffset(formattedLevel.charAt(0)), value: dispatchSiteLevelTextureOffset(formattedLevel.charAt(0)),
}; };
uniforms.siteLevelSecondCharacterOffset = { uniform.siteLevelSecondCharacterOffset = {
value: dispatchSiteLevelTextureOffset(formattedLevel.charAt(1)), value: dispatchSiteLevelTextureOffset(formattedLevel.charAt(1)),
}; };
return uniform;
}, [props.level, siteLevels]);
const vertexShader = ` const vertexShader = `
varying vec2 vUv; varying vec2 vUv;
@ -208,14 +210,21 @@ const PurpleRing = memo((props: PurpleRingProps) => {
} }
`; `;
const matRef = useRef<THREE.ShaderMaterial>();
useFrame(() => { useFrame(() => {
purpleRingRef.current!.rotation.y += 0.005; purpleRingRef.current!.rotation.y += 0.005;
}); });
useEffect(() => {
if (matRef.current) {
matRef.current.uniforms.tex.value = props.site === "a" ? siteA : siteB;
matRef.current.uniformsNeedUpdate = true;
}
}, [props.site, siteA, siteB]);
return ( return (
<mesh <mesh
position={[0, props.purpleRingPosY, 0]} position={[0, props.purpleRingPosY, 0]}
renderOrder={1}
scale={[26, 26, 26]} scale={[26, 26, 26]}
ref={purpleRingRef} ref={purpleRingRef}
> >
@ -231,6 +240,7 @@ const PurpleRing = memo((props: PurpleRingProps) => {
transparent={true} transparent={true}
uniforms={uniforms} uniforms={uniforms}
lights={true} lights={true}
ref={matRef}
/> />
</mesh> </mesh>
); );

View file

@ -1,15 +1,9 @@
import React, { memo, Suspense, useMemo } from "react"; import React, { memo, Suspense, useEffect, useState } from "react";
import site_a from "../../resources/site_a.json";
import site_b from "../../resources/site_b.json";
import level_y_values from "../../resources/level_y_values.json";
import node_positions from "../../resources/node_positions.json";
import Node from "./Node";
import { a, useSpring } from "@react-spring/three"; import { a, useSpring } from "@react-spring/three";
import { useLevelStore, useNodeStore, useSiteStore } from "../../store"; import { useSiteStore } from "../../store";
import PurpleRing from "./PurpleRing"; import ActiveLevelNodes from "./Site/ActiveLevelNodes";
import GrayRing from "./GrayRing"; import InactiveLevelNodes from "./Site/InactiveLevelNodes";
import CyanCrystal from "./CyanCrystal"; import Rings from "./Site/Rings";
import { isNodeVisible } from "../../core/nodeSelector";
export type NodeDataType = { export type NodeDataType = {
image_table_indices: { 1: string; 2: string; 3: string }; image_table_indices: { 1: string; 2: string; 3: string };
@ -34,30 +28,7 @@ export type SiteType = {
[key: string]: LevelType; [key: string]: LevelType;
}; };
const Site = memo(() => { const Site = () => {
const gameProgress = useNodeStore((state) => state.gameProgress);
const currentSite = useSiteStore((state) => state.currentSite);
const siteData = currentSite === "a" ? site_a : site_b;
const activeLevel = useLevelStore((state) => state.activeLevel);
const visibleNodes = useMemo(() => {
const obj = {};
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, siteData[level as keyof typeof siteData]);
});
return obj;
}, [activeLevel, siteData]);
const siteTransformState = useSiteStore((state) => state.transformState); const siteTransformState = useSiteStore((state) => state.transformState);
const siteState = useSpring({ const siteState = useSpring({
@ -67,51 +38,32 @@ const Site = memo(() => {
config: { duration: 1200 }, config: { duration: 1200 },
}); });
const introSiteState = useSpring({
posZ: 0,
rotX: 0,
from: { posZ: -7, rotX: Math.PI / 2 },
config: { duration: 3900 },
});
return ( return (
<Suspense fallback={null}> <Suspense fallback={null}>
<a.group
rotation-x={introSiteState.rotX}
position-z={introSiteState.posZ}
>
<a.group rotation-x={siteState.siteRotX}>
<a.group <a.group
rotation-y={siteState.siteRotY} rotation-y={siteState.siteRotY}
position-y={siteState.sitePosY} position-y={siteState.sitePosY}
rotation-x={siteState.siteRotX}
> >
{Object.entries(level_y_values).map((level: [string, number]) => { {/*<ActiveLevelNodes />*/}
if ( {/*<InactiveLevelNodes />*/}
(currentSite === "b" && parseInt(level[0]) <= 13) || <Rings />
currentSite === "a" </a.group>
) { </a.group>
return (
<group position={[0, level[1], 0]} key={level[0]}>
<PurpleRing purpleRingPosY={0.44} level={level[0]} />
<GrayRing grayRingPosY={-0.29} />
<CyanCrystal crystalRingPosY={-0.45} />
</group>
);
}
})}
{Object.entries(visibleNodes).map((node: [string, any]) => {
if (isNodeVisible(node[0], gameProgress, currentSite)) {
return (
<Node
sprite={node[1].node_name}
position={
node_positions[
node[0].substr(2) as keyof typeof node_positions
].position
}
rotation={
node_positions[
node[0].substr(2) as keyof typeof node_positions
].rotation
}
key={node[1].node_name}
level={node[0].substr(0, 2)}
/>
);
}
})}
</a.group> </a.group>
</Suspense> </Suspense>
); );
}); };
export default Site; export default Site;

View file

@ -1,11 +1,10 @@
import React, { useMemo } from "react"; import React, { useMemo } from "react";
import Node from "./Node"; import Node from "../Node";
import node_positions from "../../resources/node_positions.json"; import node_positions from "../../../resources/node_positions.json";
import site_a from "../../resources/site_a.json"; import site_a from "../../../resources/site_a.json";
import { useNodeStore, useLevelStore, useSiteStore } from "../../store"; import { useLevelStore, useNodeStore, useSiteStore } from "../../../store";
import { a, useSpring } from "@react-spring/three"; import { isNodeVisible } from "../../../core/nodeSelector";
import { isNodeVisible } from "../../core/nodeSelector"; import site_b from "../../../resources/site_b.json";
import site_b from "../../resources/site_b.json";
const ActiveLevelNodes = () => { const ActiveLevelNodes = () => {
const gameProgress = useNodeStore((state) => state.gameProgress); const gameProgress = useNodeStore((state) => state.gameProgress);
@ -22,21 +21,8 @@ const ActiveLevelNodes = () => {
[activeLevel, siteData] [activeLevel, siteData]
); );
const siteTransformState = useSiteStore((state) => state.transformState);
const siteState = useSpring({
siteRotY: siteTransformState.rotY,
sitePosY: siteTransformState.posY,
siteRotX: siteTransformState.rotX,
config: { duration: 1200 },
});
return ( return (
<a.group <>
rotation-y={siteState.siteRotY}
position-y={siteState.sitePosY}
rotation-x={siteState.siteRotX}
>
{Object.entries(activeLevelNodes).map((node: [string, any]) => { {Object.entries(activeLevelNodes).map((node: [string, any]) => {
if (isNodeVisible(node[0], gameProgress, currentSite)) { if (isNodeVisible(node[0], gameProgress, currentSite)) {
return ( return (
@ -57,7 +43,7 @@ const ActiveLevelNodes = () => {
); );
} }
})} })}
</a.group> </>
); );
}; };

View file

@ -0,0 +1,58 @@
import React, { useMemo } from "react";
import site_a from "../../../resources/site_a.json";
import site_b from "../../../resources/site_b.json";
import node_positions from "../../../resources/node_positions.json";
import Node from "../Node";
import { useLevelStore, useNodeStore, useSiteStore } from "../../../store";
import { isNodeVisible } from "../../../core/nodeSelector";
const InactiveLevelNodes = () => {
const gameProgress = useNodeStore((state) => state.gameProgress);
const currentSite = useSiteStore((state) => state.currentSite);
const siteData = currentSite === "a" ? site_a : site_b;
const activeLevel = useLevelStore((state) => state.activeLevel);
const visibleNodes = useMemo(() => {
const obj = {};
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, siteData[level as keyof typeof siteData]);
});
return obj;
}, [activeLevel, siteData]);
return (
<>
{Object.entries(visibleNodes).map((node: [string, any]) => {
if (isNodeVisible(node[0], gameProgress, currentSite)) {
return (
<Node
sprite={node[1].node_name}
position={
node_positions[node[0].substr(2) as keyof typeof node_positions]
.position
}
rotation={
node_positions[node[0].substr(2) as keyof typeof node_positions]
.rotation
}
key={node[1].node_name}
level={node[0].substr(0, 2)}
/>
);
}
})}
</>
);
};
export default InactiveLevelNodes;

View file

@ -0,0 +1,35 @@
import React from "react";
import level_y_values from "../../../resources/level_y_values.json";
import { useSiteStore } from "../../../store";
import PurpleRing from "../PurpleRing";
import GrayRing from "../GrayRing";
import CyanCrystal from "../CyanCrystal";
const Rings = () => {
const currentSite = useSiteStore((state) => state.currentSite);
return (
<>
{Object.entries(level_y_values).map((level: [string, number]) => {
if (
(currentSite === "b" && parseInt(level[0]) <= 13) ||
currentSite === "a"
) {
return (
<group position={[0, level[1], 0]} key={level[0]}>
<PurpleRing
purpleRingPosY={0.44}
level={level[0]}
site={currentSite}
/>
<GrayRing grayRingPosY={-0.29} />
<CyanCrystal crystalRingPosY={-0.45} />
</group>
);
}
})}
</>
);
};
export default Rings;

View file

@ -1,12 +1,66 @@
import { useCallback, useEffect } from "react"; import { useCallback, useEffect } from "react";
import { useSiteStore } from "../../store"; import { useSiteSaveStore, useSiteStore } from "../../store";
import { StateManagerProps } from "./EventManager"; import { StateManagerProps } from "./EventManager";
const SiteManager = (props: StateManagerProps) => { const SiteManager = (props: StateManagerProps) => {
const setTransformState = useSiteStore((state) => state.setTransformState); const setTransformState = useSiteStore((state) => state.setTransformState);
const setCurrentSite = useSiteStore((state) => state.setCurrentSite);
const setSiteSaveState = useSiteSaveStore((state) => state.setSiteSaveState);
const siteASaveState = useSiteSaveStore((state) => state.a);
const siteBSaveState = useSiteSaveStore((state) => state.b);
const changeSite = useCallback(
(
currentSite: string,
activeNodeId: string,
activeNodeMatrixIndices: {
matrixIdx: number;
rowIdx: number;
colIdx: number;
},
siteRotY: number,
sitePosY: number,
newSite: string
) => {
setSiteSaveState(currentSite, {
activeNodeId: activeNodeId,
nodeMatrixIndices: activeNodeMatrixIndices,
siteRotY: siteRotY,
sitePosY: sitePosY,
});
const siteToLoad = newSite === "a" ? siteASaveState : siteBSaveState;
setCurrentSite(newSite);
setTransformState(siteToLoad.rotY, "rotY");
setTransformState(siteToLoad.posY, "posY");
console.log(newSite)
},
[
setCurrentSite,
setSiteSaveState,
setTransformState,
siteASaveState,
siteBSaveState,
]
);
const dispatchObject = useCallback( const dispatchObject = useCallback(
(event: string, newSitePosY: number, newSiteRotY: number) => { (
event: string,
newSitePosY: number,
newSiteRotY: number,
currentSite: string,
newSite: string,
activeNodeId: string,
activeNodeMatrixIndices: {
matrixIdx: number;
rowIdx: number;
colIdx: number;
}
) => {
switch (event) { switch (event) {
case "site_up": case "site_up":
case "site_down": case "site_down":
@ -27,7 +81,7 @@ const SiteManager = (props: StateManagerProps) => {
case "pause_game": case "pause_game":
return { return {
action: setTransformState, action: setTransformState,
value: [Math.PI / 2 - 0.5, "rotX"], value: [Math.PI / 2, "rotX"],
actionDelay: 0, actionDelay: 0,
}; };
case "pause_exit_select": case "pause_exit_select":
@ -36,9 +90,22 @@ const SiteManager = (props: StateManagerProps) => {
value: [0, "rotX"], value: [0, "rotX"],
actionDelay: 0, actionDelay: 0,
}; };
case "pause_change_select":
return {
action: changeSite,
value: [
currentSite,
activeNodeId,
activeNodeMatrixIndices,
newSiteRotY,
newSitePosY,
newSite,
],
actionDelay: 0,
};
} }
}, },
[setTransformState] [changeSite, setTransformState]
); );
useEffect(() => { useEffect(() => {
@ -46,16 +113,28 @@ const SiteManager = (props: StateManagerProps) => {
const eventAction = props.eventState.event; const eventAction = props.eventState.event;
const newSiteRotY = props.eventState.newSiteRotY; const newSiteRotY = props.eventState.newSiteRotY;
const newSitePosY = props.eventState.newSitePosY; const newSitePosY = props.eventState.newSitePosY;
const activeNodeId = props.eventState.activeNodeId;
const activeNodeMatrixIndices = props.eventState.activeNodeMatrixIndices;
const currentSite = props.eventState.currentSite;
const newSite = props.eventState.newSite;
const dispatchedObject = dispatchObject( const dispatchedObject = dispatchObject(
eventAction, eventAction,
newSitePosY, newSitePosY,
newSiteRotY newSiteRotY,
currentSite,
newSite,
activeNodeId,
activeNodeMatrixIndices
); );
if (dispatchedObject) { if (dispatchedObject) {
setTimeout(() => { setTimeout(() => {
dispatchedObject.action.apply(null, dispatchedObject.value as any); (dispatchedObject.action as any).apply(
null,
dispatchedObject.value as any
);
}, dispatchedObject.actionDelay); }, dispatchedObject.actionDelay);
} }
} }

View file

@ -22,7 +22,7 @@ const handleMainSceneEvent = (gameContext: any) => {
const siteRotY = gameContext.siteTransformState.rotY; const siteRotY = gameContext.siteTransformState.rotY;
const sitePosY = gameContext.siteTransformState.posY; const sitePosY = gameContext.siteTransformState.posY;
let newActiveNodeId; let newActiveNodeId = gameContext.activeNodeId;
let newActiveHudId; let newActiveHudId;
let newLevel = parseInt(gameContext.activeLevel); let newLevel = parseInt(gameContext.activeLevel);
let newSiteRotY = gameContext.siteTransformState.rotY; let newSiteRotY = gameContext.siteTransformState.rotY;
@ -191,6 +191,12 @@ const handleMainSceneEvent = (gameContext: any) => {
case "CIRCLE": case "CIRCLE":
return { return {
event: `pause_${activePauseComponent}_select`, event: `pause_${activePauseComponent}_select`,
currentSite: currentSite,
newSitePosY: newSitePosY,
newtSiteRotY: newSiteRotY,
activeNodeId: newActiveNodeId,
activeNodeMatrixIndices: nodeMatrixIndices,
newSite: currentSite === "a" ? "b" : "a",
}; };
} }
} }

View file

@ -10,7 +10,6 @@ import { useMainSceneStore } from "../store";
import GreenTextRenderer from "../components/TextRenderer/GreenTextRenderer"; import GreenTextRenderer from "../components/TextRenderer/GreenTextRenderer";
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 ActiveLevelNodes from "../components/MainScene/ActiveLevelNodes";
import YellowTextRenderer from "../components/TextRenderer/YellowTextRenderer"; import YellowTextRenderer from "../components/TextRenderer/YellowTextRenderer";
import LevelSelection from "../components/MainScene/LevelSelection"; import LevelSelection from "../components/MainScene/LevelSelection";
import Pause from "../components/MainScene/PauseSubscene/Pause"; import Pause from "../components/MainScene/PauseSubscene/Pause";
@ -22,12 +21,11 @@ const MainScene = () => {
const isPaused = currentSubscene === "pause"; const isPaused = currentSubscene === "pause";
return ( return (
<a.perspectiveCamera position-z={3}> <perspectiveCamera position-z={3}>
<Suspense fallback={null}> <Suspense fallback={null}>
<a.group> <a.group>
<Preloader /> <Preloader />
<Site /> <Site />
<ActiveLevelNodes />
<HUD visible={!isPaused} /> <HUD visible={!isPaused} />
<GreenTextRenderer visible={!isPaused} /> <GreenTextRenderer visible={!isPaused} />
<YellowTextRenderer visible={!isPaused} /> <YellowTextRenderer visible={!isPaused} />
@ -45,7 +43,7 @@ const MainScene = () => {
</a.group> </a.group>
<Lain /> <Lain />
</Suspense> </Suspense>
</a.perspectiveCamera> </perspectiveCamera>
); );
}; };
export default MainScene; export default MainScene;

View file

@ -258,6 +258,10 @@ export const useHudStore = create<HUDState>((set) => ({
export const useNodeStore = create( export const useNodeStore = create(
combine( combine(
{ {
siteASave: {
activeNodeId: "0422",
nodeMatrixIndices: { matrixIdx: 7, rowIdx: 0, colIdx: 0 },
},
activeNodeState: { activeNodeState: {
id: "0422", id: "0422",
posX: 0, posX: 0,
@ -299,7 +303,7 @@ export const useStarfieldStore = create<StarfieldState>((set) => ({
export const useSiteStore = create( export const useSiteStore = create(
combine( combine(
{ {
currentSite: "b", currentSite: "a",
transformState: { transformState: {
posY: 0, posY: 0,
rotY: 0, rotY: 0,
@ -311,6 +315,8 @@ export const useSiteStore = create(
set((state) => ({ set((state) => ({
transformState: { ...state.transformState, [at]: to }, transformState: { ...state.transformState, [at]: to },
})), })),
setCurrentSite: (to: string) =>
set(() => ({ currentSite: to as "a" | "b" })),
}) })
) )
); );
@ -516,3 +522,33 @@ export const usePauseStore = create<PauseState>((set) => ({
setComponentMatrixIdx: (to) => set(() => ({ componentMatrixIdx: to })), setComponentMatrixIdx: (to) => set(() => ({ componentMatrixIdx: to })),
setExitAnimation: (to) => set(() => ({ exitAnimation: to })), setExitAnimation: (to) => set(() => ({ exitAnimation: to })),
})); }));
export const useSiteSaveStore = create(
combine(
{
a: {
activeNodeId: "0422",
nodeMatrixIndices: { matrixIdx: 7, rowIdx: 0, colIdx: 0 },
siteRotY: 0,
sitePosY: 0,
},
b: {
activeNodeId: "0422",
nodeMatrixIndices: { matrixIdx: 7, rowIdx: 0, colIdx: 0 },
siteRotY: 0,
sitePosY: 0,
},
} as any,
(set) => ({
setSiteSaveState: (
site: string,
to: {
activeNodeId: string;
nodeMatrixIndices: { matrixIdx: 7; rowIdx: 0; colIdx: 0 };
siteRotY: number;
sitePosY: number;
}
) => set(() => ({ site: to })),
})
)
);