diff --git a/src/App.tsx b/src/App.tsx
index 17455a0..5121dcb 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -21,8 +21,8 @@ const App = () => {
document.title = "< index >";
}, []);
- const dispatchScene = useMemo(() => {
- return {
+ const dispatchScene = useMemo(
+ () => ({
main: ,
media: ,
idle_media: ,
@@ -33,8 +33,9 @@ const App = () => {
tak: ,
change_disc: ,
end: ,
- };
- }, []);
+ }),
+ []
+ );
return (
@@ -45,7 +46,9 @@ const App = () => {
-
+ {["media", "idle_media", "tak", "end"].includes(currentScene) && (
+
+ )}
);
};
diff --git a/src/components/MainScene/SyncedComponents/HUD.tsx b/src/components/MainScene/SyncedComponents/HUD.tsx
index 8be740e..a8dec8e 100644
--- a/src/components/MainScene/SyncedComponents/HUD.tsx
+++ b/src/components/MainScene/SyncedComponents/HUD.tsx
@@ -40,10 +40,10 @@ const HUD = memo(() => {
(state) => state.activeNode.matrixIndices
);
const siteRotY = useStore((state) => state.siteRot[1]);
- const sitePosY = useStore((state) => state.sitePos[1]);
+ const activeLevel = useStore((state) => state.activeLevel);
const subscene = useStore((state) => state.mainSubscene);
const scene = useStore((state) => state.currentScene);
- const prevData = usePrevious({ siteRotY, sitePosY, subscene, scene });
+ const prevData = usePrevious({ siteRotY, activeLevel, subscene, scene });
// this part is imperative because it performs a lot better than having a toggleable spring.
useFrame(() => {
@@ -123,7 +123,7 @@ const HUD = memo(() => {
} else {
if (
prevData?.siteRotY !== siteRotY ||
- prevData?.sitePosY !== sitePosY ||
+ prevData?.activeLevel !== activeLevel ||
subscene === "level_selection"
) {
activeRef.current = false;
@@ -165,13 +165,13 @@ const HUD = memo(() => {
}
}
}, [
+ activeLevel,
activeNodeMatrixIndices,
+ prevData?.activeLevel,
prevData?.scene,
- prevData?.sitePosY,
prevData?.siteRotY,
prevData?.subscene,
scene,
- sitePosY,
siteRotY,
subscene,
]);
diff --git a/src/components/MainScene/SyncedComponents/LevelSelection.tsx b/src/components/MainScene/SyncedComponents/LevelSelection.tsx
index face0d5..96c7cac 100644
--- a/src/components/MainScene/SyncedComponents/LevelSelection.tsx
+++ b/src/components/MainScene/SyncedComponents/LevelSelection.tsx
@@ -111,6 +111,7 @@ const LevelSelection = () => {
}, [
activeLevel,
downArrowActiveTex,
+ downArrowTex,
prevData?.selectedLevel,
prevData?.subscene,
selectedLevel,
diff --git a/src/components/MainScene/SyncedComponents/Site.tsx b/src/components/MainScene/SyncedComponents/Site.tsx
index 4296e73..ae454bc 100644
--- a/src/components/MainScene/SyncedComponents/Site.tsx
+++ b/src/components/MainScene/SyncedComponents/Site.tsx
@@ -7,10 +7,11 @@ import NodeAnimations from "./Site/NodeAnimations";
import InactiveLevelNodes from "./Site/InactiveLevelNodes";
import { useFrame } from "react-three-fiber";
import * as THREE from "three";
-import lerp from "../../../core/utils/lerp";
import filterInvisibleNodes from "../../../core/utils/filterInvisibleNodes";
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 usePrevious from "../../../hooks/usePrevious";
export type NodeDataType = {
id: string;
@@ -47,14 +48,33 @@ type SiteProps = {
};
const Site = (props: SiteProps) => {
- const siteRot = useStore((state) => state.siteRot);
- const sitePos = useStore((state) => state.sitePos);
- const siteState = useSpring({
- siteRotX: siteRot[0],
- siteRotY: siteRot[1],
- sitePosY: sitePos[1],
+ const activeLevel = useStore((state) => state.activeLevel);
+
+ const [state, setState] = useSpring(() => ({
+ posY: -level_y_values[
+ useStore.getState().activeLevel as keyof typeof level_y_values
+ ],
+ rotX: useStore.getState().siteRot[0],
+ rotY: useStore.getState().siteRot[1],
config: { duration: 1200 },
- });
+ }));
+
+ useEffect(() => {
+ setTimeout(() => {
+ setState({
+ posY: -level_y_values[activeLevel as keyof typeof level_y_values],
+ });
+ }, 1200);
+ }, [activeLevel, setState]);
+
+ useEffect(() => {
+ useStore.subscribe(setState, (state) => {
+ return {
+ rotX: state.siteRot[0],
+ rotY: state.siteRot[1],
+ };
+ });
+ }, [setState]);
const introWrapperRef = useRef();
@@ -90,18 +110,15 @@ const Site = (props: SiteProps) => {
return (
-
-
+
+
-
+
diff --git a/src/components/MediaScene/MediaLoadingBar.tsx b/src/components/MediaScene/MediaLoadingBar.tsx
index 6464aa7..810d69d 100644
--- a/src/components/MediaScene/MediaLoadingBar.tsx
+++ b/src/components/MediaScene/MediaLoadingBar.tsx
@@ -31,6 +31,11 @@ const MediaLoadingBar = () => {
// doing it declaratively like this fixes that concern
const loadingBarState = useMemo(() => {
const mediaPercentageDispatch = {
+ 0: {
+ scaleX: 0,
+ texture: loadingBar10PercTex,
+ offsetX: 0,
+ },
5: {
scaleX: 0.25,
texture: loadingBar10PercTex,
diff --git a/src/components/MediaScene/MediaPlayer.tsx b/src/components/MediaScene/MediaPlayer.tsx
index a3f150a..4cc3184 100644
--- a/src/components/MediaScene/MediaPlayer.tsx
+++ b/src/components/MediaScene/MediaPlayer.tsx
@@ -9,8 +9,8 @@ import React, {
import { useStore } from "../../store";
import t from "../../static/webvtt/test.vtt";
import endroll from "../../static/movie/ENDROLL1.STR[0].webm";
-import xa0001 from "../../static/audio/a/Xa0001.mp4";
-import xa0006 from "../../static/audio/a/Xa0006.mp4";
+import xa0001 from "../../static/audio/Xa0001.mp4";
+import xa0006 from "../../static/audio/Xa0006.mp4";
const MediaPlayer = () => {
const [mediaSource, setMediaSource] = useState();
@@ -18,9 +18,7 @@ const MediaPlayer = () => {
const currentScene = useStore((state) => state.currentScene);
const setScene = useStore((state) => state.setScene);
- const setPercentageElapsed = useStore(
- (state) => state.setPercentageElapsed
- );
+ const setPercentageElapsed = useStore((state) => state.setPercentageElapsed);
const idleMedia = useStore((state) => state.idleMedia);
const nodeMedia = useStore((state) => state.activeNode.media_file);
@@ -32,12 +30,8 @@ const MediaPlayer = () => {
const requestRef = useRef();
const videoRef = createRef();
- const currentSite = useStore((state) => state.activeSite);
-
// end scene specific stuff
- const endMediaPlayedCount = useStore(
- (state) => state.endMediaPlayedCount
- );
+ const endMediaPlayedCount = useStore((state) => state.endMediaPlayedCount);
const incrementEndMediaPlayedCount = useStore(
(state) => state.incrementEndMediaPlayedCount
);
@@ -47,10 +41,7 @@ const MediaPlayer = () => {
const updateTime = useCallback(() => {
(requestRef.current as any) = requestAnimationFrame(updateTime);
- if (
- videoRef.current &&
- ["media", "idle_media", "tak", "end"].includes(currentScene)
- ) {
+ if (videoRef.current) {
const timeElapsed = videoRef.current.currentTime;
const duration = videoRef.current.duration;
const percentageElapsed = Math.floor((timeElapsed / duration) * 100);
@@ -58,6 +49,7 @@ const MediaPlayer = () => {
if (percentageElapsed % 5 === 0 && percentageElapsed !== 0) {
setPercentageElapsed(percentageElapsed);
if (percentageElapsed === 100) {
+ if (currentScene === "media") setPercentageElapsed(0);
videoRef.current.currentTime = 0;
if (currentScene === "idle_media") {
videoRef.current.pause();
@@ -124,45 +116,30 @@ const MediaPlayer = () => {
}
}
} else {
- if (currentScene === "media" || currentScene === "tak") {
- if (nodeMedia.includes("XA")) {
- import(
- "../../static/audio/" + currentSite + "/" + nodeMedia + ".ogg"
- ).then((media) => {
- setMediaSource(media.default);
- if (videoRef.current) {
- videoRef.current.load();
- }
- });
- } else {
- import("../../static/movie/" + nodeMedia + "[0].webm").then(
- (media) => {
- setMediaSource(media.default);
- if (videoRef.current) {
- videoRef.current.load();
- }
- }
- );
- }
- } else if (currentScene === "idle_media") {
- if (idleMedia) {
- if (idleMedia.includes("XA")) {
- import(
- "../../static/audio/" + currentSite + "/" + idleMedia + ".ogg"
- ).then((media) => {
- setMediaSource(media.default);
- if (videoRef.current) {
- videoRef.current.load();
- videoRef.current.play();
- }
- });
- } else {
- import("../../static/movie/" + idleMedia + "[0].webm").then(
+ if (
+ currentScene === "media" ||
+ currentScene === "tak" ||
+ currentScene === "idle_media"
+ ) {
+ if (currentScene === "media") setPercentageElapsed(0);
+ const mediaToPlay =
+ currentScene === "idle_media" ? idleMedia : nodeMedia;
+ if (mediaToPlay) {
+ if (mediaToPlay.includes("XA")) {
+ import("../../static/audio/" + mediaToPlay + ".ogg").then(
+ (media) => {
+ setMediaSource(media.default);
+ if (videoRef.current) {
+ videoRef.current.load();
+ }
+ }
+ );
+ } else {
+ import("../../static/movie/" + mediaToPlay + "[0].webm").then(
(media) => {
setMediaSource(media.default);
if (videoRef.current) {
videoRef.current.load();
- videoRef.current.play();
}
}
);
@@ -172,10 +149,10 @@ const MediaPlayer = () => {
}
}, [
currentScene,
- currentSite,
endMediaPlayedCount,
idleMedia,
nodeMedia,
+ setPercentageElapsed,
videoRef,
]);
diff --git a/src/components/TextRenderer/BigLetter.tsx b/src/components/TextRenderer/BigLetter.tsx
index e7e4984..7552843 100644
--- a/src/components/TextRenderer/BigLetter.tsx
+++ b/src/components/TextRenderer/BigLetter.tsx
@@ -137,6 +137,7 @@ const BigLetter = memo((props: { letter: string; letterIdx: number }) => {
activeMediaComponent,
lastMediaLeftComponent,
prevData?.scene,
+ prevData?.subscene,
]);
return (
diff --git a/src/core/StateManagers/MainSceneEventManager.tsx b/src/core/StateManagers/MainSceneEventManager.tsx
index 03ca78d..e9b70fa 100644
--- a/src/core/StateManagers/MainSceneEventManager.tsx
+++ b/src/core/StateManagers/MainSceneEventManager.tsx
@@ -25,7 +25,6 @@ const MainSceneEventManager = (props: MainSceneEventManagerProps) => {
const activeNodeId = useStore((state) => state.activeNode.id);
const nodeMatrixIndices = useStore((state) => state.activeNode.matrixIndices);
const siteRotY = useStore((state) => state.siteRot[1]);
- const sitePosY = useStore((state) => state.sitePos[1]);
const activeLevel = useStore((state) => state.activeLevel);
const mainSubscene = useStore((state) => state.mainSubscene);
const selectedLevel = useStore((state) => state.selectedLevel);
@@ -54,7 +53,7 @@ const MainSceneEventManager = (props: MainSceneEventManagerProps) => {
// scene: "idle_media",
// site: currentSite,
// });
- // timePassedSinceLastKeyPress.current = -1;
+ timePassedSinceLastKeyPress.current = -1;
} else if (now > timePassedSinceLastKeyPress.current + 10000) {
const moves = [
"prayer",
@@ -94,7 +93,6 @@ const MainSceneEventManager = (props: MainSceneEventManagerProps) => {
const event = handleMainSceneEvent({
mainSubscene: mainSubscene,
keyPress: keyPress,
- sitePosY: sitePosY,
siteRotY: siteRotY,
activeNodeId: activeNodeId,
nodeMatrixIndices: nodeMatrixIndices,
@@ -112,7 +110,6 @@ const MainSceneEventManager = (props: MainSceneEventManagerProps) => {
[
props.loaded,
mainSubscene,
- sitePosY,
siteRotY,
activeNodeId,
nodeMatrixIndices,
diff --git a/src/core/StateManagers/MainSceneManagers/SiteManager.tsx b/src/core/StateManagers/MainSceneManagers/SiteManager.tsx
index ec157cb..78d9ce8 100644
--- a/src/core/StateManagers/MainSceneManagers/SiteManager.tsx
+++ b/src/core/StateManagers/MainSceneManagers/SiteManager.tsx
@@ -3,22 +3,12 @@ import { useStore } from "../../../store";
import { StateManagerProps } from "../EventManager";
const SiteManager = (props: StateManagerProps) => {
- const setPos = useStore((state) => state.setSitePos);
const setRot = useStore((state) => state.setSiteRot);
const setRotX = useStore((state) => state.setSiteRotX);
const dispatchObject = useCallback(
- (eventState: { event: string; sitePosY: number; siteRotY: number }) => {
+ (eventState: { event: string; siteRotY: number }) => {
switch (eventState.event) {
- case "site_up":
- case "site_down":
- case "select_level_up":
- case "select_level_down":
- return {
- action: setPos,
- value: [[0, eventState.sitePosY, 0]],
- actionDelay: 1300,
- };
case "site_left":
case "site_right":
return {
@@ -40,7 +30,7 @@ const SiteManager = (props: StateManagerProps) => {
};
}
},
- [setPos, setRot, setRotX]
+ [setRot, setRotX]
);
useEffect(() => {
diff --git a/src/core/nodeSelector.ts b/src/core/nodeSelector.ts
index 1ea14b2..bc37912 100644
--- a/src/core/nodeSelector.ts
+++ b/src/core/nodeSelector.ts
@@ -8,6 +8,12 @@ import {
import unlocked_nodes from "../resources/initial_progress.json";
import level_y_values from "../resources/level_y_values.json";
import node_huds from "../resources/node_huds.json";
+import filterInvisibleNodes from "./utils/filterInvisibleNodes";
+import {
+ findNodeLeft,
+ findNodeRight,
+ getVisibleNodesMatrix,
+} from "./utils/nodeUtils";
type NodeSelectorContext = {
action: string;
@@ -35,6 +41,12 @@ const hudAssocs = {
"23": "fg_hud_6",
};
+export const getNodeById = (id: string, currentSite: string) => {
+ const siteData = currentSite === "a" ? site_a : site_b;
+ const level = id.substr(0, 2);
+ return (siteData as SiteType)[level][id];
+};
+
export const getNode = (
level: number,
nodeMatrixIndices: {
@@ -377,6 +389,21 @@ const nodeSelector = (context: NodeSelectorContext) => {
switch (context.action) {
case "site_left":
case "site_right":
+ const t =
+ context.action === "site_right"
+ ? findNodeRight(
+ context.nodeMatrixIndices,
+ context.level,
+ context.currentSite,
+ context.gameProgress
+ )
+ : findNodeLeft(
+ context.nodeMatrixIndices,
+ context.level,
+ context.currentSite,
+ context.gameProgress
+ );
+
move = context.action === "site_left" ? "left" : "right";
newNodeData = findNodeHorizontal(
move,
@@ -387,14 +414,15 @@ const nodeSelector = (context: NodeSelectorContext) => {
context.currentSite
);
+ console.log(t!.matrixIndices);
if (newNodeData) {
const siteRotYModifier = move === "left" ? Math.PI / 4 : -Math.PI / 4;
return {
event: newNodeData.didMove ? context.action : "change_node",
- node: newNodeData.node,
+ node: getNodeById(t!.node, context.currentSite),
newActiveHud: newNodeData.newNodeHud,
- newNodeMatrixIndices: newNodeData.newNodeMatrixIndices,
+ newNodeMatrixIndices: t!.matrixIndices,
newSiteRotY: newNodeData.didMove
? context.siteRotY + siteRotYModifier
: context.siteRotY,
diff --git a/src/core/utils/nodeUtils.ts b/src/core/utils/nodeUtils.ts
index c37f97e..17c8dbd 100644
--- a/src/core/utils/nodeUtils.ts
+++ b/src/core/utils/nodeUtils.ts
@@ -1,4 +1,6 @@
import { SiteType } from "../../components/MainScene/SyncedComponents/Site";
+import node_matrices from "../../resources/node_matrices.json";
+import { getNode, getNodeById, isNodeVisible } from "../nodeSelector";
export const generateInactiveNodes = (
visibleNodes: SiteType,
@@ -19,3 +21,186 @@ export const generateInactiveNodes = (
return obj;
};
+
+export const getVisibleNodesMatrix = (
+ matrixIdx: number,
+ activeLevel: number,
+ currentSite: string,
+ gameProgress: any
+) => {
+ const formattedLevel = activeLevel.toString().padStart(2, "0");
+ const currentMatrix =
+ node_matrices[matrixIdx.toString() as keyof typeof node_matrices];
+
+ return currentMatrix.map((row: string[]) =>
+ row.map((nodePos: string) => {
+ const nodeId = formattedLevel + nodePos;
+ if (isNodeVisible(getNodeById(nodeId, currentSite), gameProgress))
+ return nodeId;
+ else return undefined;
+ })
+ );
+};
+
+const generateRowPrecedence = (rowIdx: number) => {
+ switch (rowIdx) {
+ case 0:
+ return [0, 1, 2];
+ case 1:
+ return [1, 0, 2];
+ case 2:
+ return [2, 1, 0];
+ default:
+ return [0, 1, 2];
+ }
+};
+
+export const findNodeLeft = (
+ nodeMatrixIndices: {
+ matrixIdx: number;
+ rowIdx: number;
+ colIdx: number;
+ },
+ level: number,
+ currentSite: string,
+ gameProgress: any
+) => {
+ const { matrixIdx, rowIdx, colIdx } = nodeMatrixIndices;
+
+ const visibleNodes = getVisibleNodesMatrix(
+ matrixIdx,
+ level,
+ currentSite,
+ gameProgress
+ );
+
+ const precedence = generateRowPrecedence(rowIdx);
+
+ let chosenNode;
+ let matrixIndices;
+ loop: for (let col = colIdx - 1; col > -1; col--) {
+ for (let i = 0; i < 3; i++) {
+ const current = visibleNodes[precedence[i]][col];
+ if (current) {
+ chosenNode = current;
+ matrixIndices = {
+ matrixIdx: matrixIdx,
+ rowIdx: precedence[i],
+ colIdx: col,
+ };
+ break loop;
+ }
+ }
+ }
+
+ if (chosenNode) {
+ return {
+ node: chosenNode,
+ matrixIndices: matrixIndices,
+ didRotate: false,
+ };
+ } else {
+ const newMatrixIdx = matrixIdx + 1 > 8 ? 1 : matrixIdx + 1;
+ const visibleNodes = getVisibleNodesMatrix(
+ newMatrixIdx,
+ level,
+ currentSite,
+ gameProgress
+ );
+
+ loop: for (let col = 0; col < 4; col++) {
+ for (let i = 0; i < 3; i++) {
+ const current = visibleNodes[precedence[i]][col];
+ if (current) {
+ chosenNode = current;
+ matrixIndices = {
+ matrixIdx: newMatrixIdx,
+ rowIdx: precedence[i],
+ colIdx: col,
+ };
+ break loop;
+ }
+ }
+ }
+
+ if (chosenNode)
+ return {
+ node: chosenNode,
+ matrixIndices: matrixIndices,
+ didRotate: true,
+ };
+ }
+};
+
+export const findNodeRight = (
+ nodeMatrixIndices: {
+ matrixIdx: number;
+ rowIdx: number;
+ colIdx: number;
+ },
+ level: number,
+ currentSite: string,
+ gameProgress: any
+) => {
+ const { matrixIdx, rowIdx, colIdx } = nodeMatrixIndices;
+
+ const visibleNodes = getVisibleNodesMatrix(
+ matrixIdx,
+ level,
+ currentSite,
+ gameProgress
+ );
+
+ const precedence = generateRowPrecedence(rowIdx);
+
+ let chosenNode;
+ let matrixIndices;
+ loop: for (let col = colIdx + 1; col < 4; col++) {
+ for (let i = 0; i < 3; i++) {
+ const current = visibleNodes[precedence[i]][col];
+ if (current) {
+ chosenNode = current;
+ matrixIndices = {
+ matrixIdx: matrixIdx,
+ rowIdx: precedence[i],
+ colIdx: col,
+ };
+ break loop;
+ }
+ }
+ }
+
+ if (chosenNode) {
+ return { node: chosenNode, didRotate: false, matrixIndices: matrixIndices };
+ } else {
+ const newMatrixIdx = matrixIdx - 1 < 1 ? 8 : matrixIdx - 1;
+ const visibleNodes = getVisibleNodesMatrix(
+ newMatrixIdx,
+ level,
+ currentSite,
+ gameProgress
+ );
+
+ loop: for (let col = 3; col > -1; col--) {
+ for (let i = 0; i < 3; i++) {
+ const current = visibleNodes[precedence[i]][col];
+ if (current) {
+ chosenNode = current;
+ matrixIndices = {
+ matrixIdx: newMatrixIdx,
+ rowIdx: precedence[i],
+ colIdx: col,
+ };
+ break loop;
+ }
+ }
+ }
+
+ if (chosenNode)
+ return {
+ node: chosenNode,
+ matrixIndices: matrixIndices,
+ didRotate: true,
+ };
+ }
+};
diff --git a/src/scenes/IdleMediaScene.tsx b/src/scenes/IdleMediaScene.tsx
index 2476c74..c0a5764 100644
--- a/src/scenes/IdleMediaScene.tsx
+++ b/src/scenes/IdleMediaScene.tsx
@@ -6,12 +6,12 @@ const IdleMediaScene = () => {
const idleMedia = useStore((state) => state.idleMedia);
useEffect(() => {
- document.getElementsByTagName("canvas")[0].className =
- "media-scene-background";
+ const mediaElement = document.getElementById("media") as HTMLMediaElement;
- return () => {
- document.getElementsByTagName("canvas")[0].className = "";
- };
+ if (mediaElement) {
+ mediaElement.currentTime = 0;
+ mediaElement.play();
+ }
}, []);
return (
diff --git a/src/store.ts b/src/store.ts
index 962aa4e..5341d80 100644
--- a/src/store.ts
+++ b/src/store.ts
@@ -50,7 +50,6 @@ type State = {
// site
activeSite: "a" | "b";
siteRot: number[];
- sitePos: number[];
// level
activeLevel: string;
@@ -175,7 +174,6 @@ export const useStore = create(
// site
activeSite: "a",
siteRot: [0, 0, 0],
- sitePos: [0, 0, 0],
// level
activeLevel: "04",
@@ -280,7 +278,6 @@ export const useStore = create(
nextPos[0] = to;
return { siteRot: nextPos };
}),
- setSitePos: (to: number[]) => set(() => ({ sitePos: to })),
// level setters
setActiveLevel: (to: string) => set(() => ({ activeLevel: to })),