added main menu

This commit is contained in:
ad044 2020-11-08 21:41:25 +04:00
parent 3e62072a7b
commit 81cabd0667
10 changed files with 409 additions and 106 deletions

View file

@ -3,7 +3,6 @@ import MainScene from "./scenes/MainScene";
import "./static/css/main_scene.css";
import "./static/css/page.css";
import { Canvas } from "react-three-fiber";
import Boot from "./components/Boot";
import MediaPlayer from "./components/MediaScene/MediaPlayer";
import MediaScene from "./scenes/MediaScene";
import EventManager from "./core/StateManagers/EventManager";
@ -12,7 +11,6 @@ import GateScene from "./scenes/GateScene";
import BootScene from "./scenes/BootScene";
const App = () => {
const [moveToGame, setMoveToGame] = useState(false);
const currentScene = useSceneStore((state) => state.currentScene);
useEffect(() => {
document.title = "< index >";
@ -33,8 +31,6 @@ const App = () => {
return (
<div id="game-root" className="game">
{/*<Boot setMoveToGame={setMoveToGame} />*/}
{/* {moveToGame ? <MainScene /> : <Boot setMoveToGame={setMoveToGame} />} */}
<span className="canvas">
<EventManager />
<Canvas concurrent>

View file

@ -5,7 +5,11 @@ import { useFrame, useLoader } from "react-three-fiber";
import * as THREE from "three";
import { PlainAnimator } from "three-plain-animator/lib/plain-animator";
const BootAccela = () => {
type BootAccelaProps = {
visible: boolean;
};
const BootAccela = (props: BootAccelaProps) => {
const accelaBootTex: any = useLoader(
THREE.TextureLoader,
accelaBootSpriteSheet
@ -24,10 +28,18 @@ const BootAccela = () => {
return (
<>
<sprite scale={[0.35, 0.6, 0.35]} position={[0, 0.2, 0]}>
<sprite
scale={[0.35, 0.6, 0.35]}
position={[0, 0.2, 0]}
visible={props.visible}
>
<spriteMaterial attach="material" map={accelaBootTex} />
</sprite>
<sprite scale={[0.4, 0.6, 0.4]} position={[0, -0.5, 0]}>
<sprite
scale={[0.4, 0.6, 0.4]}
position={[0, -0.5, 0]}
visible={props.visible}
>
<spriteMaterial attach="material" map={makeMeSadTex} />
</sprite>
</>

View file

@ -8,12 +8,24 @@ import bootDangoText from "../../static/sprite/dango_text.png";
import bootMisoShio from "../../static/sprite/miso_shio.png";
import bootArrows from "../../static/sprite/boot_arrows.png";
import bootStatusTexts from "../../static/sprite/boot_status_texts.png";
import bootBackgroundText from "../../static/sprite/boot_background_text.png";
import bootBackgroundDistortedTex from "../../static/sprite/distorted_text.png";
import { useFrame, useLoader } from "react-three-fiber";
import { a, useSpring } from "@react-spring/three";
import * as THREE from "three";
import { OrbitControls } from "@react-three/drei";
type BootAnimationProps = {
visible: boolean;
};
const BootAnimation = (props: BootAnimationProps) => {
const [
backgroundFloatingTextShown,
setBackgroundFloatingTextShown,
] = useState(false);
const BootAnimation = () => {
const bootLofTex = useLoader(THREE.TextureLoader, bootLof);
const bootBottomBarLeftTex = useLoader(
THREE.TextureLoader,
@ -29,6 +41,14 @@ const BootAnimation = () => {
const bootMisoShioTex = useLoader(THREE.TextureLoader, bootMisoShio);
const bootArrowsTex = useLoader(THREE.TextureLoader, bootArrows);
const bootStatusTextsTex = useLoader(THREE.TextureLoader, bootStatusTexts);
const bootBackgroundTextTex = useLoader(
THREE.TextureLoader,
bootBackgroundText
);
const bootBackgroundDistortedTextTex = useLoader(
THREE.TextureLoader,
bootBackgroundDistortedTex
);
const graySquareRef = useRef<THREE.SpriteMaterial>();
const arrowRef = useRef<THREE.Object3D>();
@ -41,6 +61,45 @@ const BootAnimation = () => {
arrowRef.current.position.y =
arrowRef.current.position.y === -1.04 ? -0.96 : -1.04;
}
if (
backgroundFloatingTextShown &&
firstBackgroundTextRef.current &&
sndBackgroundTextRef.current &&
firstDistortedBackgroundTextRef.current &&
sndDistortedBackgroundTextRef.current
) {
if (firstBackgroundTextRef.current.position.y > 3.5) {
firstBackgroundTextRef.current.position.y = -3.5;
firstBackgroundTextRef.current.position.x = -0.85;
} else {
firstBackgroundTextRef.current.position.y += 0.01;
firstBackgroundTextRef.current.position.x += 0.001;
}
if (sndBackgroundTextRef.current.position.y > 3.5) {
sndBackgroundTextRef.current.position.y = -3.5;
sndBackgroundTextRef.current.position.x = -0.85;
} else {
sndBackgroundTextRef.current.position.y += 0.01;
sndBackgroundTextRef.current.position.x += 0.001;
}
if (firstDistortedBackgroundTextRef.current.position.y > 2.8) {
firstDistortedBackgroundTextRef.current.position.y = -3;
firstDistortedBackgroundTextRef.current.position.x = 0;
} else {
firstDistortedBackgroundTextRef.current.position.y += 0.025;
firstDistortedBackgroundTextRef.current.position.x -= 0.013;
}
if (sndDistortedBackgroundTextRef.current.position.y > 2.8) {
sndDistortedBackgroundTextRef.current.position.y = -3;
sndDistortedBackgroundTextRef.current.position.x = 0;
} else {
sndDistortedBackgroundTextRef.current.position.y += 0.025;
sndDistortedBackgroundTextRef.current.position.x -= 0.013;
}
}
});
const currentBootStatusTextTex = useMemo(() => {
@ -50,45 +109,49 @@ const BootAnimation = () => {
}, [bootStatusTextsTex]);
useEffect(() => {
setTimeout(() => {
currentBootStatusTextTex.offset.y = 0.528;
}, 900);
if (props.visible) {
setTimeout(() => {
currentBootStatusTextTex.offset.y = 0.528;
}, 900);
setTimeout(() => {
currentBootStatusTextTex.offset.y = 0.79;
}, 1200);
setTimeout(() => {
currentBootStatusTextTex.offset.y = 0.79;
}, 1200);
setTimeout(() => {
currentBootStatusTextTex.offset.y = 0.264;
}, 1500);
setTimeout(() => {
currentBootStatusTextTex.offset.y = 0.264;
}, 1500);
setTimeout(() => {
currentBootStatusTextTex.offset.y = 0.79;
}, 1600);
setTimeout(() => {
currentBootStatusTextTex.offset.y = 0.79;
}, 1600);
setTimeout(() => {
currentBootStatusTextTex.offset.x = 0.5;
currentBootStatusTextTex.offset.y = 0.264;
}, 2100);
setTimeout(() => {
currentBootStatusTextTex.offset.x = 0.5;
currentBootStatusTextTex.offset.y = 0.264;
}, 2100);
setTimeout(() => {
currentBootStatusTextTex.offset.x = 0;
currentBootStatusTextTex.offset.y = 0.005;
}, 2400);
setTimeout(() => {
currentBootStatusTextTex.offset.x = 0;
currentBootStatusTextTex.offset.y = 0.005;
}, 2400);
setTimeout(() => {
currentBootStatusTextTex.offset.y = 0.79;
}, 2500);
setTimeout(() => {
currentBootStatusTextTex.offset.y = 0.79;
}, 2500);
setTimeout(() => {
currentBootStatusTextTex.offset.x = 0.5;
currentBootStatusTextTex.offset.y = 0.005;
setBootOpacity(0);
setGraySquarePosY(0);
setLofPosX(1.3);
setLofPosY(1);
}, 4000);
}, [currentBootStatusTextTex.offset]);
setTimeout(() => {
currentBootStatusTextTex.offset.x = 0.5;
currentBootStatusTextTex.offset.y = 0.005;
setBootOpacity(0);
setGraySquarePosY(0);
setLofPosX(1.3);
setLofPosY(1);
setBackgroundFloatingTextShown(true);
}, 4200);
}
}, [bootBackgroundTextTex, currentBootStatusTextTex.offset, props.visible]);
const [bootOpacity, setBootOpacity] = useState(1);
const [graySquarePosY, setGraySquarePosY] = useState(-0.8);
@ -107,73 +170,150 @@ const BootAnimation = () => {
config: { duration: 600 },
});
const firstBackgroundTextRef = useRef<THREE.Object3D>();
const sndBackgroundTextRef = useRef<THREE.Object3D>();
const firstDistortedBackgroundTextRef = useRef<THREE.Object3D>();
const sndDistortedBackgroundTextRef = useRef<THREE.Object3D>();
return (
<>
<a.sprite
scale={[1.2, 0.4, 0]}
position-x={positionState.lofPosX}
position-y={positionState.lofPosY}
>
<spriteMaterial attach="material" map={bootLofTex} />
</a.sprite>
<sprite scale={[2.2, 0.66, 0]} position={[-1.1, -0.8, 0]}>
<a.spriteMaterial
attach="material"
map={bootBottomBarLeftTex}
opacity={bootState.bootOpacity}
/>
</sprite>
<sprite scale={[2.2, 0.66, 0]} position={[1.1, -0.8, 0]}>
<a.spriteMaterial
attach="material"
map={bootBottomBarRightTex}
opacity={bootState.bootOpacity}
/>
</sprite>
<sprite scale={[0.2, 0.2, 0]} position={[0, -0.8, 0]}>
<a.spriteMaterial
attach="material"
map={bootPurpleSquareTex}
opacity={bootState.bootOpacity}
/>
</sprite>
<sprite scale={[1.4, 0.5, 0]} position={[-1.2, -1.17, 0]}>
<a.spriteMaterial
attach="material"
map={bootDangoTextTex}
opacity={bootState.bootOpacity}
/>
</sprite>
<sprite scale={[0.6, 0.15, 0]} position={[0.9, -1, 0]}>
<a.spriteMaterial
attach="material"
map={bootMisoShioTex}
opacity={bootState.bootOpacity}
/>
</sprite>
<sprite scale={[0.12, 0.06, 0]} position={[0.5, -0.96, 0]} ref={arrowRef}>
<a.spriteMaterial
attach="material"
map={bootArrowsTex}
opacity={bootState.bootOpacity}
/>
</sprite>
{props.visible ? (
<>
{/*we have two of each to create looping effect*/}
<a.sprite
scale={[1.5, 3.5, 0]}
renderOrder={-1}
position={[-0.85, -3.5, 0]}
ref={firstBackgroundTextRef}
>
<spriteMaterial
attach="material"
rotation={-0.1}
map={bootBackgroundTextTex}
transparent={true}
opacity={0.6}
/>
</a.sprite>
<a.sprite
scale={[1.5, 3.5, 0]}
renderOrder={-1}
position={[-1.2, -7, 0]}
ref={sndBackgroundTextRef}
>
<spriteMaterial
attach="material"
rotation={-0.1}
map={bootBackgroundTextTex}
transparent={true}
opacity={0.6}
/>
</a.sprite>
<sprite scale={[1.4, 0.2, 0]} position={[1.15, -1.2, 0]}>
<a.spriteMaterial
attach="material"
map={currentBootStatusTextTex}
opacity={bootState.bootOpacity}
/>
</sprite>
<group position={[1, 0, 0]}>
<a.sprite
scale={[1, 3.5, 0]}
renderOrder={-1}
position={[0, -3.5, 0]}
ref={firstDistortedBackgroundTextRef}
>
<spriteMaterial
attach="material"
rotation={0.5}
map={bootBackgroundDistortedTextTex}
transparent={true}
/>
</a.sprite>
<a.sprite
scale={[1, 3.5, 0]}
renderOrder={-1}
position={[1.55, -6.5, 0]}
ref={sndDistortedBackgroundTextRef}
>
<spriteMaterial
attach="material"
rotation={0.5}
map={bootBackgroundDistortedTextTex}
transparent={true}
/>
</a.sprite>
</group>
<a.sprite scale={[0.2, 0.2, 0]} position-y={positionState.graySquarePosY}>
<spriteMaterial
attach="material"
map={bootGraySquareTex}
ref={graySquareRef}
/>
</a.sprite>
<a.sprite
scale={[1.2, 0.4, 0]}
position-x={positionState.lofPosX}
position-y={positionState.lofPosY}
>
<spriteMaterial attach="material" map={bootLofTex} />
</a.sprite>
<sprite scale={[2.2, 0.66, 0]} position={[-1.1, -0.8, 0]}>
<a.spriteMaterial
attach="material"
map={bootBottomBarLeftTex}
opacity={bootState.bootOpacity}
/>
</sprite>
<sprite scale={[2.2, 0.66, 0]} position={[1.1, -0.8, 0]}>
<a.spriteMaterial
attach="material"
map={bootBottomBarRightTex}
opacity={bootState.bootOpacity}
/>
</sprite>
<sprite scale={[0.2, 0.2, 0]} position={[0, -0.8, 0]}>
<a.spriteMaterial
attach="material"
map={bootPurpleSquareTex}
opacity={bootState.bootOpacity}
/>
</sprite>
<sprite scale={[1.4, 0.5, 0]} position={[-1.2, -1.17, 0]}>
<a.spriteMaterial
attach="material"
map={bootDangoTextTex}
opacity={bootState.bootOpacity}
/>
</sprite>
<sprite scale={[0.6, 0.15, 0]} position={[0.9, -1, 0]}>
<a.spriteMaterial
attach="material"
map={bootMisoShioTex}
opacity={bootState.bootOpacity}
/>
</sprite>
<sprite
scale={[0.12, 0.06, 0]}
position={[0.5, -0.96, 0]}
ref={arrowRef}
>
<a.spriteMaterial
attach="material"
map={bootArrowsTex}
opacity={bootState.bootOpacity}
/>
</sprite>
<sprite scale={[1.4, 0.2, 0]} position={[1.15, -1.2, 0]}>
<a.spriteMaterial
attach="material"
map={currentBootStatusTextTex}
opacity={bootState.bootOpacity}
/>
</sprite>
<a.sprite
scale={[0.2, 0.2, 0]}
position-y={positionState.graySquarePosY}
>
<spriteMaterial
attach="material"
map={bootGraySquareTex}
ref={graySquareRef}
/>
</a.sprite>
</>
) : (
<></>
)}
</>
);
};

View file

@ -0,0 +1,71 @@
import React from "react";
import { a } from "@react-spring/three";
import authorizeActive from "../../static/sprite/authorize_user_active.png";
import authorizeInactive from "../../static/sprite/authorize_user_inactive.png";
import loadDataActive from "../../static/sprite/load_data_active.png";
import loadDataInactive from "../../static/sprite/load_data_inactive.png";
import { useLoader } from "react-three-fiber";
import * as THREE from "three";
import { useMainMenuStore } from "../../store";
type BootMainMenuProps = {
visible: boolean;
};
const BootMainMenu = (props: BootMainMenuProps) => {
const activeMainMenuElement = useMainMenuStore(
(state) => state.activeMainMenuElement
);
const authorizeActiveTex = useLoader(THREE.TextureLoader, authorizeActive);
const authorizeInactiveTex = useLoader(
THREE.TextureLoader,
authorizeInactive
);
const loadDataActiveTex = useLoader(THREE.TextureLoader, loadDataActive);
const loadDataInactiveTex = useLoader(THREE.TextureLoader, loadDataInactive);
return (
<>
{props.visible ? (
<>
<a.sprite
scale={[1.8, 0.3, 0]}
renderOrder={1}
position={[0, 0.5, 0]}
>
<spriteMaterial
attach="material"
map={
activeMainMenuElement === "authorize_user"
? authorizeActiveTex
: authorizeInactiveTex
}
transparent={true}
/>
</a.sprite>
<a.sprite
scale={[1.4, 0.3, 0]}
renderOrder={1}
position={[0, -0.5, 0]}
>
<spriteMaterial
attach="material"
map={
activeMainMenuElement === "load_data"
? loadDataActiveTex
: loadDataInactiveTex
}
transparent={true}
/>
</a.sprite>
</>
) : (
<></>
)}
</>
);
};
export default BootMainMenu;

View file

@ -21,6 +21,7 @@ import MediaImageManager from "./MediaImageManager";
import computeAction from "../computeAction";
import available_blue_orbs_on_projection from "../../resources/available_blue_orbs_on_projection.json";
import LevelManager from "./LevelManager";
import MainMenuManager from "./MainMenuManager";
const getKeyCodeAssociation = (keyCode: number): string => {
const keyCodeAssocs = {
@ -128,6 +129,7 @@ const EventManager = () => {
<YellowTextManager eventState={eventState!} />
<MediaImageManager eventState={eventState!} />
<LevelManager eventState={eventState!} />
<MainMenuManager eventState={eventState!} />
</>
);
};

View file

@ -0,0 +1,41 @@
import { useCallback, useEffect } from "react";
import { StateManagerProps } from "./EventManager";
import { useMainMenuStore } from "../../store";
const MainMenuManager = (props: StateManagerProps) => {
const setActiveMainMenuElement = useMainMenuStore(
(state) => state.setActiveMainMenuElement
);
const dispatchObject = useCallback(
(event: string) => {
const dispatcherObjects = {
switch_to_load_data: {
action: setActiveMainMenuElement,
value: "load_data",
},
switch_to_authorize_user: {
action: setActiveMainMenuElement,
value: "authorize_user",
},
};
return dispatcherObjects[event as keyof typeof dispatcherObjects];
},
[setActiveMainMenuElement]
);
useEffect(() => {
if (props.eventState) {
const eventAction = props.eventState.event;
const dispatchedObject = dispatchObject(eventAction);
if (dispatchedObject) {
dispatchedObject.action(dispatchedObject.value);
}
}
}, [dispatchObject, props.eventState]);
return null;
};
export default MainMenuManager;

View file

@ -0,0 +1,14 @@
import { GameContext } from "./StateManagers/EventManager";
const handleBootMainMenuEvent = (gameContext: GameContext) => {
const keyPress = gameContext.keyPress;
switch (keyPress) {
case "down":
return { event: "switch_to_load_data" };
case "up":
return { event: "switch_to_authorize_user" };
}
};
export default handleBootMainMenuEvent;

View file

@ -1,6 +1,7 @@
import { GameContext } from "./StateManagers/EventManager";
import handleMainSceneEvent from "./mainSceneEventHandler";
import handleMediaSceneEvent from "./mediaSceneEventHandler";
import handleBootMainMenuEvent from "./bootMainMenuEventHandler";
const computeAction = (gameContext: GameContext) => {
switch (gameContext.scene) {
@ -8,6 +9,8 @@ const computeAction = (gameContext: GameContext) => {
return handleMainSceneEvent(gameContext);
case "media":
return handleMediaSceneEvent(gameContext);
case "boot":
return handleBootMainMenuEvent(gameContext);
}
};

View file

@ -1,12 +1,26 @@
import React from "react";
import React, { useEffect, useState } from "react";
import BootAccela from "../components/Boot/BootAccela";
import BootAnimation from "../components/Boot/BootAnimation";
import BootMainMenu from "../components/Boot/BootMainMenu";
const BootScene = () => {
const [accelaVisible, setAccelaVisible] = useState(true);
const [mainMenuVisible, setMainMenuVisible] = useState(false);
useEffect(() => {
setTimeout(() => {
setAccelaVisible(false);
}, 2000);
setTimeout(() => {
setMainMenuVisible(true);
}, 6200);
}, []);
return (
<perspectiveCamera position-z={3}>
{/*<BootAccela />*/}
<BootAnimation />
<BootAccela visible={accelaVisible} />
<BootAnimation visible={!accelaVisible} />
<BootMainMenu visible={mainMenuVisible} />
</perspectiveCamera>
);
};

View file

@ -159,6 +159,11 @@ type ImageState = {
};
};
type MainMenuState ={
activeMainMenuElement: string;
setActiveMainMenuElement: (to: string) => void;
}
export const useTextRendererStore = create<TextRendererState>((set) => ({
// yellow text
yellowText: "Play",
@ -384,6 +389,11 @@ export const useSceneStore = create<SceneState>((set) => ({
setScene: (to) => set(() => ({ currentScene: to })),
}));
export const useMainMenuStore = create<MainMenuState>(set=> ({
activeMainMenuElement: "authorize_user",
setActiveMainMenuElement: (to) => set(() => ({activeMainMenuElement: to}))
}))
export const useImageStore = create(
combine(
{