mirror of
https://github.com/ad044/lainTSX.git
synced 2024-10-22 23:19:06 +00:00
adding level selection
This commit is contained in:
parent
46d9c421c8
commit
00de2883a8
7 changed files with 205 additions and 30 deletions
152
src/components/MainScene/LevelSelection.tsx
Normal file
152
src/components/MainScene/LevelSelection.tsx
Normal file
|
@ -0,0 +1,152 @@
|
|||
import React, { useCallback, useEffect, useMemo } from "react";
|
||||
import level_selection_font from "../../static/sprite/select_level_font.png";
|
||||
import verticalHud from "../../static/sprite/select_level_hud_vertical.png";
|
||||
import horizontalHud from "../../static/sprite/select_level_hud_horizontal.png";
|
||||
import levelSelectionText from "../../static/sprite/select_level_text.png";
|
||||
import upArrow from "../../static/sprite/select_level_up_arrow.png";
|
||||
import downArrow from "../../static/sprite/select_level_down_arrow.png";
|
||||
import { useLevelSelectionStore } from "../../store";
|
||||
import { useLoader } from "react-three-fiber";
|
||||
import * as THREE from "three";
|
||||
import { a, useSpring } from "@react-spring/three";
|
||||
|
||||
const LevelSelection = () => {
|
||||
const levelSelectionFontTex = useLoader(
|
||||
THREE.TextureLoader,
|
||||
level_selection_font
|
||||
);
|
||||
const verticalHudTex = useLoader(THREE.TextureLoader, verticalHud);
|
||||
const horizontalHudTex = useLoader(THREE.TextureLoader, horizontalHud);
|
||||
const levelSelectionTextTex = useLoader(
|
||||
THREE.TextureLoader,
|
||||
levelSelectionText
|
||||
);
|
||||
const upArrowTex = useLoader(THREE.TextureLoader, upArrow);
|
||||
const downArrowTex = useLoader(THREE.TextureLoader, downArrow);
|
||||
|
||||
const selectedLevelIdx = useLevelSelectionStore(
|
||||
(state) => state.selectedLevelIdx
|
||||
);
|
||||
|
||||
const selectedLevel = useLevelSelectionStore(
|
||||
useCallback((state) => state.availableLevels[selectedLevelIdx], [
|
||||
selectedLevelIdx,
|
||||
])
|
||||
)
|
||||
.toString()
|
||||
.padStart(2, "0");
|
||||
|
||||
const levelSelectionToggled = useLevelSelectionStore(
|
||||
(state) => state.levelSelectionToggled
|
||||
);
|
||||
|
||||
const { levelSelectionToggle } = useSpring({
|
||||
levelSelectionToggle: levelSelectionToggled,
|
||||
config: { duration: 500 },
|
||||
});
|
||||
|
||||
const verticalHudPosY = levelSelectionToggle.to([0, 1], [-2.5, 0]);
|
||||
const horizontalHudPosX = levelSelectionToggle.to([0, 1], [-4, -0.6]);
|
||||
|
||||
const generateGeom = useCallback((number: number) => {
|
||||
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 * 22) / 240 + number / 10;
|
||||
|
||||
uvAttribute.setXY(i, u, v);
|
||||
}
|
||||
return geometry;
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<>
|
||||
<a.group position-y={verticalHudPosY} renderOrder={5}>
|
||||
<mesh
|
||||
scale={[0.3, 0.4, 0]}
|
||||
position={[0.95, 0, 0]}
|
||||
renderOrder={5}
|
||||
geometry={generateGeom(parseInt(selectedLevel[0]))}
|
||||
>
|
||||
<meshBasicMaterial
|
||||
map={levelSelectionFontTex}
|
||||
attach="material"
|
||||
transparent={true}
|
||||
depthTest={false}
|
||||
/>
|
||||
</mesh>
|
||||
<mesh
|
||||
scale={[0.3, 0.4, 0]}
|
||||
position={[1.23, 0, 0]}
|
||||
renderOrder={5}
|
||||
geometry={generateGeom(parseInt(selectedLevel[1]))}
|
||||
>
|
||||
<meshBasicMaterial
|
||||
map={levelSelectionFontTex}
|
||||
attach="material"
|
||||
transparent={true}
|
||||
depthTest={false}
|
||||
/>
|
||||
</mesh>
|
||||
|
||||
<sprite scale={[0.65, 3, 0]} position={[1.1, -0.8, 0]} renderOrder={4}>
|
||||
<spriteMaterial
|
||||
map={verticalHudTex}
|
||||
attach="material"
|
||||
transparent={true}
|
||||
depthTest={false}
|
||||
/>
|
||||
</sprite>
|
||||
<sprite scale={[0.5, 0.12, 0]} position={[1.1, 0.3, 0]} renderOrder={4}>
|
||||
<spriteMaterial
|
||||
map={levelSelectionTextTex}
|
||||
attach="material"
|
||||
transparent={true}
|
||||
depthTest={false}
|
||||
/>
|
||||
</sprite>
|
||||
<sprite
|
||||
scale={[0.3, 0.15, 0]}
|
||||
position={[1.1, -0.35, 0]}
|
||||
renderOrder={4}
|
||||
>
|
||||
<spriteMaterial
|
||||
map={downArrowTex}
|
||||
attach="material"
|
||||
transparent={true}
|
||||
depthTest={false}
|
||||
/>
|
||||
</sprite>
|
||||
<sprite scale={[0.3, 0.15, 0]} position={[1.1, 0.5, 0]} renderOrder={4}>
|
||||
<spriteMaterial
|
||||
map={upArrowTex}
|
||||
attach="material"
|
||||
transparent={true}
|
||||
depthTest={false}
|
||||
/>
|
||||
</sprite>
|
||||
</a.group>
|
||||
|
||||
<a.sprite
|
||||
scale={[3, 0.3, 0]}
|
||||
position={[-0.6, 0, 0]}
|
||||
renderOrder={4}
|
||||
position-x={horizontalHudPosX}
|
||||
>
|
||||
<spriteMaterial
|
||||
map={horizontalHudTex}
|
||||
attach="material"
|
||||
transparent={true}
|
||||
depthTest={false}
|
||||
/>
|
||||
</a.sprite>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default LevelSelection;
|
|
@ -1,14 +0,0 @@
|
|||
import React, { memo } from "react";
|
||||
|
||||
const Lights = memo(() => {
|
||||
return (
|
||||
<>
|
||||
<pointLight color={0xffffff} position={[0, 0, 7]} intensity={1} />
|
||||
<pointLight color={0x7f7f7f} position={[0, 10, 0]} intensity={1.5} />
|
||||
<pointLight color={0xffffff} position={[8, 0, 0]} intensity={0.2} />
|
||||
<pointLight color={0xffffff} position={[-8, 0, 0]} intensity={0.2} />
|
||||
</>
|
||||
);
|
||||
});
|
||||
|
||||
export default Lights;
|
|
@ -37,6 +37,7 @@ const getKeyCodeAssociation = (keyCode: number): string => {
|
|||
39: "right", // right arrow
|
||||
88: "select", // x key
|
||||
90: "back", // z key
|
||||
69: "toggle_level_selection", // e key
|
||||
};
|
||||
return keyCodeAssocs[keyCode as keyof typeof keyCodeAssocs];
|
||||
};
|
||||
|
|
|
@ -1,9 +1,12 @@
|
|||
import { useCallback, useEffect } from "react";
|
||||
import { StateManagerProps } from "./EventManager";
|
||||
import { useLevelStore } from "../../store";
|
||||
import { useLevelSelectionStore, useLevelStore } from "../../store";
|
||||
|
||||
const LevelManager = (props: StateManagerProps) => {
|
||||
const setActiveLevel = useLevelStore((state) => state.setActiveLevel);
|
||||
const toggleLevelSelection = useLevelSelectionStore(
|
||||
(state) => state.toggleLevelSelection
|
||||
);
|
||||
|
||||
const dispatchObject = useCallback(
|
||||
(event: string, newLevel: string) => {
|
||||
|
@ -14,9 +17,13 @@ const LevelManager = (props: StateManagerProps) => {
|
|||
action: setActiveLevel,
|
||||
value: newLevel,
|
||||
};
|
||||
case "toggle_level_selection":
|
||||
return {
|
||||
action: toggleLevelSelection,
|
||||
};
|
||||
}
|
||||
},
|
||||
[setActiveLevel]
|
||||
[setActiveLevel, toggleLevelSelection]
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
|
@ -26,7 +33,10 @@ const LevelManager = (props: StateManagerProps) => {
|
|||
const dispatchedObject = dispatchObject(eventAction, newLevel);
|
||||
|
||||
if (dispatchedObject) {
|
||||
dispatchedObject.action(dispatchedObject.value);
|
||||
(dispatchedObject.action as any).apply(
|
||||
null,
|
||||
dispatchedObject.value as any
|
||||
);
|
||||
}
|
||||
}
|
||||
}, [props.eventState, dispatchObject]);
|
||||
|
|
|
@ -113,6 +113,9 @@ const handleMainSceneEvent = (gameContext: any) => {
|
|||
newScene = "sskn";
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case "toggle_level_selection":
|
||||
return { event: "toggle_level_selection" };
|
||||
}
|
||||
|
||||
const newActiveNodeId =
|
||||
|
|
|
@ -3,7 +3,6 @@ import { OrbitControls } from "@react-three/drei";
|
|||
import React, { Suspense, useEffect } from "react";
|
||||
import Site from "../components/MainScene/Site";
|
||||
import Lain from "../components/MainScene/Lain";
|
||||
import Lights from "../components/MainScene/Lights";
|
||||
import Preloader from "../components/Preloader";
|
||||
import MainSceneIntro from "../components/MainSceneIntro";
|
||||
import GrayPlanes from "../components/MainScene/GrayPlanes";
|
||||
|
@ -15,6 +14,7 @@ import HUD from "../components/MainScene/HUD";
|
|||
import YellowOrb from "../components/MainScene/YellowOrb";
|
||||
import ActiveLevelNodes from "../components/MainScene/ActiveLevelNodes";
|
||||
import YellowTextRenderer from "../components/TextRenderer/YellowTextRenderer";
|
||||
import LevelSelection from "../components/MainScene/LevelSelection";
|
||||
|
||||
const MainScene = () => {
|
||||
const setLainMoveState = useLainStore((state) => state.setLainMoveState);
|
||||
|
@ -30,18 +30,22 @@ const MainScene = () => {
|
|||
<Suspense fallback={null}>
|
||||
<MainSceneIntro />
|
||||
<a.group>
|
||||
<Preloader />
|
||||
<Site />
|
||||
<ActiveLevelNodes />
|
||||
<HUD />
|
||||
<TextRenderer />
|
||||
<YellowTextRenderer />
|
||||
<YellowOrb />
|
||||
<Starfield />
|
||||
<GrayPlanes />
|
||||
<Lights />
|
||||
<MiddleRing />
|
||||
{/*<Preloader />*/}
|
||||
{/*<Site />*/}
|
||||
{/*<ActiveLevelNodes />*/}
|
||||
{/*<HUD />*/}
|
||||
{/*<TextRenderer />*/}
|
||||
{/*<YellowTextRenderer />*/}
|
||||
{/*<YellowOrb />*/}
|
||||
{/*<Starfield />*/}
|
||||
{/*<GrayPlanes />*/}
|
||||
{/*<MiddleRing />*/}
|
||||
<LevelSelection />
|
||||
<OrbitControls />
|
||||
<pointLight color={0xffffff} position={[0, 0, 7]} intensity={1} />
|
||||
<pointLight color={0x7f7f7f} position={[0, 10, 0]} intensity={1.5} />
|
||||
<pointLight color={0xffffff} position={[8, 0, 0]} intensity={0.2} />
|
||||
<pointLight color={0xffffff} position={[-8, 0, 0]} intensity={0.2} />
|
||||
</a.group>
|
||||
<Lain />
|
||||
</Suspense>
|
||||
|
|
21
src/store.ts
21
src/store.ts
|
@ -3,6 +3,14 @@ import { combine } from "zustand/middleware";
|
|||
import * as THREE from "three";
|
||||
import authorize_user_letters from "./resources/authorize_user_letters.json";
|
||||
|
||||
type LevelSelectionState = {
|
||||
availableLevels: number[];
|
||||
selectedLevelIdx: number;
|
||||
levelSelectionToggled: number;
|
||||
setSelectedLevelIdx: (to: number) => void;
|
||||
toggleLevelSelection: () => void;
|
||||
};
|
||||
|
||||
type SceneState = {
|
||||
currentScene: string;
|
||||
setScene: (to: string) => void;
|
||||
|
@ -381,7 +389,7 @@ export const useSSknStore = create<SSknState>((set) => ({
|
|||
}));
|
||||
|
||||
export const useSceneStore = create<SceneState>((set) => ({
|
||||
currentScene: "polytan",
|
||||
currentScene: "main",
|
||||
setScene: (to) => set(() => ({ currentScene: to })),
|
||||
}));
|
||||
|
||||
|
@ -457,3 +465,14 @@ export const useGateStore = create<GateState>((set) => ({
|
|||
gateLvl: 4,
|
||||
incrementGateLvl: () => set((state) => ({ gateLvl: state.gateLvl + 1 })),
|
||||
}));
|
||||
|
||||
export const useLevelSelectionStore = create<LevelSelectionState>((set) => ({
|
||||
availableLevels: Array.from({ length: 24 }, (x, i) => i + 1),
|
||||
selectedLevelIdx: 23,
|
||||
levelSelectionToggled: 0,
|
||||
setSelectedLevelIdx: (to) => set(() => ({ selectedLevelIdx: to })),
|
||||
toggleLevelSelection: () =>
|
||||
set((state) => ({
|
||||
levelSelectionToggled: Number(!state.levelSelectionToggled),
|
||||
})),
|
||||
}));
|
||||
|
|
Loading…
Reference in a new issue