diff --git a/src/components/BootScene/BootLoadData.tsx b/src/components/BootScene/BootLoadData.tsx
index e92e5e9..fdf458e 100644
--- a/src/components/BootScene/BootLoadData.tsx
+++ b/src/components/BootScene/BootLoadData.tsx
@@ -14,92 +14,93 @@ type BootLoadDataProps = {
};
const BootLoadData = (props: BootLoadDataProps) => {
- const loadDataUnderlineTex = useLoader(
- THREE.TextureLoader,
- loadDataUnderline
- );
- const loadDataQuestionContainerTex = useLoader(
- THREE.TextureLoader,
- loadDataQuestionContainer
- );
- const loadDataAnswerContainerTex = useLoader(
- THREE.TextureLoader,
- loadDataAnswerContainer
- );
- const areYouSureTex = useLoader(THREE.TextureLoader, areYouSure);
- const yesTex = useLoader(THREE.TextureLoader, yes);
- const noTex = useLoader(THREE.TextureLoader, no);
-
- return (
- <>
- {props.visible ? (
- <>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- >
- ) : (
- <>>
- )}
- >
- );
+ // const loadDataUnderlineTex = useLoader(
+ // THREE.TextureLoader,
+ // loadDataUnderline
+ // );
+ // const loadDataQuestionContainerTex = useLoader(
+ // THREE.TextureLoader,
+ // loadDataQuestionContainer
+ // );
+ // const loadDataAnswerContainerTex = useLoader(
+ // THREE.TextureLoader,
+ // loadDataAnswerContainer
+ // );
+ // const areYouSureTex = useLoader(THREE.TextureLoader, areYouSure);
+ // const yesTex = useLoader(THREE.TextureLoader, yes);
+ // const noTex = useLoader(THREE.TextureLoader, no);
+ //
+ // return (
+ // <>
+ // {props.visible ? (
+ // <>
+ //
+ //
+ //
+ //
+ //
+ //
+ //
+ //
+ //
+ //
+ //
+ //
+ //
+ //
+ //
+ //
+ //
+ //
+ //
+ //
+ //
+ //
+ //
+ // >
+ // ) : (
+ // <>>
+ // )}
+ // >
+ // );
+ return <>>;
};
export default BootLoadData;
diff --git a/src/components/KeyPressHandler.tsx b/src/components/KeyPressHandler.tsx
index 5daab03..0c72267 100644
--- a/src/components/KeyPressHandler.tsx
+++ b/src/components/KeyPressHandler.tsx
@@ -22,6 +22,7 @@ import handleMainSceneEvent from "../core/scene-keypress-handlers/handleMainKeyP
import gameLoader from "../core/setters/gameLoader";
import gameSaver from "../core/setters/gameSaver";
import progressManager from "../core/setters/progressManager";
+import promptManager from "../core/setters/promptManager";
const KeyPressHandler = () => {
const mediaSceneSetters = useMemo(
@@ -32,6 +33,7 @@ const KeyPressHandler = () => {
levelManager,
siteManager,
progressManager,
+ mainSubsceneManager,
],
[]
);
@@ -52,6 +54,7 @@ const KeyPressHandler = () => {
gameLoader,
gameSaver,
progressManager,
+ promptManager,
],
[]
);
@@ -92,6 +95,7 @@ const KeyPressHandler = () => {
};
case "gate":
case "polytan":
+ case "about":
return {
action: () => useStore.setState({ currentScene: "main" }),
};
diff --git a/src/components/MainScene/HUD.tsx b/src/components/MainScene/HUD.tsx
index 97f242a..59b21e7 100644
--- a/src/components/MainScene/HUD.tsx
+++ b/src/components/MainScene/HUD.tsx
@@ -130,6 +130,7 @@ const HUD = memo(() => {
if (
!(scene === "main" && prevData?.scene === "main") ||
(subscene === "site" && prevData?.subscene === "pause") ||
+ (subscene === "site" && prevData?.subscene === "not_found") ||
subscene === "pause"
) {
// set to final pos instantly
diff --git a/src/components/MainScene/NotFound.tsx b/src/components/MainScene/NotFound.tsx
new file mode 100644
index 0000000..762290b
--- /dev/null
+++ b/src/components/MainScene/NotFound.tsx
@@ -0,0 +1,48 @@
+import React from "react";
+import notFound from "../../static/sprite/not_found.png";
+import notFoundLof from "../../static/sprite/not_found_lof.png";
+import { useLoader } from "react-three-fiber";
+import * as THREE from "three";
+
+type NotFoundProps = {
+ visible: boolean;
+};
+
+const NotFound = (props: NotFoundProps) => {
+ const notFoundTex = useLoader(THREE.TextureLoader, notFound);
+ const notFoundLofTex = useLoader(THREE.TextureLoader, notFoundLof);
+
+ return (
+ <>
+ {props.visible && (
+ <>
+
+
+
+
+
+
+
+ >
+ )}
+ >
+ );
+};
+
+export default NotFound;
diff --git a/src/components/MainScene/PauseSubscene/About.tsx b/src/components/MainScene/PauseSubscene/About.tsx
new file mode 100644
index 0000000..bf36931
--- /dev/null
+++ b/src/components/MainScene/PauseSubscene/About.tsx
@@ -0,0 +1,41 @@
+import React, { useRef } from "react";
+import aboutBg from "../../../static/sprite/about_background.png";
+import { useFrame, useLoader } from "react-three-fiber";
+import * as THREE from "three";
+import { useStore } from "../../../store";
+
+const About = () => {
+ const setShowingAbout = useStore((state) => state.setShowingAbout);
+ const aboutBgTex = useLoader(THREE.TextureLoader, aboutBg);
+
+ const bgRef = useRef();
+ // todo im not sure where the other bg file is located,
+ // the one here is just the text, in the original game there's another one
+
+ useFrame(() => {
+ if (bgRef.current) {
+ bgRef.current.position.y += 0.03;
+ if (Math.round(bgRef.current.position.y) === 14) {
+ setShowingAbout(false);
+ }
+ }
+ });
+
+ return (
+ <>
+
+
+
+
+
+
+ >
+ );
+};
+
+export default About;
diff --git a/src/components/MainScene/PauseSubscene/Pause.tsx b/src/components/MainScene/PauseSubscene/Pause.tsx
index 4991f08..319b9df 100644
--- a/src/components/MainScene/PauseSubscene/Pause.tsx
+++ b/src/components/MainScene/PauseSubscene/Pause.tsx
@@ -4,9 +4,12 @@ import PauseSquare from "./PauseSquare";
import StaticBigLetter from "../../TextRenderer/StaticBigLetter";
import { useStore } from "../../../store";
import { useLoader } from "react-three-fiber";
+import About from "./About";
+import Prompt from "../../Prompt";
const Pause = () => {
const exit = useStore((state) => state.pauseExitAnimation);
+ const showingAbout = useStore((state) => state.showingAbout);
const [showActiveComponent, setShowActiveComponent] = useState(false);
const [animation, setAnimation] = useState(false);
const [intro, setIntro] = useState(true);
@@ -274,7 +277,6 @@ const Pause = () => {
active={activeComponent === "load"}
/>
))}
-
{"About".split("").map((letter, idx) => (
0 ? "yellow" : "orange"}
@@ -286,7 +288,6 @@ const Pause = () => {
key={idx}
/>
))}
-
{"Change".split("").map((letter, idx) => (
0 ? "yellow" : "orange"}
@@ -298,7 +299,6 @@ const Pause = () => {
key={idx}
/>
))}
-
{"Save".split("").map((letter, idx) => (
0 ? "yellow" : "orange"}
@@ -310,7 +310,6 @@ const Pause = () => {
key={idx}
/>
))}
-
{"Exit".split("").map((letter, idx) => (
0 ? "yellow" : "orange"}
@@ -322,7 +321,6 @@ const Pause = () => {
active={activeComponent === "exit"}
/>
))}
-
{
/>
+ {showingAbout && }
+
+
+
)}
>
diff --git a/src/components/Prompt.tsx b/src/components/Prompt.tsx
new file mode 100644
index 0000000..86f3ed5
--- /dev/null
+++ b/src/components/Prompt.tsx
@@ -0,0 +1,110 @@
+import React, { useCallback, useEffect } from "react";
+import answerContainer from "../static/sprite/prompt_answer_container.png";
+import questionContainer from "../static/sprite/prompt_question_container.png";
+import yes from "../static/sprite/prompt_yes.png";
+import no from "../static/sprite/prompt_no.png";
+import question from "../static/sprite/prompt_question.png";
+import { useLoader } from "react-three-fiber";
+import * as THREE from "three";
+import { useStore } from "../store";
+
+const Prompt = () => {
+ const promptVisible = useStore((state) => state.promptVisible);
+
+ const questionContainerTex = useLoader(
+ THREE.TextureLoader,
+ questionContainer
+ );
+ const answerContainerTex = useLoader(THREE.TextureLoader, answerContainer);
+ const questionTex = useLoader(THREE.TextureLoader, question);
+ const yesTex = useLoader(THREE.TextureLoader, yes);
+ const noTex = useLoader(THREE.TextureLoader, no);
+
+ const activeComponent = useStore(
+ useCallback(
+ (state) => state.promptComponentMatrix[state.promptComponentMatrixIdx],
+ []
+ )
+ );
+
+ useEffect(() => {
+ console.log(promptVisible);
+ }, [promptVisible]);
+ return (
+ <>
+ {promptVisible && (
+ <>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ >
+ )}
+ >
+ );
+};
+
+export default Prompt;
diff --git a/src/components/TextRenderer/BigLetter.tsx b/src/components/TextRenderer/BigLetter.tsx
index 7552843..470b2c2 100644
--- a/src/components/TextRenderer/BigLetter.tsx
+++ b/src/components/TextRenderer/BigLetter.tsx
@@ -100,6 +100,7 @@ const BigLetter = memo((props: { letter: string; letterIdx: number }) => {
useEffect(() => {
if (
subscene === "pause" ||
+ (subscene === "site" && prevData?.subscene === "not_found") ||
(subscene === "site" && prevData?.subscene === "pause")
)
return;
diff --git a/src/components/TextRenderer/YellowTextRenderer.tsx b/src/components/TextRenderer/YellowTextRenderer.tsx
index b71c0db..030adf1 100644
--- a/src/components/TextRenderer/YellowTextRenderer.tsx
+++ b/src/components/TextRenderer/YellowTextRenderer.tsx
@@ -3,7 +3,7 @@ import { useStore } from "../../store";
import { a, useTrail } from "@react-spring/three";
import BigLetter from "./BigLetter";
import usePrevious from "../../hooks/usePrevious";
-import {getNodeHud} from "../../utils/node-utils";
+import { getNodeHud } from "../../utils/node-utils";
const YellowTextRenderer = (props: { visible?: boolean }) => {
const activeNode = useStore((state) => state.activeNode);
@@ -22,6 +22,7 @@ const YellowTextRenderer = (props: { visible?: boolean }) => {
useEffect(() => {
const hud = getNodeHud(activeNode.matrixIndices!);
+
if (subscene === "level_selection") {
setTimeout(() => {
set({ posX: -0.02, posY: 0.005 });
diff --git a/src/core/scene-keypress-handlers/handleMainKeyPress.ts b/src/core/scene-keypress-handlers/handleMainKeyPress.ts
index a5846db..a9fab40 100644
--- a/src/core/scene-keypress-handlers/handleMainKeyPress.ts
+++ b/src/core/scene-keypress-handlers/handleMainKeyPress.ts
@@ -18,273 +18,308 @@ const handleMainSceneEvent = (mainSceneContext: any) => {
level,
keyPress,
ssknLvl,
+ showingAbout,
+ promptVisible,
+ activePromptComponent,
} = mainSceneContext;
- switch (subscene) {
- case "site":
- switch (keyPress) {
- case "LEFT":
- case "RIGHT": {
- const keyPressToLower = keyPress.toLowerCase();
-
- const nodeData = findNode(
- activeNode.id,
- keyPressToLower,
- activeNode.matrixIndices!,
- level,
- currentSite,
- gameProgress,
- true
- );
-
- if (!nodeData) return;
-
- if (nodeData.didMove) {
+ if (promptVisible) {
+ switch (keyPress) {
+ case "LEFT":
+ return { event: "prompt_left" };
+ case "RIGHT":
+ return { event: "prompt_right" };
+ case "CIRCLE":
+ switch (activePromptComponent) {
+ case "no":
+ return { event: "exit_prompt" };
+ case "yes":
return {
- event: keyPressToLower === "left" ? `site_left` : "site_right",
- siteRotY:
- keyPressToLower === "left"
- ? siteRotY + Math.PI / 4
- : siteRotY - Math.PI / 4,
- node: {
- ...(nodeData.node !== "unknown"
- ? getNodeById(nodeData.node, currentSite)
- : unknownNodeTemplate),
- matrixIndices: nodeData.matrixIndices,
- },
+ event: `pause_${activePauseComponent}_select`,
+ site: currentSite,
};
- } else {
- return {
- event: "change_node",
- nodeMatrixIndices: nodeData.matrixIndices,
- node: {
- ...getNodeById(nodeData.node, currentSite),
- matrixIndices: nodeData.matrixIndices,
- },
- };
- }
}
- case "UP":
- case "DOWN": {
- const keyPressToLower = keyPress.toLowerCase();
- const nodeData = findNode(
- activeNode.id,
- keyPressToLower,
- activeNode.matrixIndices!,
- level,
- currentSite,
- gameProgress,
- true
- );
+ }
+ } else {
+ switch (subscene) {
+ case "site":
+ switch (keyPress) {
+ case "LEFT":
+ case "RIGHT": {
+ const keyPressToLower = keyPress.toLowerCase();
- if (!nodeData) return;
+ const nodeData = findNode(
+ activeNode.id,
+ keyPressToLower,
+ activeNode.matrixIndices!,
+ level,
+ currentSite,
+ gameProgress,
+ true
+ );
- if (nodeData.didMove) {
- return {
- event: keyPressToLower === "up" ? "site_up" : "site_down",
- level: (keyPressToLower === "up" ? level + 1 : level - 1)
- .toString()
- .padStart(2, "0"),
- node: {
- ...(nodeData.node !== "unknown"
- ? getNodeById(nodeData.node, currentSite)
- : unknownNodeTemplate),
- matrixIndices: nodeData.matrixIndices,
- },
- };
- } else {
- return {
- event: "change_node",
- node: {
- ...getNodeById(nodeData.node, currentSite),
- matrixIndices: nodeData.matrixIndices,
- },
- };
+ if (!nodeData) return;
+
+ if (nodeData.didMove) {
+ return {
+ event: keyPressToLower === "left" ? `site_left` : "site_right",
+ siteRotY:
+ keyPressToLower === "left"
+ ? siteRotY + Math.PI / 4
+ : siteRotY - Math.PI / 4,
+ node: {
+ ...(nodeData.node !== "unknown"
+ ? getNodeById(nodeData.node, currentSite)
+ : unknownNodeTemplate),
+ matrixIndices: nodeData.matrixIndices,
+ },
+ };
+ } else {
+ return {
+ event: "change_node",
+ nodeMatrixIndices: nodeData.matrixIndices,
+ node: {
+ ...getNodeById(nodeData.node, currentSite),
+ matrixIndices: nodeData.matrixIndices,
+ },
+ };
+ }
}
- }
- case "CIRCLE":
- const eventAnimation =
- Math.random() < 0.4 ? "rip_node" : "throw_node";
+ case "UP":
+ case "DOWN": {
+ const keyPressToLower = keyPress.toLowerCase();
+ const nodeData = findNode(
+ activeNode.id,
+ keyPressToLower,
+ activeNode.matrixIndices!,
+ level,
+ currentSite,
+ gameProgress,
+ true
+ );
- const nodeType = activeNode.type;
+ if (!nodeData) return;
- if (activeNode.id === "" || !isNodeVisible(activeNode, gameProgress))
- return;
+ if (nodeData.didMove) {
+ return {
+ event: keyPressToLower === "up" ? "site_up" : "site_down",
+ level: (keyPressToLower === "up" ? level + 1 : level - 1)
+ .toString()
+ .padStart(2, "0"),
+ node: {
+ ...(nodeData.node !== "unknown"
+ ? getNodeById(nodeData.node, currentSite)
+ : unknownNodeTemplate),
+ matrixIndices: nodeData.matrixIndices,
+ },
+ };
+ } else {
+ return {
+ event: "change_node",
+ node: {
+ ...getNodeById(nodeData.node, currentSite),
+ matrixIndices: nodeData.matrixIndices,
+ },
+ };
+ }
+ }
+ case "CIRCLE":
+ const eventAnimation =
+ Math.random() < 0.4 ? "rip_node" : "throw_node";
- if (activeNode.upgrade_requirement > ssknLvl) {
- const rejectAnimations = [
- "touch_and_scare",
- "knock_and_fall",
- "knock",
- ];
+ const nodeType = activeNode.type;
- const pickedAnim =
- rejectAnimations[
- Math.floor(Math.random() * rejectAnimations.length)
+ if (
+ activeNode.id === "" ||
+ !isNodeVisible(activeNode, gameProgress)
+ )
+ return;
+
+ if (activeNode.upgrade_requirement > ssknLvl) {
+ const rejectAnimations = [
+ "touch_and_scare",
+ "knock_and_fall",
+ "knock",
];
- return {
- event: pickedAnim,
- siteRotY: siteRotY,
- };
- }
+ const pickedAnim =
+ rejectAnimations[
+ Math.floor(Math.random() * rejectAnimations.length)
+ ];
- switch (nodeType) {
- case 0:
- case 2:
- case 4:
- case 3:
- case 5:
return {
- event: `${eventAnimation}_media`,
- scene: "media",
+ event: pickedAnim,
siteRotY: siteRotY,
- level: level.toString().padStart(2, "0"),
};
- case 6:
- if (activeNode.node_name.substr(0, 3) === "TaK") {
- return {
- event: `${eventAnimation}_tak`,
- scene: "tak",
- siteRotY: siteRotY,
- node: activeNode,
- };
- } else {
+ }
+
+ switch (nodeType) {
+ case 0:
+ case 2:
+ case 4:
+ case 3:
+ case 5:
return {
event: `${eventAnimation}_media`,
scene: "media",
siteRotY: siteRotY,
level: level.toString().padStart(2, "0"),
};
- }
- case 8:
- return {
- event: `${eventAnimation}_gate`,
- scene: "gate",
- siteRotY: siteRotY,
- node: activeNode,
- };
- case 7:
- return {
- event: `${eventAnimation}_sskn`,
- scene: "sskn",
- siteRotY: siteRotY,
- };
- case 9:
- const bodyPart = (() => {
- switch (parseInt(activeNode.node_name.slice(-1))) {
- case 6:
- return "head";
- case 5:
- return "rightArm";
- case 4:
- return "leftArm";
- case 3:
- return "rightLeg";
- case 2:
- return "leftLeg";
- case 1:
- return "body";
+ case 6:
+ if (activeNode.node_name.substr(0, 3) === "TaK") {
+ return {
+ event: `${eventAnimation}_tak`,
+ scene: "tak",
+ siteRotY: siteRotY,
+ node: activeNode,
+ };
+ } else {
+ return {
+ event: `${eventAnimation}_media`,
+ scene: "media",
+ siteRotY: siteRotY,
+ level: level.toString().padStart(2, "0"),
+ };
}
- })();
+ case 8:
+ return {
+ event: `${eventAnimation}_gate`,
+ scene: "gate",
+ siteRotY: siteRotY,
+ node: activeNode,
+ };
+ case 7:
+ return {
+ event: `${eventAnimation}_sskn`,
+ scene: "sskn",
+ siteRotY: siteRotY,
+ };
+ case 9:
+ const bodyPart = (() => {
+ switch (parseInt(activeNode.node_name.slice(-1))) {
+ case 6:
+ return "head";
+ case 5:
+ return "rightArm";
+ case 4:
+ return "leftArm";
+ case 3:
+ return "rightLeg";
+ case 2:
+ return "leftLeg";
+ case 1:
+ return "body";
+ }
+ })();
+ return {
+ event: `${eventAnimation}_polytan`,
+ scene: "polytan",
+ siteRotY: siteRotY,
+ node: activeNode,
+ bodyPart: bodyPart,
+ };
+ }
+ break;
+ case "L2":
+ return { event: "toggle_level_selection", level: level };
+ case "TRIANGLE":
+ return { event: "pause_game" };
+ case "SPACE":
+ return { event: "play_with_hair", siteRotY: siteRotY };
+ }
+ break;
+ case "level_selection":
+ switch (keyPress) {
+ case "UP":
+ if (currentSite === "a") {
+ if (selectedLevel + 1 <= 22)
+ return {
+ event: `level_selection_up`,
+ selectedLevelIdx: selectedLevel + 1,
+ };
+ } else if (currentSite === "b") {
+ if (selectedLevel + 1 <= 13)
+ return {
+ event: `level_selection_up`,
+ selectedLevelIdx: selectedLevel + 1,
+ };
+ }
+ break;
+ case "DOWN":
+ if (selectedLevel - 1 >= 1)
return {
- event: `${eventAnimation}_polytan`,
- scene: "polytan",
- siteRotY: siteRotY,
- node: activeNode,
- bodyPart: bodyPart,
+ event: `level_selection_down`,
+ selectedLevelIdx: selectedLevel - 1,
};
- }
- break;
- case "L2":
- return { event: "toggle_level_selection", level: level };
- case "TRIANGLE":
- return { event: "pause_game" };
- case "SPACE":
- return { event: "play_with_hair", siteRotY: siteRotY };
- }
- break;
- case "level_selection":
- switch (keyPress) {
- case "UP":
- if (currentSite === "a") {
- if (selectedLevel + 1 <= 22)
- return {
- event: `level_selection_up`,
- selectedLevelIdx: selectedLevel + 1,
- };
- } else if (currentSite === "b") {
- if (selectedLevel + 1 <= 13)
- return {
- event: `level_selection_up`,
- selectedLevelIdx: selectedLevel + 1,
- };
- }
- break;
- case "DOWN":
- if (selectedLevel - 1 >= 1)
+ break;
+ case "X":
return {
- event: `level_selection_down`,
- selectedLevelIdx: selectedLevel - 1,
+ event: "level_selection_back",
};
- break;
- case "X":
+
+ case "CIRCLE":
+ if (level === selectedLevel) return;
+
+ const direction = selectedLevel > level ? "up" : "down";
+
+ const rowIdx = direction === "up" ? 2 : 0;
+ const nodeData = findNode(
+ activeNode.id,
+ direction,
+ { ...activeNode.matrixIndices!, rowIdx: rowIdx },
+ selectedLevel,
+ currentSite,
+ gameProgress,
+ false
+ );
+
+ if (nodeData) {
+ const event =
+ selectedLevel < level ? "select_level_down" : "select_level_up";
+ return {
+ event: event,
+ node: {
+ ...(nodeData.node !== "unknown"
+ ? getNodeById(nodeData.node, currentSite)
+ : unknownNodeTemplate),
+ matrixIndices: nodeData.matrixIndices,
+ },
+ level: selectedLevel.toString().padStart(2, "0"),
+ };
+ }
+ }
+ break;
+ case "pause":
+ if (showingAbout)
return {
- event: "level_selection_back",
+ event: "exit_about",
};
-
- case "CIRCLE":
- if (level === selectedLevel) return;
-
- const direction = selectedLevel > level ? "up" : "down";
-
- const rowIdx = direction === "up" ? 2 : 0;
- const nodeData = findNode(
- activeNode.id,
- direction,
- { ...activeNode.matrixIndices!, rowIdx: rowIdx },
- selectedLevel,
- currentSite,
- gameProgress,
- false
- );
-
- if (nodeData) {
- const event =
- selectedLevel < level ? "select_level_down" : "select_level_up";
- return {
- event: event,
- node: {
- ...(nodeData.node !== "unknown"
- ? getNodeById(nodeData.node, currentSite)
- : unknownNodeTemplate),
- matrixIndices: nodeData.matrixIndices,
- },
- level: selectedLevel.toString().padStart(2, "0"),
- };
+ else {
+ switch (keyPress) {
+ case "UP":
+ if (pauseMatrixIdx - 1 < 0) break;
+ return {
+ event: "pause_up",
+ pauseMatrixIdx: pauseMatrixIdx - 1,
+ };
+ case "DOWN":
+ if (pauseMatrixIdx + 1 > 4) break;
+ return {
+ event: "pause_down",
+ pauseMatrixIdx: pauseMatrixIdx + 1,
+ };
+ case "CIRCLE":
+ if (activePauseComponent === "change") {
+ return {
+ event: "display_prompt",
+ };
+ }
}
- }
- break;
- case "pause":
- switch (keyPress) {
- case "UP":
- if (pauseMatrixIdx - 1 < 0) break;
- return {
- event: "pause_up",
- pauseMatrixIdx: pauseMatrixIdx - 1,
- };
- case "DOWN":
- if (pauseMatrixIdx + 1 > 4) break;
- return {
- event: "pause_down",
- pauseMatrixIdx: pauseMatrixIdx + 1,
- };
- case "CIRCLE":
- return {
- event: `pause_${activePauseComponent}_select`,
- site: currentSite,
- };
- }
+ }
+ break;
+ case "not_found":
+ return { event: "exit_not_found" };
+ }
}
};
diff --git a/src/core/scene-keypress-handlers/handleMediaKeyPress.ts b/src/core/scene-keypress-handlers/handleMediaKeyPress.ts
index 34a8147..aa4d53f 100644
--- a/src/core/scene-keypress-handlers/handleMediaKeyPress.ts
+++ b/src/core/scene-keypress-handlers/handleMediaKeyPress.ts
@@ -8,6 +8,7 @@ const handleMediaKeyPress = (mediaSceneContext: any) => {
rightSideComponentIdx,
activeNode,
activeSite,
+ gameProgress,
} = mediaSceneContext;
const calculateNewRightSide = (
@@ -72,14 +73,14 @@ const handleMediaKeyPress = (mediaSceneContext: any) => {
const data = findNodeFromWord(
activeMediaComponent,
activeNode,
- activeSite
+ activeSite,
+ gameProgress
);
if (data) {
return { event: `media_${activeMediaComponent}_select`, ...data };
} else {
- // todo in case node isnt unlocked yet
- return;
+ return { event: `word_node_not_found` };
}
default:
if (activeMediaComponent === "play") {
diff --git a/src/core/setters/main/mainSubsceneManager.ts b/src/core/setters/main/mainSubsceneManager.ts
index 5e97a26..b77b7c8 100644
--- a/src/core/setters/main/mainSubsceneManager.ts
+++ b/src/core/setters/main/mainSubsceneManager.ts
@@ -5,9 +5,15 @@ const mainSubsceneManager = (eventState: any) => {
const dispatchAction = (eventState: { event: string }) => {
switch (eventState.event) {
+ case "word_node_not_found":
+ return {
+ action: () => setMainSubscene("not_found"),
+ delay: 0,
+ };
case "level_selection_back":
case "select_level_up":
case "select_level_down":
+ case "exit_not_found":
return {
action: () => setMainSubscene("site"),
delay: 0,
diff --git a/src/core/setters/main/pause/pauseManager.ts b/src/core/setters/main/pause/pauseManager.ts
index 6e1eb42..fe5b59a 100644
--- a/src/core/setters/main/pause/pauseManager.ts
+++ b/src/core/setters/main/pause/pauseManager.ts
@@ -5,6 +5,7 @@ type PauseManagerProps = { event: string; pauseMatrixIdx: number };
const pauseManager = (eventState: any) => {
const setComponentMatrixIdx = useStore.getState().setPauseComponentMatrixIdx;
const setExitAnimation = useStore.getState().setPauseExitAnimation;
+ const setShowingAbout = useStore.getState().setShowingAbout;
const dispatchAction = (eventState: PauseManagerProps) => {
switch (eventState.event) {
@@ -17,6 +18,14 @@ const pauseManager = (eventState: any) => {
return {
action: () => setExitAnimation(true),
};
+ case "pause_about_select":
+ return {
+ action: () => setShowingAbout(true),
+ };
+ case "exit_about":
+ return {
+ action: () => setShowingAbout(false),
+ };
case "pause_game":
return { action: () => setExitAnimation(false) };
}
diff --git a/src/core/setters/media/mediaManager.ts b/src/core/setters/media/mediaManager.ts
index b7d612c..a23ef72 100644
--- a/src/core/setters/media/mediaManager.ts
+++ b/src/core/setters/media/mediaManager.ts
@@ -1,5 +1,4 @@
import { useStore } from "../../../store";
-import { useCallback } from "react";
import * as THREE from "three";
const mediaManager = (eventState: any) => {
diff --git a/src/core/setters/promptManager.ts b/src/core/setters/promptManager.ts
new file mode 100644
index 0000000..323df44
--- /dev/null
+++ b/src/core/setters/promptManager.ts
@@ -0,0 +1,32 @@
+import { useStore } from "../../store";
+
+const promptManager = (eventState: any) => {
+ const setComponentMatrixIdx = useStore.getState().setPromptComponentMatrixIdx;
+ const setPromptVisible = useStore.getState().setPromptVisible;
+
+ const dispatchAction = (eventState: { event: string; scene: string }) => {
+ switch (eventState.event) {
+ case "display_prompt": {
+ return { action: () => setPromptVisible(true) };
+ }
+ case "prompt_right":
+ return {
+ action: () => setComponentMatrixIdx(1),
+ };
+ case "prompt_left":
+ return { action: () => setComponentMatrixIdx(0) };
+ case "pause_change_select":
+ return { action: () => setPromptVisible(false) };
+ case "exit_prompt":
+ return { action: () => setPromptVisible(false) };
+ }
+ };
+
+ const { action } = { ...dispatchAction(eventState) };
+
+ if (action) {
+ action();
+ }
+};
+
+export default promptManager;
diff --git a/src/core/setters/sceneManager.ts b/src/core/setters/sceneManager.ts
index f249270..3a0c557 100644
--- a/src/core/setters/sceneManager.ts
+++ b/src/core/setters/sceneManager.ts
@@ -52,6 +52,7 @@ const sceneManager = (eventState: any) => {
case "media_fstWord_select":
case "media_sndWord_select":
case "media_thirdWord_select":
+ case "word_node_not_found":
return {
action: () =>
useStore.setState({ currentScene: "main", intro: false }),
diff --git a/src/scenes/MainScene.tsx b/src/scenes/MainScene.tsx
index 19804d7..4b7e89c 100644
--- a/src/scenes/MainScene.tsx
+++ b/src/scenes/MainScene.tsx
@@ -13,6 +13,7 @@ import Site from "../components/MainScene/Site";
import Lain from "../components/MainScene/Lain";
import * as THREE from "three";
import { useFrame } from "react-three-fiber";
+import NotFound from "../components/MainScene/NotFound";
const MainScene = () => {
const intro = useStore((state) => state.intro);
@@ -94,10 +95,13 @@ const MainScene = () => {
+
-
-
+
+
+
+
diff --git a/src/store.ts b/src/store.ts
index a68e100..5196456 100644
--- a/src/store.ts
+++ b/src/store.ts
@@ -44,6 +44,7 @@ type State = {
pauseComponentMatrix: ["load", "about", "change", "save", "exit"];
pauseComponentMatrixIdx: number;
pauseExitAnimation: boolean;
+ showingAbout: boolean;
// media/media scene
audioAnalyser: undefined | THREE.AudioAnalyser;
@@ -98,6 +99,11 @@ type State = {
// end scene
endMediaPlayedCount: number;
+ // prompt
+ promptVisible: boolean;
+ promptComponentMatrix: ["yes", "no"];
+ promptComponentMatrixIdx: 1 | 0;
+
// save state
siteSaveState: {
a: {
@@ -188,6 +194,7 @@ export const useStore = create(
pauseComponentMatrix: ["load", "about", "change", "save", "exit"],
pauseComponentMatrixIdx: 2,
pauseExitAnimation: false,
+ showingAbout: false,
// media / media scene
audioAnalyser: undefined,
@@ -249,6 +256,11 @@ export const useStore = create(
// end scene
endMediaPlayedCount: 0,
+ // prompt
+ promptVisible: false,
+ promptComponentMatrix: ["yes", "no"],
+ promptComponentMatrixIdx: 1,
+
// save states for loading the game/changing sites
siteSaveState: {
a: {
@@ -325,6 +337,7 @@ export const useStore = create(
set(() => ({ pauseComponentMatrixIdx: to })),
setPauseExitAnimation: (to: boolean) =>
set(() => ({ pauseExitAnimation: to })),
+ setShowingAbout: (to: boolean) => set(() => ({ showingAbout: to })),
// media/media scene setters
toggleMediaSide: () =>
@@ -404,6 +417,11 @@ export const useStore = create(
})),
resetEndMediaPlayedCount: () => set(() => ({ endMediaPlayedCount: 0 })),
+ // prompt setters
+ setPromptVisible: (to: boolean) => set(() => ({ promptVisible: to })),
+ setPromptComponentMatrixIdx: (to: 1 | 0) =>
+ set(() => ({ promptComponentMatrixIdx: to })),
+
// site state setters
setSiteSaveState: (
site: string,
@@ -467,6 +485,10 @@ export const getMainSceneContext = () => {
activeNode: state.activeNode,
level: parseInt(state.activeLevel),
ssknLvl: state.ssknLvl,
+ showingAbout: state.showingAbout,
+ promptVisible: state.promptVisible,
+ activePromptComponent:
+ state.promptComponentMatrix[state.promptComponentMatrixIdx],
};
};
@@ -493,5 +515,6 @@ export const getMediaSceneContext = () => {
wordPosStateIdx: state.mediaWordPosStateIdx,
activeNode: state.activeNode,
activeSite: state.activeSite,
+ gameProgress: state.gameProgress,
};
};
diff --git a/src/utils/media-utils.ts b/src/utils/media-utils.ts
index 3298282..8a7f5be 100644
--- a/src/utils/media-utils.ts
+++ b/src/utils/media-utils.ts
@@ -1,15 +1,14 @@
import site_a from "../resources/site_a.json";
import site_b from "../resources/site_b.json";
import node_matrices from "../resources/node_matrices.json";
-import {
- NodeDataType,
- SiteType,
-} from "../components/MainScene/Site";
+import { NodeDataType, SiteType } from "../components/MainScene/Site";
+import { isNodeVisible } from "./node-utils";
export const findNodeFromWord = (
wordLabel: string,
activeNode: NodeDataType,
- site: "a" | "b"
+ site: "a" | "b",
+ gameProgress: any
) => {
const labelToIdx = (() => {
switch (wordLabel) {
@@ -41,7 +40,8 @@ export const findNodeFromWord = (
) + 1
] ?? nodesWithSameWords[0];
- //todo check if visible
+ if (!isNodeVisible(chosenNode, gameProgress)) return;
+
const pos = chosenNode.id.substr(2);
const matrixIndices = Object.entries(node_matrices).flatMap((matrixData) =>