media scene code improvement, renamed blue orbs to nodes (their actual names)

This commit is contained in:
ad044 2020-11-17 19:31:06 +04:00
parent edb67baf9a
commit c4668b8fa1
27 changed files with 579 additions and 651 deletions

View file

@ -1,12 +1,12 @@
import React, { useMemo } from "react";
import BlueOrb from "./BlueOrb";
import blue_orb_positions from "../../resources/blue_orb_positions.json";
import Node from "./Node";
import node_positions from "../../resources/node_positions.json";
import site_a from "../../resources/site_a.json";
import { useBlueOrbStore, useLevelStore, useSiteStore } from "../../store";
import { useNodeStore, useLevelStore, useSiteStore } from "../../store";
import { a, useSpring } from "@react-spring/three";
const CurrentLevelNodes = () => {
const activeBlueOrbId = useBlueOrbStore((state) => state.activeBlueOrbId);
const activeNodeId = useNodeStore((state) => state.activeNodeId);
const currentLevel = useLevelStore((state) => state.currentLevel);
const currentLevelNodes = useMemo(
@ -25,23 +25,23 @@ const CurrentLevelNodes = () => {
return (
<a.group rotation-y={siteState.siteRotY} position-y={siteState.sitePosY}>
{Object.entries(currentLevelNodes).map((blueOrb: [string, any]) => {
{Object.entries(currentLevelNodes).map((node: [string, any]) => {
return (
<BlueOrb
sprite={blueOrb[1].node_name}
<Node
sprite={node[1].node_name}
position={
blue_orb_positions[
blueOrb[0].substr(2) as keyof typeof blue_orb_positions
node_positions[
node[0].substr(2) as keyof typeof node_positions
].position
}
rotation={
blue_orb_positions[
blueOrb[0].substr(2) as keyof typeof blue_orb_positions
node_positions[
node[0].substr(2) as keyof typeof node_positions
].rotation
}
key={blueOrb[1].node_name}
active={blueOrb[0] === activeBlueOrbId}
level={blueOrb[0].substr(0, 2)}
key={node[1].node_name}
active={node[0] === activeNodeId}
level={node[0].substr(0, 2)}
/>
);
})}

View file

@ -8,8 +8,8 @@ import longHudMirrored from "../../static/sprite/long_hud_mirrored.png";
import boringHud from "../../static/sprite/long_hud_boring.png";
import boringHudMirrored from "../../static/sprite/long_hud_boring_mirrored.png";
import { a, useSpring } from "@react-spring/three";
import {useBlueOrbStore, useHudStore} from "../../store";
import blue_orb_huds from "../../resources/blue_orb_huds.json";
import {useNodeStore, useHudStore} from "../../store";
import node_huds from "../../resources/node_huds.json";
const HUD = memo(() => {
const hudActive = useHudStore((state) => state.hudActive);
@ -17,7 +17,7 @@ const HUD = memo(() => {
const hudVisible = useHudStore((state) => state.hudVisible);
const currentHud = blue_orb_huds[currentHudId as keyof typeof blue_orb_huds];
const currentHud = node_huds[currentHudId as keyof typeof node_huds];
const hudElementState = useSpring({
bigHUDPositionX: hudActive,

View file

@ -8,7 +8,7 @@ import moveLeftSpriteSheet from "../../static/sprite/move_left.png";
import moveRightSpriteSheet from "../../static/sprite/move_right.png";
import standingSpriteSheet from "../../static/sprite/standing.png";
import introSpriteSheet from "../../static/sprite/intro.png";
import throwBlueOrbSpriteSheet from "../../static/sprite/throw_blue_orb.png";
import throwNodeSpriteSheet from "../../static/sprite/throw_node.png";
import { useLainStore } from "../../store";
type LainConstructorProps = {
@ -101,10 +101,10 @@ export const LainMoveUp = () => (
/>
);
export const LainThrowBlueOrb = () => {
export const LainThrowNode = () => {
return (
<LainConstructor
sprite={throwBlueOrbSpriteSheet}
sprite={throwNodeSpriteSheet}
frameCount={47}
framesHorizontal={7}
framesVertical={7}
@ -121,7 +121,7 @@ const Lain = () => {
move_right: <LainMoveRight />,
move_up: <LainMoveUp />,
move_down: <LainMoveDown />,
throwBlueOrb: <LainThrowBlueOrb />,
throwNode: <LainThrowNode />,
};
return (

View file

@ -17,9 +17,9 @@ import LdaActive from "../../static/sprite/Lda_active.png";
import MULTI from "../../static/sprite/MULTI.png";
import MULTIActive from "../../static/sprite/MULTI_active.png";
import level_y_values from "../../resources/level_y_values.json";
import { useBlueOrbStore } from "../../store";
import { useNodeStore } from "../../store";
type BlueOrbContructorProps = {
type NodeContructorProps = {
sprite: string;
position: number[];
rotation: number[];
@ -27,7 +27,7 @@ type BlueOrbContructorProps = {
level: string;
};
const BlueOrb = (props: BlueOrbContructorProps) => {
const Node = (props: NodeContructorProps) => {
// the game only has a couple of sprite that it displays in the hub
// dynamically importnig them would be worse for performance,
// so we import all of them here and then use this function to
@ -116,52 +116,52 @@ const BlueOrb = (props: BlueOrbContructorProps) => {
// to avoid excess unnecessary renders (this is absolutely crucial for performance).
const [
{
activeBlueOrbPosX,
activeBlueOrbPosY,
activeBlueOrbPosZ,
activeBlueOrbRotZ,
activeNodePosX,
activeNodePosY,
activeNodePosZ,
activeNodeRotZ,
},
set,
] = useSpring(() => ({
activeBlueOrbPosX: useBlueOrbStore.getState().isActiveBlueOrbInteractedWith
? useBlueOrbStore.getState().activeBlueOrbPosX
activeNodePosX: useNodeStore.getState().isActiveNodeInteractedWith
? useNodeStore.getState().activeNodePosX
: props.position[0],
activeBlueOrbPosY: useBlueOrbStore.getState().isActiveBlueOrbInteractedWith
activeNodePosY: useNodeStore.getState().isActiveNodeInteractedWith
? level_y_values[props.level as keyof typeof level_y_values]
: props.position[1],
activeBlueOrbPosZ: useBlueOrbStore.getState().isActiveBlueOrbInteractedWith
? useBlueOrbStore.getState().activeBlueOrbPosZ
activeNodePosZ: useNodeStore.getState().isActiveNodeInteractedWith
? useNodeStore.getState().activeNodePosZ
: props.position[2],
activeBlueOrbRotZ: useBlueOrbStore.getState().isActiveBlueOrbInteractedWith
? useBlueOrbStore.getState().activeBlueOrbRotZ
activeNodeRotZ: useNodeStore.getState().isActiveNodeInteractedWith
? useNodeStore.getState().activeNodeRotZ
: 0,
config: { duration: 800 },
}));
useEffect(() => {
useBlueOrbStore.subscribe(set, (state) => ({
activeBlueOrbPosX: useBlueOrbStore.getState()
.isActiveBlueOrbInteractedWith
? state.activeBlueOrbPosX
useNodeStore.subscribe(set, (state) => ({
activeNodePosX: useNodeStore.getState()
.isActiveNodeInteractedWith
? state.activeNodePosX
: props.position[0],
activeBlueOrbPosY: useBlueOrbStore.getState()
.isActiveBlueOrbInteractedWith
activeNodePosY: useNodeStore.getState()
.isActiveNodeInteractedWith
? level_y_values[props.level as keyof typeof level_y_values]
: props.position[1],
activeBlueOrbPosZ: useBlueOrbStore.getState()
.isActiveBlueOrbInteractedWith
? state.activeBlueOrbPosZ
activeNodePosZ: useNodeStore.getState()
.isActiveNodeInteractedWith
? state.activeNodePosZ
: props.position[2],
activeBlueOrbRotZ: useBlueOrbStore.getState()
.isActiveBlueOrbInteractedWith
? state.activeBlueOrbRotZ
activeNodeRotZ: useNodeStore.getState()
.isActiveNodeInteractedWith
? state.activeNodeRotZ
: 0,
}));
}, [
props.level,
activeBlueOrbPosX,
activeBlueOrbPosZ,
activeBlueOrbRotZ,
activeNodePosX,
activeNodePosZ,
activeNodeRotZ,
props.position,
set,
]);
@ -176,10 +176,10 @@ const BlueOrb = (props: BlueOrbContructorProps) => {
>
{props.active ? (
<a.mesh
position-x={activeBlueOrbPosX}
position-y={activeBlueOrbPosY}
position-z={activeBlueOrbPosZ}
rotation-z={activeBlueOrbRotZ}
position-x={activeNodePosX}
position-y={activeNodePosY}
position-z={activeNodePosZ}
rotation-z={activeNodeRotZ}
rotation-y={props.rotation[1]}
scale={[0.36, 0.18, 0.36]}
renderOrder={1}
@ -218,4 +218,4 @@ const BlueOrb = (props: BlueOrbContructorProps) => {
);
};
export default BlueOrb;
export default Node;

View file

@ -1,8 +1,8 @@
import React, { memo, Suspense, useMemo } from "react";
import site_a from "../../resources/site_a.json";
import level_y_values from "../../resources/level_y_values.json";
import blue_orb_positions from "../../resources/blue_orb_positions.json";
import BlueOrb from "./BlueOrb";
import node_positions from "../../resources/node_positions.json";
import Node from "./Node";
import { a, useSpring } from "@react-spring/three";
import { useLevelStore, useSiteStore } from "../../store";
import PurpleRing from "./PurpleRing";
@ -66,21 +66,21 @@ const Site = memo(() => {
<CyanCrystal crystalRingPosY={-0.45} />
</group>
))}
{Object.entries(visibleNodes).map((blueOrb: [string, any]) => (
<BlueOrb
sprite={blueOrb[1].node_name}
{Object.entries(visibleNodes).map((node: [string, any]) => (
<Node
sprite={node[1].node_name}
position={
blue_orb_positions[
blueOrb[0].substr(2) as keyof typeof blue_orb_positions
node_positions[
node[0].substr(2) as keyof typeof node_positions
].position
}
rotation={
blue_orb_positions[
blueOrb[0].substr(2) as keyof typeof blue_orb_positions
node_positions[
node[0].substr(2) as keyof typeof node_positions
].rotation
}
key={blueOrb[1].node_name}
level={blueOrb[0].substr(0, 2)}
key={node[1].node_name}
level={node[0].substr(0, 2)}
/>
))}
)

View file

@ -5,8 +5,8 @@ import t from "../../static/webvtt/test.vtt";
const MediaPlayer = () => {
const currentScene = useSceneStore((state) => state.currentScene);
const setMediaPercentageElapsed = useMediaStore(
(state) => state.setMediaPercentageElapsed
const setPercentageElapsed = useMediaStore(
(state) => state.setPercentageElapsed
);
const requestRef = useRef();
@ -20,10 +20,10 @@ const MediaPlayer = () => {
const percentageElapsed = Math.floor((timeElapsed / duration) * 100);
if (percentageElapsed % 5 === 0) {
setMediaPercentageElapsed(percentageElapsed);
setPercentageElapsed(percentageElapsed);
}
}
}, [setMediaPercentageElapsed, videoRef]);
}, [setPercentageElapsed, videoRef]);
React.useEffect(() => {
(requestRef.current as any) = requestAnimationFrame(updateTime);

View file

@ -10,7 +10,7 @@ import longHudSpriteSheet from "../static/sprite/long_hud.png";
import longHudMirroredSpriteSheet from "../static/sprite/long_hud_mirrored.png";
import boringHudSpriteSheet from "../static/sprite/long_hud_boring.png";
import boringHudMirroredSpriteSheet from "../static/sprite/long_hud_boring_mirrored.png";
import throwBlueOrbSpriteSheet from "../static/sprite/throw_blue_orb.png";
import throwNodeSpriteSheet from "../static/sprite/throw_node.png";
import * as THREE from "three";
import { useLoader, useThree } from "react-three-fiber";
@ -25,7 +25,7 @@ const Preloader = () => {
const moveLeft = useLoader(THREE.TextureLoader, moveLeftSpriteSheet);
const moveRight = useLoader(THREE.TextureLoader, moveRightSpriteSheet);
const stand = useLoader(THREE.TextureLoader, standingSpriteSheet);
const throwBlueOrb = useLoader(THREE.TextureLoader, throwBlueOrbSpriteSheet);
const throwNode = useLoader(THREE.TextureLoader, throwNodeSpriteSheet);
const bigHud = useLoader(THREE.TextureLoader, bigHudSpriteSheet);
const bigHudMirrored = useLoader(
THREE.TextureLoader,
@ -56,7 +56,7 @@ const Preloader = () => {
gl.initTexture(longHudMirrored);
gl.initTexture(boringHud);
gl.initTexture(boringHudMirrored);
gl.initTexture(throwBlueOrb);
gl.initTexture(throwNode);
}, [
moveDown,
moveUp,
@ -71,7 +71,7 @@ const Preloader = () => {
longHud,
longHudMirrored,
intro,
throwBlueOrb,
throwNode,
]);
return null;
};

View file

@ -1,163 +0,0 @@
import { useCallback, useEffect } from "react";
import { useBlueOrbStore } from "../../store";
import { StateManagerProps } from "./EventManager";
type UpdateActiveBlueOrb = (
newActiveBlueOrbId: string,
newBlueOrbColIdx: number,
newBlueOrbRowIdx: number
) => void;
type SetIsActiveBlueOrbInteractedWith = (value: boolean) => void;
type BlueOrbDispatchData = {
action: any;
value: any;
};
type BlueOrbDispatcher = {
move_up: BlueOrbDispatchData;
move_down: BlueOrbDispatchData;
move_left: BlueOrbDispatchData;
move_right: BlueOrbDispatchData;
change_blue_orb: BlueOrbDispatchData;
throw_blue_orb_media: BlueOrbDispatchData;
throw_blue_orb_gate: BlueOrbDispatchData;
};
const BlueOrbManager = (props: StateManagerProps) => {
const setActiveBlueOrb = useBlueOrbStore((state) => state.setActiveBlueOrbId);
const setBlueOrbMatrixIndices = useBlueOrbStore(
(state) => state.setBlueOrbMatrixIndices
);
const setIsActiveBlueOrbInteractedWith: SetIsActiveBlueOrbInteractedWith = useBlueOrbStore(
(state) => state.setIsActiveBlueOrbInteractedWith
);
const setActiveBlueOrbPosX = useBlueOrbStore(
(state) => state.setActiveBlueOrbPosX
);
const setActiveBlueOrbPosZ = useBlueOrbStore(
(state) => state.setActiveBlueOrbPosZ
);
const setActiveBlueOrbRotZ = useBlueOrbStore(
(state) => state.setActiveBlueOrbRotZ
);
const animateActiveBlueOrbThrow = useCallback(() => {
setIsActiveBlueOrbInteractedWith(true);
setActiveBlueOrbPosZ(0.3);
setActiveBlueOrbPosX(0.9);
setTimeout(() => {
setActiveBlueOrbPosZ(0.2);
setActiveBlueOrbPosX(0.5);
}, 800);
setTimeout(() => {
setActiveBlueOrbPosX(1.55);
setActiveBlueOrbRotZ(-0.005);
}, 2600);
setTimeout(() => {
setActiveBlueOrbPosZ(2);
setActiveBlueOrbPosX(0);
setActiveBlueOrbRotZ(-0.5);
}, 2700);
setTimeout(() => {
setActiveBlueOrbRotZ(0);
setIsActiveBlueOrbInteractedWith(false);
}, 3800);
}, [
setActiveBlueOrbPosX,
setActiveBlueOrbPosZ,
setActiveBlueOrbRotZ,
setIsActiveBlueOrbInteractedWith,
]);
const updateActiveBlueOrb = useCallback(
(
delay: number,
isMoving: boolean,
newActiveBlueOrbId: string,
newBlueOrbColIdx: number,
newBlueOrbRowIdx: number
) => {
setTimeout(() => {
setActiveBlueOrb(newActiveBlueOrbId);
setBlueOrbMatrixIndices({
rowIdx: newBlueOrbRowIdx,
colIdx: newBlueOrbColIdx,
});
}, delay);
},
[setActiveBlueOrb, setBlueOrbMatrixIndices]
);
const dispatchObject = useCallback(
(
event: string,
newActiveBlueOrbId: string,
newBlueOrbColIdx: number,
newBlueOrbRowIdx: number
) => {
switch (event) {
case "move_up":
case "move_down":
case "move_left":
case "move_right":
return {
action: updateActiveBlueOrb,
value: [
3903.704,
true,
newActiveBlueOrbId,
newBlueOrbColIdx,
newBlueOrbRowIdx,
],
};
case "change_blue_orb":
return {
action: updateActiveBlueOrb,
value: [
0,
false,
newActiveBlueOrbId,
newBlueOrbColIdx,
newBlueOrbRowIdx,
],
};
case "throw_blue_orb_media":
case "throw_blue_orb_gate":
return {
action: animateActiveBlueOrbThrow,
value: [0, true],
};
}
},
[animateActiveBlueOrbThrow, updateActiveBlueOrb]
);
useEffect(() => {
if (props.eventState) {
const eventAction = props.eventState.event;
const newActiveBlueOrbId = props.eventState.newActiveBlueOrbId;
const newBlueOrbRowIdx = props.eventState.newBlueOrbRowIdx;
const newBlueOrbColIdx = props.eventState.newBlueOrbColIdx;
const dispatchedObject = dispatchObject(
eventAction,
newActiveBlueOrbId,
newBlueOrbColIdx,
newBlueOrbRowIdx
);
if (dispatchedObject) {
dispatchedObject.action.apply(null, dispatchedObject.value as never);
}
}
}, [props.eventState, setActiveBlueOrb, dispatchObject]);
return null;
};
export default BlueOrbManager;

View file

@ -2,10 +2,10 @@ import React, { useCallback, useEffect, useMemo, useState } from "react";
import SiteManager from "./SiteManager";
import MiddleRingManager from "./MiddleRingManager";
import LainManager from "./LainManager";
import BlueOrbManager from "./BlueOrbManager";
import BlueOrbHUDManager from "./BlueOrbHUDManager";
import NodeManager from "./NodeManager";
import NodeHUDManager from "./NodeHUDManager";
import {
useBlueOrbStore,
useNodeStore,
useBootStore,
useLevelStore,
useMediaStore,
@ -39,10 +39,10 @@ const getKeyCodeAssociation = (keyCode: number): string => {
type EventState = {
event: string;
newBlueOrbColIdx: number;
newBlueOrbRowIdx: number;
newNodeColIdx: number;
newNodeRowIdx: number;
newLevel: string;
newActiveBlueOrbId: string;
newActiveNodeId: string;
newSiteRotIdx: string;
};
@ -54,7 +54,7 @@ export type GameContext = {
keyPress?: string;
scene: string;
subscene: string;
blueOrbMatrixIndices: { rowIdx: number; colIdx: number };
nodeMatrixIndices: { rowIdx: number; colIdx: number };
currentLevel: string;
siteRotIdx: string;
activeMediaComponent: string;
@ -66,17 +66,29 @@ const EventManager = () => {
const currentSubscene = useSubsceneStore((state) => state.activeSubscene);
// main scene
const blueOrbMatrixIndices = useBlueOrbStore(
(state) => state.blueOrbMatrixIndices
);
const nodeMatrixIndices = useNodeStore((state) => state.nodeMatrixIndices);
const siteRotIdx = useSiteStore((state) => state.siteRotIdx);
const currentLevel = useLevelStore((state) => state.currentLevel);
// media scene
const activeMediaComponent = useMediaStore(
(state) => state.activeMediaComponent
const mediaComponentMatrixIndices = useMediaStore(
(state) => state.componentMatrixIndices
);
const activeMediaComponent = useMediaStore(
useCallback(
(state) =>
state.componentMatrix[mediaComponentMatrixIndices.sideIdx][
mediaComponentMatrixIndices.sideIdx === 0
? mediaComponentMatrixIndices.leftSideIdx
: mediaComponentMatrixIndices.rightSideIdx
],
[mediaComponentMatrixIndices]
)
);
console.log(activeMediaComponent)
// boot scene
const activeBootElement = useBootStore((state) => state.activeBootElement);
@ -89,7 +101,7 @@ const EventManager = () => {
scene: currentScene,
subscene: currentSubscene,
siteRotIdx: siteRotIdx,
blueOrbMatrixIndices: blueOrbMatrixIndices,
nodeMatrixIndices: nodeMatrixIndices,
currentLevel: currentLevel,
activeMediaComponent: activeMediaComponent,
activeBootElement: activeBootElement,
@ -97,7 +109,7 @@ const EventManager = () => {
[
activeBootElement,
activeMediaComponent,
blueOrbMatrixIndices,
nodeMatrixIndices,
currentLevel,
currentScene,
currentSubscene,
@ -130,8 +142,8 @@ const EventManager = () => {
return (
<>
<BlueOrbManager eventState={eventState!} />
<BlueOrbHUDManager eventState={eventState!} />
<NodeManager eventState={eventState!} />
<NodeHUDManager eventState={eventState!} />
<GreenTextManager eventState={eventState!} />
<SiteManager eventState={eventState!} />
<LainManager eventState={eventState!} />

View file

@ -1,7 +1,7 @@
import { useCallback, useEffect } from "react";
import { useTextRendererStore } from "../../store";
import { StateManagerProps } from "./EventManager";
import blue_orb_huds from "../../resources/blue_orb_huds.json";
import node_huds from "../../resources/node_huds.json";
import site_a from "../../resources/site_a.json";
import { SiteType } from "../../components/MainScene/Site";
@ -19,16 +19,16 @@ const GreenTextManager = (props: StateManagerProps) => {
const toggleAndSetGreenText = useCallback(
(
newActiveBlueOrbId: string,
newActiveNodeId: string,
newActiveHudId: string,
newLevel: string,
delay: number
) => {
const targetGreenText = (site_a as SiteType)[newLevel][newActiveBlueOrbId]
const targetGreenText = (site_a as SiteType)[newLevel][newActiveNodeId]
.title;
const targetGreenTextPosData =
blue_orb_huds[newActiveHudId as keyof typeof blue_orb_huds].medium_text;
node_huds[newActiveHudId as keyof typeof node_huds].medium_text;
toggleGreenText();
@ -46,9 +46,9 @@ const GreenTextManager = (props: StateManagerProps) => {
);
const initializeGreenTextForMediaScene = useCallback(
(activeBlueOrbId: string, level: string) => {
(activeNodeId: string, level: string) => {
setTimeout(() => {
setGreenText((site_a as SiteType)[level][activeBlueOrbId].node_name);
setGreenText((site_a as SiteType)[level][activeNodeId].node_name);
setGreenTextPosX({ initial: 0.0, final: 0.009 });
setGreenTextPosY(0.675);
}, 3950);
@ -59,7 +59,7 @@ const GreenTextManager = (props: StateManagerProps) => {
const dispatchObject = useCallback(
(
event: string,
newActiveBlueOrbId: string,
newActiveNodeId: string,
newActiveHudId: string,
newLevel: string
) => {
@ -70,17 +70,17 @@ const GreenTextManager = (props: StateManagerProps) => {
case "move_right":
return {
action: toggleAndSetGreenText,
value: [newActiveBlueOrbId, newActiveHudId, newLevel, 3903.704],
value: [newActiveNodeId, newActiveHudId, newLevel, 3903.704],
};
case "change_blue_orb":
case "change_node":
return {
action: toggleAndSetGreenText,
value: [newActiveBlueOrbId, newActiveHudId, newLevel, 500],
value: [newActiveNodeId, newActiveHudId, newLevel, 500],
};
case "throw_blue_orb_media":
case "throw_node_media":
return {
action: initializeGreenTextForMediaScene,
value: [newActiveBlueOrbId, newLevel],
value: [newActiveNodeId, newLevel],
};
}
},
@ -90,13 +90,13 @@ const GreenTextManager = (props: StateManagerProps) => {
useEffect(() => {
if (props.eventState) {
const eventAction = props.eventState.event;
const newActiveBlueOrbId = props.eventState.newActiveBlueOrbId;
const newActiveNodeId = props.eventState.newActiveNodeId;
const newActiveHudId = props.eventState.newActiveHudId;
const newLevel = props.eventState.newLevel;
const dispatchedObject = dispatchObject(
eventAction,
newActiveBlueOrbId,
newActiveNodeId,
newActiveHudId,
newLevel
);

View file

@ -28,14 +28,14 @@ const LainManager = (props: StateManagerProps) => {
value: "move_right",
duration: 3904.704,
},
throw_blue_orb_media: {
throw_node_media: {
action: setLainMoveState,
value: "throwBlueOrb",
value: "throwNode",
duration: 3904.704,
},
throw_blue_orb_gate: {
throw_node_gate: {
action: setLainMoveState,
value: "throwBlueOrb",
value: "throwNode",
duration: 3904.704,
},
};

View file

@ -3,113 +3,60 @@ import { StateManagerProps } from "./EventManager";
import { useMediaStore } from "../../store";
const MediaComponentManager = (props: StateManagerProps) => {
const setActiveMediaComponent = useMediaStore(
(state) => state.setActiveMediaComponent
const toggleSide = useMediaStore((state) => state.toggleSide);
const toggleLeftComponent = useMediaStore(
(state) => state.toggleLeftComponent
);
const addToRightComponentMatrixIdx = useMediaStore(
(state) => state.addToRightComponentMatrixIdx
);
const setLastActiveLeftSideElement = useMediaStore(
(state) => state.setLastActiveLeftSideElement
);
const lastActiveLeftSideElement = useMediaStore(
(state) => state.lastActiveLeftSideElement
);
const setLastActiveRightSideElement = useMediaStore(
(state) => state.setLastActiveRightSideElement
);
const lastActiveRightSideElement = useMediaStore(
(state) => state.lastActiveRightSideElement
);
const switchToLeftSide = useCallback(
(from: string) => {
setActiveMediaComponent(lastActiveLeftSideElement);
// store last active right side elem
setLastActiveRightSideElement(from);
},
[
lastActiveLeftSideElement,
setActiveMediaComponent,
setLastActiveRightSideElement,
]
);
const switchToRightSide = useCallback(
(from: string) => {
setActiveMediaComponent(lastActiveRightSideElement);
// store last active left side elem
setLastActiveLeftSideElement(from);
},
[
lastActiveRightSideElement,
setActiveMediaComponent,
setLastActiveLeftSideElement,
]
const resetComponentMatrixIndices = useMediaStore(
(state) => state.resetComponentMatrixIndices
);
const dispatchObject = useCallback(
(event: string) => {
const dispatcherObjects = {
fstWord_up: {
action: setActiveMediaComponent,
value: "thirdWord",
},
fstWord_down: {
action: setActiveMediaComponent,
value: "sndWord",
},
sndWord_up: {
action: setActiveMediaComponent,
value: "fstWord",
},
sndWord_down: {
action: setActiveMediaComponent,
value: "thirdWord",
},
thirdWord_down: {
action: setActiveMediaComponent,
value: "fstWord",
},
thirdWord_up: {
action: setActiveMediaComponent,
value: "sndWord",
},
play_down: {
action: setActiveMediaComponent,
value: "exit",
},
exit_up: {
action: setActiveMediaComponent,
value: "play",
},
play_right: {
action: switchToRightSide,
value: "play",
},
exit_right: {
action: switchToRightSide,
value: "exit",
},
fstWord_left: {
action: switchToLeftSide,
value: "fstWord",
},
sndWord_left: {
action: switchToLeftSide,
value: "sndWord",
},
thirdWord_left: {
action: switchToLeftSide,
value: "thirdWord",
},
throw_blue_orb_media: {
action: setActiveMediaComponent,
value: "play",
},
};
return dispatcherObjects[event as keyof typeof dispatcherObjects];
switch (event) {
case "fstWord_down":
case "sndWord_down":
case "thirdWord_down":
return {
action: addToRightComponentMatrixIdx,
value: [1],
};
case "fstWord_up":
case "thirdWord_up":
case "sndWord_up":
return {
action: addToRightComponentMatrixIdx,
value: [-1],
};
case "play_down":
case "exit_up":
return {
action: toggleLeftComponent,
};
case "play_right":
case "exit_right":
case "fstWord_left":
case "sndWord_left":
case "thirdWord_left":
return {
action: toggleSide,
};
case "throw_node_media":
return {
action: resetComponentMatrixIndices,
};
}
},
[setActiveMediaComponent, switchToLeftSide, switchToRightSide]
[
addToRightComponentMatrixIdx,
resetComponentMatrixIndices,
toggleLeftComponent,
toggleSide,
]
);
useEffect(() => {
@ -119,7 +66,7 @@ const MediaComponentManager = (props: StateManagerProps) => {
const dispatchedObject = dispatchObject(eventAction);
if (dispatchedObject) {
dispatchedObject.action(dispatchedObject.value);
dispatchedObject.action.apply(null, dispatchedObject.value);
}
}
}, [props.eventState, dispatchObject]);

View file

@ -16,8 +16,8 @@ const MediaImageManager = (props: StateManagerProps) => {
);
const updateSceneImages = useCallback(
(newActiveBlueOrbId: string) => {
const nodeName = currentLevelData[newActiveBlueOrbId].node_name;
(newActiveNodeId: string) => {
const nodeName = currentLevelData[newActiveNodeId].node_name;
const images = image_table[nodeName as keyof typeof image_table];
Object.values(images).forEach((img) => {
@ -52,11 +52,11 @@ const MediaImageManager = (props: StateManagerProps) => {
);
const dispatchObject = useCallback(
(event: string, newActiveBlueOrbId: string) => {
(event: string, newActiveNodeId: string) => {
const dispatcherObjects = {
throw_blue_orb_media: {
throw_node_media: {
action: updateSceneImages,
value: newActiveBlueOrbId,
value: newActiveNodeId,
},
};
@ -68,8 +68,8 @@ const MediaImageManager = (props: StateManagerProps) => {
useEffect(() => {
if (props.eventState) {
const eventAction = props.eventState.event;
const newActiveBlueOrbId = props.eventState.newActiveBlueOrbId;
const dispatchedObject = dispatchObject(eventAction, newActiveBlueOrbId);
const newActiveNodeId = props.eventState.newActiveNodeId;
const dispatchedObject = dispatchObject(eventAction, newActiveNodeId);
if (dispatchedObject) {
dispatchedObject.action(dispatchedObject.value);

View file

@ -2,21 +2,6 @@ import { useCallback, useEffect } from "react";
import { StateManagerProps } from "./EventManager";
import { useMediaWordStore } from "../../store";
type MediaWordDispatcher = {
action: any;
value?: number;
};
type MediaWordDispatchData = {
fstWord_down: MediaWordDispatcher;
fstWord_up: MediaWordDispatcher;
sndWord_down: MediaWordDispatcher;
sndWord_up: MediaWordDispatcher;
thirdWord_down: MediaWordDispatcher;
thirdWord_up: MediaWordDispatcher;
throw_blue_orb_media: MediaWordDispatcher;
};
const MediaWordManager = (props: StateManagerProps) => {
const addToWordPositionDataStructIdx = useMediaWordStore(
(state) => state.addToWordPositionDataStructIdx
@ -27,37 +12,26 @@ const MediaWordManager = (props: StateManagerProps) => {
const dispatchObject = useCallback(
(event: string) => {
const dispatcherObjects: MediaWordDispatchData = {
fstWord_down: {
action: addToWordPositionDataStructIdx,
value: 1,
},
fstWord_up: {
action: addToWordPositionDataStructIdx,
value: -1,
},
sndWord_down: {
action: addToWordPositionDataStructIdx,
value: 1,
},
sndWord_up: {
action: addToWordPositionDataStructIdx,
value: -1,
},
thirdWord_down: {
action: addToWordPositionDataStructIdx,
value: 1,
},
thirdWord_up: {
action: addToWordPositionDataStructIdx,
value: -1,
},
throw_blue_orb_media: {
action: resetWordPositionDataStructIdx,
},
};
return dispatcherObjects[event as keyof typeof dispatcherObjects];
switch (event) {
case "fstWord_down":
case "sndWord_down":
case "thirdWord_down":
return {
action: addToWordPositionDataStructIdx,
value: 1,
};
case "fstWord_up":
case "sndWord_up":
case "thirdWord_up":
return {
action: addToWordPositionDataStructIdx,
value: -1,
};
case "throw_node_media":
return {
action: resetWordPositionDataStructIdx,
};
}
},
[addToWordPositionDataStructIdx, resetWordPositionDataStructIdx]
);
@ -69,7 +43,7 @@ const MediaWordManager = (props: StateManagerProps) => {
const dispatchedObject = dispatchObject(eventAction);
if (dispatchedObject) {
dispatchedObject.action(dispatchedObject.value);
dispatchedObject.action(dispatchedObject.value as any);
}
}
}, [props.eventState, dispatchObject]);

View file

@ -2,33 +2,33 @@ import { useCallback, useEffect } from "react";
import { useHudStore } from "../../store";
import { StateManagerProps } from "./EventManager";
const BlueOrbHUDManager = (props: StateManagerProps) => {
const setActiveBlueOrbHudId = useHudStore(
(state) => state.setActiveBlueOrbHudId
const NodeHUDManager = (props: StateManagerProps) => {
const setActiveNodeHudId = useHudStore(
(state) => state.setActiveNodeHudId
);
const toggleHud = useHudStore((state) => state.toggleHud);
const dispatchObject = useCallback(
(event: string, targetBlueOrbHudId: string) => {
(event: string, targetNodeHudId: string) => {
switch (event) {
case "move_up":
case "move_down":
case "move_left":
case "move_right":
return {
action: setActiveBlueOrbHudId,
value: targetBlueOrbHudId,
action: setActiveNodeHudId,
value: targetNodeHudId,
actionDelay: 3903.704,
};
case "change_blue_orb":
case "change_node":
return {
action: setActiveBlueOrbHudId,
value: targetBlueOrbHudId,
action: setActiveNodeHudId,
value: targetNodeHudId,
actionDelay: 500,
};
}
},
[setActiveBlueOrbHudId]
[setActiveNodeHudId]
);
useEffect(() => {
@ -47,8 +47,8 @@ const BlueOrbHUDManager = (props: StateManagerProps) => {
}, dispatchedObject.actionDelay);
}
}
}, [props.eventState, setActiveBlueOrbHudId, toggleHud, dispatchObject]);
}, [props.eventState, setActiveNodeHudId, toggleHud, dispatchObject]);
return null;
};
export default BlueOrbHUDManager;
export default NodeHUDManager;

View file

@ -0,0 +1,130 @@
import { useCallback, useEffect } from "react";
import { useNodeStore } from "../../store";
import { StateManagerProps } from "./EventManager";
type SetIsActiveNodeInteractedWith = (value: boolean) => void;
const NodeManager = (props: StateManagerProps) => {
const setActiveNode = useNodeStore((state) => state.setActiveNodeId);
const setNodeMatrixIndices = useNodeStore(
(state) => state.setNodeMatrixIndices
);
const setIsActiveNodeInteractedWith: SetIsActiveNodeInteractedWith = useNodeStore(
(state) => state.setIsActiveNodeInteractedWith
);
const setActiveNodePosX = useNodeStore((state) => state.setActiveNodePosX);
const setActiveNodePosZ = useNodeStore((state) => state.setActiveNodePosZ);
const setActiveNodeRotZ = useNodeStore((state) => state.setActiveNodeRotZ);
const animateActiveNodeThrow = useCallback(() => {
setIsActiveNodeInteractedWith(true);
setActiveNodePosZ(0.3);
setActiveNodePosX(0.9);
setTimeout(() => {
setActiveNodePosZ(0.2);
setActiveNodePosX(0.5);
}, 800);
setTimeout(() => {
setActiveNodePosX(1.55);
setActiveNodeRotZ(-0.005);
}, 2600);
setTimeout(() => {
setActiveNodePosZ(2);
setActiveNodePosX(0);
setActiveNodeRotZ(-0.5);
}, 2700);
setTimeout(() => {
setActiveNodeRotZ(0);
setIsActiveNodeInteractedWith(false);
}, 3800);
}, [
setActiveNodePosX,
setActiveNodePosZ,
setActiveNodeRotZ,
setIsActiveNodeInteractedWith,
]);
const updateActiveNode = useCallback(
(
delay: number,
isMoving: boolean,
newActiveNodeId: string,
newNodeColIdx: number,
newNodeRowIdx: number
) => {
setTimeout(() => {
setActiveNode(newActiveNodeId);
setNodeMatrixIndices({
rowIdx: newNodeRowIdx,
colIdx: newNodeColIdx,
});
}, delay);
},
[setActiveNode, setNodeMatrixIndices]
);
const dispatchObject = useCallback(
(
event: string,
newActiveNodeId: string,
newNodeColIdx: number,
newNodeRowIdx: number
) => {
switch (event) {
case "move_up":
case "move_down":
case "move_left":
case "move_right":
return {
action: updateActiveNode,
value: [
3903.704,
true,
newActiveNodeId,
newNodeColIdx,
newNodeRowIdx,
],
};
case "change_node":
return {
action: updateActiveNode,
value: [0, false, newActiveNodeId, newNodeColIdx, newNodeRowIdx],
};
case "throw_node_media":
case "throw_node_gate":
return {
action: animateActiveNodeThrow,
value: [0, true],
};
}
},
[animateActiveNodeThrow, updateActiveNode]
);
useEffect(() => {
if (props.eventState) {
const eventAction = props.eventState.event;
const newActiveNodeId = props.eventState.newActiveNodeId;
const newNodeRowIdx = props.eventState.newNodeRowIdx;
const newNodeColIdx = props.eventState.newNodeColIdx;
const dispatchedObject = dispatchObject(
eventAction,
newActiveNodeId,
newNodeColIdx,
newNodeRowIdx
);
if (dispatchedObject) {
dispatchedObject.action.apply(null, dispatchedObject.value as never);
}
}
}, [props.eventState, setActiveNode, dispatchObject]);
return null;
};
export default NodeManager;

View file

@ -7,29 +7,22 @@ const SceneManager = (props: StateManagerProps) => {
const dispatchObject = useCallback(
(event: string, newScene: string) => {
const dispatcherObjects = {
throw_blue_orb_media: {
action: setScene,
value: newScene,
delay: 3904.704,
},
throw_blue_orb_gate: {
action: setScene,
value: newScene,
delay: 3904.704,
},
exit_select: {
action: setScene,
value: "main",
delay: 0,
},
exit_gate: {
action: setScene,
value: "main",
delay: 0,
},
};
return dispatcherObjects[event as keyof typeof dispatcherObjects];
switch (event) {
case "throw_node_media":
case "throw_node_gate":
return {
action: setScene,
value: newScene,
delay: 3904.704,
};
case "exit_select":
case "exit_gate":
return {
action: setScene,
value: "main",
delay: 0,
};
}
},
[setScene]
);

View file

@ -18,22 +18,32 @@ const SiteManager = (props: StateManagerProps) => {
const dispatchObject = useCallback(
(event: string, newSiteRotIdx: string) => {
const dispatcherObjects = {
move_up: { action: addToSitePosY, value: [-1.5], actionDelay: 1300 },
move_down: { action: addToSitePosY, value: [1.5], actionDelay: 1300 },
move_left: {
action: rotateSite,
value: [Math.PI / 4, newSiteRotIdx],
actionDelay: 1100,
},
move_right: {
action: rotateSite,
value: [-Math.PI / 4, newSiteRotIdx],
actionDelay: 1100,
},
};
return dispatcherObjects[event as keyof typeof dispatcherObjects];
switch (event) {
case "move_up":
return {
action: addToSitePosY,
value: [-1.5],
actionDelay: 1300,
};
case "move_down":
return {
action: addToSitePosY,
value: [1.5],
actionDelay: 1300,
};
case "move_left":
return {
action: rotateSite,
value: [Math.PI / 4, newSiteRotIdx],
actionDelay: 1100,
};
case "move_right":
return {
action: rotateSite,
value: [-Math.PI / 4, newSiteRotIdx],
actionDelay: 1100,
};
}
},
[addToSitePosY, rotateSite]
);

View file

@ -9,25 +9,25 @@ const SubSceneManager = (props: StateManagerProps) => {
const dispatchObject = useCallback(
(event: string) => {
const dispatcherObjects = {
authorize_user_back: {
action: setActiveSubscene,
value: "main_menu",
},
select_authorize_user: {
action: setActiveSubscene,
value: "authorize_user",
},
select_load_data: {
action: setActiveSubscene,
value: "load_data",
},
select_load_data_no: {
action: setActiveSubscene,
value: "main_menu",
},
};
return dispatcherObjects[event as keyof typeof dispatcherObjects];
switch (event) {
case "authorize_user_back":
return {
action: setActiveSubscene,
value: "main_menu",
};
case "select_authorize_user":
return { action: setActiveSubscene, value: "authorize_user" };
case "select_load_data":
return {
action: setActiveSubscene,
value: "load_data",
};
case "select_load_data_no":
return {
action: setActiveSubscene,
value: "main_menu",
};
}
},
[setActiveSubscene]
);

View file

@ -1,29 +1,9 @@
import { useCallback, useEffect } from "react";
import blue_orb_huds from "../../resources/blue_orb_huds.json";
import node_huds from "../../resources/node_huds.json";
import site_a from "../../resources/site_a.json";
import { useTextRendererStore } from "../../store";
import { SiteType } from "../../components/MainScene/Site";
type AnimateYellowTextWithMove = (
yellowLetterPosYOffset: number,
yellowLetterPosXOffset: number,
newActiveHudId: string,
newActiveBlueOrbId: string,
newLevel: string,
delay: number
) => void;
type AnimateYellowTextWithoutMove = (
newActiveHudId: string,
newActiveBlueOrbId: string,
newLevel: string
) => void;
type AnimateMediaYellowText = (
targetMediaText: string,
targetMediaTextPos: number[]
) => void;
const YellowTextManager = (props: any) => {
const setYellowText = useTextRendererStore((state) => state.setYellowText);
@ -44,12 +24,12 @@ const YellowTextManager = (props: any) => {
(state) => state.setYellowTextPosX
);
const animateYellowTextWithMove: AnimateYellowTextWithMove = useCallback(
const animateYellowTextWithMove = useCallback(
(
yellowLetterPosXOffset: number,
yellowLetterPosYOffset: number,
newActiveHudId: string,
newActiveBlueOrbId: string,
newActiveNodeId: string,
newLevel: string,
delay: number
) => {
@ -68,16 +48,14 @@ const YellowTextManager = (props: any) => {
setTimeout(() => {
// animate it to new pos x/y
setYellowTextPosX(
blue_orb_huds[newActiveHudId as keyof typeof blue_orb_huds]
.big_text[0]
node_huds[newActiveHudId as keyof typeof node_huds].big_text[0]
);
setYellowTextPosY(
blue_orb_huds[newActiveHudId as keyof typeof blue_orb_huds]
.big_text[1]
node_huds[newActiveHudId as keyof typeof node_huds].big_text[1]
);
// set new text according to the node name
setYellowText(
(site_a as SiteType)[newLevel][newActiveBlueOrbId].node_name
(site_a as SiteType)[newLevel][newActiveNodeId].node_name
);
}, 3000);
@ -96,28 +74,24 @@ const YellowTextManager = (props: any) => {
]
);
const animateYellowTextWithoutMove: AnimateYellowTextWithoutMove = useCallback(
(newActiveHudId: string, newActiveBlueOrbId: string, level: string) => {
const animateYellowTextWithoutMove = useCallback(
(newActiveHudId: string, newActiveNodeId: string, level: string) => {
// make current hud big text shrink
setYellowTextOffsetXCoeff(-1);
setTimeout(() => {
setYellowTextPosX(
blue_orb_huds[newActiveHudId as keyof typeof blue_orb_huds]
.big_text[0]
node_huds[newActiveHudId as keyof typeof node_huds].big_text[0]
);
setYellowTextPosY(
blue_orb_huds[newActiveHudId as keyof typeof blue_orb_huds]
.big_text[1]
node_huds[newActiveHudId as keyof typeof node_huds].big_text[1]
);
}, 400);
// animate it to new pos x/y
setTimeout(() => {
// set new text according to the node name
setYellowText(
(site_a as SiteType)[level][newActiveBlueOrbId].node_name
);
setYellowText((site_a as SiteType)[level][newActiveNodeId].node_name);
}, 1000);
setTimeout(() => {
@ -133,7 +107,7 @@ const YellowTextManager = (props: any) => {
]
);
const animateMediaYellowText: AnimateMediaYellowText = useCallback(
const animateMediaYellowText = useCallback(
(
targetMediaComponentText: string,
targetMediaComponentTextPos: number[]
@ -172,13 +146,13 @@ const YellowTextManager = (props: any) => {
}, [setYellowText, setYellowTextPosX, setYellowTextPosY]);
const initializeYellowTextForMainScene = useCallback(
(activeBlueOrbId: string, level: string) => {
setYellowText((site_a as SiteType)[level][activeBlueOrbId].node_name);
(activeNodeId: string, level: string) => {
setYellowText((site_a as SiteType)[level][activeNodeId].node_name);
setYellowTextPosX(
blue_orb_huds[activeBlueOrbId as keyof typeof blue_orb_huds].big_text[0]
node_huds[activeNodeId as keyof typeof node_huds].big_text[0]
);
setYellowTextPosY(
blue_orb_huds[activeBlueOrbId as keyof typeof blue_orb_huds].big_text[1]
node_huds[activeNodeId as keyof typeof node_huds].big_text[1]
);
},
[setYellowText, setYellowTextPosX, setYellowTextPosY]
@ -188,26 +162,19 @@ const YellowTextManager = (props: any) => {
(
event: string,
newActiveHudId: string | undefined,
newActiveBlueOrbId: string | undefined,
newActiveNodeId: string | undefined,
newLevel: string
) => {
switch (event) {
case "move_up":
return {
action: animateYellowTextWithMove,
value: [
0,
-1.5,
newActiveHudId,
newActiveBlueOrbId,
newLevel,
1300,
],
value: [0, -1.5, newActiveHudId, newActiveNodeId, newLevel, 1300],
};
case "move_down":
return {
action: animateYellowTextWithMove,
value: [0, 1.5, newActiveHudId, newActiveBlueOrbId, newLevel, 1300],
value: [0, 1.5, newActiveHudId, newActiveNodeId, newLevel, 1300],
};
case "move_left":
return {
@ -216,7 +183,7 @@ const YellowTextManager = (props: any) => {
Math.PI / 4,
0,
newActiveHudId,
newActiveBlueOrbId,
newActiveNodeId,
newLevel,
1100,
],
@ -228,7 +195,7 @@ const YellowTextManager = (props: any) => {
-Math.PI / 4,
0,
newActiveHudId,
newActiveBlueOrbId,
newActiveNodeId,
newLevel,
1100,
],
@ -238,24 +205,24 @@ const YellowTextManager = (props: any) => {
action: animateMediaYellowText,
value: ["Play", [-0.8, 0.05, 0.6]],
};
case "change_blue_orb":
case "change_node":
return {
action: animateYellowTextWithoutMove,
value: [newActiveHudId, newActiveBlueOrbId, newLevel],
value: [newActiveHudId, newActiveNodeId, newLevel],
};
case "play_down":
return {
action: animateMediaYellowText,
value: ["Exit", [-0.8, -0.08, 0.6]],
};
case "throw_blue_orb_media":
case "throw_node_media":
return {
action: initializeYellowTextForMediaScene,
};
case "exit_media_scene":
return {
action: initializeYellowTextForMainScene,
value: [newActiveBlueOrbId, newLevel],
value: [newActiveNodeId, newLevel],
};
}
},
@ -272,14 +239,14 @@ const YellowTextManager = (props: any) => {
if (props.eventState) {
const eventAction = props.eventState.event;
const newActiveBlueOrbId = props.eventState.newActiveBlueOrbId;
const newActiveNodeId = props.eventState.newActiveNodeId;
const newActiveHudId = props.eventState.newActiveHudId;
const newLevel = props.eventState.newLevel;
const dispatchedObject = dispatchObject(
eventAction,
newActiveHudId,
newActiveBlueOrbId,
newActiveNodeId,
newLevel
);
@ -292,7 +259,7 @@ const YellowTextManager = (props: any) => {
animateYellowTextWithoutMove,
props.eventState,
props.newActiveHudId,
props.newActiveBlueOrbId,
props.newActiveNodeId,
dispatchObject,
]);

View file

@ -1,5 +1,5 @@
import { GameContext } from "./StateManagers/EventManager";
import available_blue_orbs_on_projection from "../resources/available_blue_orbs_on_projection.json";
import node_matrices from "../resources/node_matrices.json";
import site_a from "../resources/site_a.json";
const hudAssocs = {
@ -22,86 +22,86 @@ const handleMainSceneEvent = (gameContext: GameContext) => {
const keyPress = gameContext.keyPress;
const blueOrbColIdx = gameContext.blueOrbMatrixIndices.colIdx;
const blueOrbRowIdx = gameContext.blueOrbMatrixIndices.rowIdx;
const nodeColIdx = gameContext.nodeMatrixIndices.colIdx;
const nodeRowIdx = gameContext.nodeMatrixIndices.rowIdx;
let newBlueOrbColIdx = gameContext.blueOrbMatrixIndices.colIdx;
let newBlueOrbRowIdx = gameContext.blueOrbMatrixIndices.rowIdx;
let newNodeColIdx = gameContext.nodeMatrixIndices.colIdx;
let newNodeRowIdx = gameContext.nodeMatrixIndices.rowIdx;
let newLevel = gameContext.currentLevel;
let newSiteRotIdx = gameContext.siteRotIdx;
let newScene = gameContext.scene;
switch (keyPress) {
case "left":
newBlueOrbColIdx = blueOrbColIdx - 1;
if (newBlueOrbColIdx < 0) {
newNodeColIdx = nodeColIdx - 1;
if (newNodeColIdx < 0) {
event = "move_left";
newSiteRotIdx =
parseInt(gameContext.siteRotIdx) + 1 > 8
? "1"
: (parseInt(gameContext.siteRotIdx) + 1).toString();
newBlueOrbColIdx = 0;
newNodeColIdx = 0;
} else {
event = "change_blue_orb";
event = "change_node";
}
break;
case "down":
newBlueOrbRowIdx = blueOrbRowIdx + 1;
if (newBlueOrbRowIdx > 2) {
newNodeRowIdx = nodeRowIdx + 1;
if (newNodeRowIdx > 2) {
event = "move_down";
newLevel = (parseInt(gameContext.currentLevel) - 1)
.toString()
.padStart(2, "0");
newBlueOrbRowIdx = 0;
newNodeRowIdx = 0;
} else {
event = "change_blue_orb";
event = "change_node";
}
break;
case "up":
newBlueOrbRowIdx = blueOrbRowIdx - 1;
if (newBlueOrbRowIdx < 0) {
newNodeRowIdx = nodeRowIdx - 1;
if (newNodeRowIdx < 0) {
event = "move_up";
newLevel = (parseInt(gameContext.currentLevel) + 1)
.toString()
.padStart(2, "0");
newBlueOrbRowIdx = 2;
newNodeRowIdx = 2;
} else {
event = "change_blue_orb";
event = "change_node";
}
break;
case "right":
newBlueOrbColIdx = blueOrbColIdx + 1;
if (newBlueOrbColIdx > 3) {
newNodeColIdx = nodeColIdx + 1;
if (newNodeColIdx > 3) {
event = "move_right";
newSiteRotIdx =
parseInt(gameContext.siteRotIdx) - 1 < 1
? "8"
: (parseInt(gameContext.siteRotIdx) - 1).toString();
newBlueOrbColIdx = 3;
newNodeColIdx = 3;
} else {
event = "change_blue_orb";
event = "change_node";
}
break;
case "select":
// in this case we have to check the type of the blue orb
// and dispatch an action depending on that, so we have to precalculate the
// new active blue orb here.
const newActiveBlueOrbId =
const newActiveNodeId =
newLevel +
available_blue_orbs_on_projection[
newSiteRotIdx as keyof typeof available_blue_orbs_on_projection
][newBlueOrbRowIdx as number][newBlueOrbColIdx as number];
node_matrices[
newSiteRotIdx as keyof typeof node_matrices
][newNodeRowIdx as number][newNodeColIdx as number];
const blueOrbType = (site_a as any)[newLevel][newActiveBlueOrbId]
const nodeType = (site_a as any)[newLevel][newActiveNodeId]
.type;
const eventAnimation = "throw_blue_orb_";
const eventAnimation = "throw_node_";
switch (parseInt(blueOrbType)) {
switch (parseInt(nodeType)) {
case 0:
case 2:
event = eventAnimation + "media";
@ -114,25 +114,25 @@ const handleMainSceneEvent = (gameContext: GameContext) => {
}
}
const newActiveBlueOrbId =
const newActiveNodeId =
newLevel +
available_blue_orbs_on_projection[
newSiteRotIdx as keyof typeof available_blue_orbs_on_projection
][newBlueOrbRowIdx as number][newBlueOrbColIdx as number];
node_matrices[
newSiteRotIdx as keyof typeof node_matrices
][newNodeRowIdx as number][newNodeColIdx as number];
const newActiveHudId =
hudAssocs[
`${newBlueOrbRowIdx}${newBlueOrbColIdx}` as keyof typeof hudAssocs
`${newNodeRowIdx}${newNodeColIdx}` as keyof typeof hudAssocs
];
return {
event: event,
newBlueOrbColIdx: newBlueOrbColIdx,
newBlueOrbRowIdx: newBlueOrbRowIdx,
newNodeColIdx: newNodeColIdx,
newNodeRowIdx: newNodeRowIdx,
newSiteRotIdx: newSiteRotIdx,
newLevel: newLevel,
newScene: newScene,
newActiveBlueOrbId: newActiveBlueOrbId,
newActiveNodeId: newActiveNodeId,
newActiveHudId: newActiveHudId,
};
};

View file

@ -10,7 +10,7 @@ import GrayPlanes from "../components/MainScene/GrayPlanes";
import MiddleRing from "../components/MainScene/MiddleRing";
import Starfield from "../components/MainScene/Starfield";
import {
useBlueOrbStore,
useNodeStore,
useHudStore,
useLainStore,
useMainGroupStore,
@ -22,9 +22,9 @@ import CurrentLevelNodes from "../components/MainScene/CurrentLevelNodes";
const MainScene = () => {
const setLainMoveState = useLainStore((state) => state.setLainMoveState);
const setActiveBlueOrb = useBlueOrbStore((state) => state.setActiveBlueOrbId);
const setActiveBlueOrbHudId = useHudStore(
(state) => state.setActiveBlueOrbHudId
const setActiveNode = useNodeStore((state) => state.setActiveNodeId);
const setActiveNodeHudId = useHudStore(
(state) => state.setActiveNodeHudId
);
const mainGroupPosY = useMainGroupStore((state) => state.mainGroupPosY);
@ -44,9 +44,9 @@ const MainScene = () => {
useEffect(() => {
setLainMoveState("standing");
setActiveBlueOrb("0422");
setActiveBlueOrbHudId("fg_hud_1");
}, [setActiveBlueOrb, setActiveBlueOrbHudId, setLainMoveState]);
setActiveNode("0422");
setActiveNodeHudId("fg_hud_1");
}, [setActiveNode, setActiveNodeHudId, setLainMoveState]);
// set lain intro spritesheet before the page loads fully
return (

View file

@ -1,4 +1,4 @@
import React, { useEffect } from "react";
import React, { useCallback, useEffect, useMemo } from "react";
import { useMediaStore } from "../store";
import TextRenderer from "../components/TextRenderer/TextRenderer";
import LeftSide from "../components/MediaScene/Selectables/LeftSide";
@ -11,8 +11,20 @@ import { OrbitControls } from "@react-three/drei";
import Images from "../components/MediaScene/Images";
const MediaScene = () => {
const mediaComponentMatrixIndices = useMediaStore(
(state) => state.componentMatrixIndices
);
const activeMediaComponent = useMediaStore(
(state) => state.activeMediaComponent
useCallback(
(state) =>
state.componentMatrix[mediaComponentMatrixIndices.sideIdx][
mediaComponentMatrixIndices.sideIdx === 0
? mediaComponentMatrixIndices.leftSideIdx
: mediaComponentMatrixIndices.rightSideIdx
],
[mediaComponentMatrixIndices]
)
);
useEffect(() => {

View file

@ -10,23 +10,23 @@ type HUDState = {
activeHudId: string;
hudActive: number;
hudVisible: boolean;
setActiveBlueOrbHudId: (to: string) => void;
setActiveNodeHudId: (to: string) => void;
toggleHud: () => void;
};
type BlueOrbState = {
activeBlueOrbId: string;
isActiveBlueOrbInteractedWith: boolean;
activeBlueOrbPosX: number;
activeBlueOrbPosZ: number;
activeBlueOrbRotZ: number;
setActiveBlueOrbPosX: (to: number) => void;
setActiveBlueOrbPosZ: (to: number) => void;
setActiveBlueOrbRotZ: (to: number) => void;
setActiveBlueOrbId: (to: string) => void;
setIsActiveBlueOrbInteractedWith: (to: boolean) => void;
blueOrbMatrixIndices: { rowIdx: number; colIdx: number };
setBlueOrbMatrixIndices: (to: { rowIdx: number; colIdx: number }) => void;
type NodeState = {
activeNodeId: string;
isActiveNodeInteractedWith: boolean;
activeNodePosX: number;
activeNodePosZ: number;
activeNodeRotZ: number;
setActiveNodePosX: (to: number) => void;
setActiveNodePosZ: (to: number) => void;
setActiveNodeRotZ: (to: number) => void;
setActiveNodeId: (to: string) => void;
setIsActiveNodeInteractedWith: (to: boolean) => void;
nodeMatrixIndices: { rowIdx: number; colIdx: number };
setNodeMatrixIndices: (to: { rowIdx: number; colIdx: number }) => void;
};
type LainState = {
@ -122,7 +122,7 @@ type MediaState = {
setLastActiveLeftSideElement: (to: string) => void;
lastActiveRightSideElement: string;
setLastActiveRightSideElement: (to: string) => void;
setMediaPercentageElapsed: (to: number) => void;
setPercentageElapsed: (to: number) => void;
};
export type TextRendererState = {
@ -204,26 +204,26 @@ export const useHudStore = create<HUDState>((set) => ({
activeHudId: "fg_hud_1",
hudActive: 1,
hudVisible: true,
setActiveBlueOrbHudId: (to) => set(() => ({ activeHudId: to })),
setActiveNodeHudId: (to) => set(() => ({ activeHudId: to })),
toggleHud: () => set((state) => ({ hudActive: Number(!state.hudActive) })),
}));
export const useBlueOrbStore = create<BlueOrbState>((set) => ({
activeBlueOrbId: "0422",
isActiveBlueOrbInteractedWith: false,
activeBlueOrbPosX: 0,
activeBlueOrbPosZ: 0,
activeBlueOrbRotZ: 0,
setActiveBlueOrbPosX: (to) => set(() => ({ activeBlueOrbPosX: to })),
setActiveBlueOrbPosZ: (to) => set(() => ({ activeBlueOrbPosZ: to })),
setActiveBlueOrbRotZ: (to) => set(() => ({ activeBlueOrbRotZ: to })),
setActiveBlueOrbId: (to) => set(() => ({ activeBlueOrbId: to })),
setIsActiveBlueOrbInteractedWith: (to) =>
set(() => ({ isActiveBlueOrbInteractedWith: to })),
blueOrbRowIdx: 0,
export const useNodeStore = create<NodeState>((set) => ({
activeNodeId: "0422",
isActiveNodeInteractedWith: false,
activeNodePosX: 0,
activeNodePosZ: 0,
activeNodeRotZ: 0,
setActiveNodePosX: (to) => set(() => ({ activeNodePosX: to })),
setActiveNodePosZ: (to) => set(() => ({ activeNodePosZ: to })),
setActiveNodeRotZ: (to) => set(() => ({ activeNodeRotZ: to })),
setActiveNodeId: (to) => set(() => ({ activeNodeId: to })),
setIsActiveNodeInteractedWith: (to) =>
set(() => ({ isActiveNodeInteractedWith: to })),
nodeRowIdx: 0,
blueOrbMatrixIndices: { rowIdx: 0, colIdx: 0 },
setBlueOrbMatrixIndices: (to) => set(() => ({ blueOrbMatrixIndices: to })),
nodeMatrixIndices: { rowIdx: 0, colIdx: 0 },
setNodeMatrixIndices: (to) => set(() => ({ nodeMatrixIndices: to })),
}));
export const useLainStore = create<LainState>((set) => ({
@ -303,23 +303,69 @@ export const useLevelStore = create<LevelState>((set) => ({
setCurrentLevel: (to) => set(() => ({ currentLevel: to })),
}));
export const useMediaStore = create<MediaState>((set) => ({
// we can't have one global activeMediaComponent because both right and left col
// elements need to be stored (when you switch back and forth between the columns,
// you end up on the last active element FROM THAT COLUMN).
// so we store leftColActiveMediaComponent as well as rightCol.
mediaPercentageElapsed: 0,
activeMediaComponent: "play",
setActiveMediaComponent: (to) => set(() => ({ activeMediaComponent: to })),
lastActiveLeftSideElement: "play",
lastActiveRightSideElement: "fstWord",
setLastActiveLeftSideElement: (to) =>
set(() => ({ lastActiveLeftSideElement: to })),
setLastActiveRightSideElement: (to) =>
set(() => ({ lastActiveRightSideElement: to })),
setMediaPercentageElapsed: (to) =>
set(() => ({ mediaPercentageElapsed: to })),
}));
export const useMediaStore = create(
combine(
{
mediaPercentageElapsed: 0,
componentMatrix: [
["play", "exit"],
["fstWord", "sndWord", "thirdWord"],
],
componentMatrixIndices: {
// 0 or 1 (left/right)
sideIdx: 0,
// 0 or 1 ("play" or "exit")
leftSideIdx: 0,
// 0 or 1 or 2 ("fstWord", "sndWord" or "thirdWord")
rightSideIdx: 0,
},
} as any,
(set) => ({
toggleSide: () =>
set((state) => ({
componentMatrixIndices: {
...state.componentMatrixIndices,
sideIdx: Number(!state.componentMatrixIndices.sideIdx),
},
})),
toggleLeftComponent: () =>
set((state) => ({
componentMatrixIndices: {
...state.componentMatrixIndices,
leftSideIdx: Number(!state.componentMatrixIndices.leftSideIdx),
},
})),
addToRightComponentMatrixIdx: (val: number) =>
set((state) => {
let finalVal;
const newSum = state.componentMatrixIndices["rightSideIdx"] + val;
if (newSum > 2) {
finalVal = 0;
} else if (newSum < 0) {
finalVal = 2;
} else {
finalVal = newSum;
}
return {
componentMatrixIndices: {
...state.componentMatrixIndices,
rightSideIdx: finalVal,
},
};
}),
resetComponentMatrixIndices: () =>
set(() => ({
componentMatrixIndices: {
sideIdx: 0,
leftSideIdx: 0,
rightSideIdx: 0,
},
})),
setPercentageElapsed: (to: number) =>
set(() => ({ mediaPercentageElapsed: to })),
})
)
);
export const useMediaWordStore = create<MediaWordState>((set) => ({
words: ["eye", "quiet", "hallucination"],
@ -394,7 +440,7 @@ export const useMediaWordStore = create<MediaWordState>((set) => ({
}));
export const useSceneStore = create<SceneState>((set) => ({
currentScene: "main",
currentScene: "media",
setScene: (to) => set(() => ({ currentScene: to })),
}));