diff --git a/src/components/BootScene/BootAuthorizeUser.tsx b/src/components/BootScene/BootAuthorizeUser.tsx index 3309edc..8dac128 100644 --- a/src/components/BootScene/BootAuthorizeUser.tsx +++ b/src/components/BootScene/BootAuthorizeUser.tsx @@ -44,78 +44,33 @@ const BootAuthorizeUser = (props: BootAuthorizeUserProps) => { authorizeActiveLetters ); - const letterIdx = useStore((state) => state.authorizeUserLetterIdx); const subscene = useStore((state) => state.bootSubscene); - const prevData = usePrevious({ letterIdx, subscene }); + const authorizeUserMatrixIndices = useStore( + (state) => state.authorizeUserMatrixIndices + ); const bgLettersRef = useRef(); const activeLetterMap = useMemo(() => { activeLettersTex.wrapT = activeLettersTex.wrapS = THREE.RepeatWrapping; activeLettersTex.repeat.set(0.06, 0.2); - activeLettersTex.offset.x = 0; - activeLettersTex.offset.y = -0.2; + activeLettersTex.offset.x = 0.0775 * authorizeUserMatrixIndices.colIdx; + activeLettersTex.offset.y = -0.2 - 0.2 * authorizeUserMatrixIndices.rowIdx; return activeLettersTex; - }, [activeLettersTex]); - - useEffect(() => { - if (prevData?.subscene === "main_menu" && subscene === "authorize_user") { - activeLetterMap.offset.x = 0; - activeLetterMap.offset.y = -0.2; - } - }, [subscene, prevData?.subscene, activeLetterMap.offset]); + }, [ + activeLettersTex, + authorizeUserMatrixIndices.colIdx, + authorizeUserMatrixIndices.rowIdx, + ]); useEffect(() => { if (bgLettersRef.current) { - //down - if (prevData!.letterIdx + 13 === letterIdx) { - bgLettersRef.current.position.y += 0.25; - activeLetterMap.offset.y -= 0.2; - // down skip - } else if (letterIdx === prevData!.letterIdx + 26) { - bgLettersRef.current.position.y += 0.5; - activeLetterMap.offset.y -= 0.4; - } else if (letterIdx === prevData!.letterIdx + 52) { - bgLettersRef.current.position.y += 1; - activeLetterMap.offset.y -= 0.8; - } - // up - else if (letterIdx === prevData!.letterIdx - 13) { - bgLettersRef.current.position.y -= 0.25; - activeLetterMap.offset.y += 0.2; - // up skip - } else if (letterIdx === prevData!.letterIdx - 26) { - bgLettersRef.current.position.y -= 0.5; - activeLetterMap.offset.y += 0.4; - } else if (letterIdx === prevData!.letterIdx - 52) { - bgLettersRef.current.position.y -= 1; - activeLetterMap.offset.y += 0.8; - } - // left - else if (letterIdx === prevData!.letterIdx - 1) { - bgLettersRef.current.position.x += 0.3; - activeLetterMap.offset.x -= 0.0775; - } - // left skip - else if (letterIdx === prevData!.letterIdx - 2) { - bgLettersRef.current.position.x += 0.6; - activeLetterMap.offset.x -= 0.155; - } - // right - else if (letterIdx === prevData!.letterIdx + 1) { - bgLettersRef.current.position.x -= 0.3; - activeLetterMap.offset.x += 0.0775; - } else if (letterIdx === prevData!.letterIdx + 2) { - bgLettersRef.current.position.x -= 0.6; - activeLetterMap.offset.x += 0.155; - } + bgLettersRef.current.position.y = + -0.7 + 0.25 * authorizeUserMatrixIndices.rowIdx; + bgLettersRef.current.position.x = + 3.35 - 0.3 * authorizeUserMatrixIndices.colIdx; } - - return () => { - activeLetterMap.offset.x = 0; - activeLetterMap.offset.y = -0.2; - }; - }, [activeLetterMap.offset, letterIdx, prevData]); + }, [authorizeUserMatrixIndices.colIdx, authorizeUserMatrixIndices.rowIdx]); const playerName = useStore((state) => state.playerName.split("")); diff --git a/src/components/GateScene/GateMiddleObject.tsx b/src/components/GateScene/GateMiddleObject.tsx index fe197b5..53c9cea 100644 --- a/src/components/GateScene/GateMiddleObject.tsx +++ b/src/components/GateScene/GateMiddleObject.tsx @@ -67,6 +67,7 @@ const GateMiddleObject = (props: GateMiddleObjectProps) => { } posX={item.posX} posY={item.posY} + key={idx} /> ))} diff --git a/src/components/Images.tsx b/src/components/Images.tsx index 48f6638..064bebf 100644 --- a/src/components/Images.tsx +++ b/src/components/Images.tsx @@ -57,24 +57,27 @@ const Images = () => { }, [currentScene, activeSite, idleNodeImages, nodeImages]); useEffect(() => { - const loadNewImage = (imgIdx: number) => { - setImageScaleY(0); + let timer: ReturnType; - setTimeout(() => { - textureLoader.load(sceneImages[imgIdx].default, setActiveImage); + if (mediaPercentageElapsed === 0 && sceneImages[0]) { + textureLoader.load(sceneImages[0].default, setActiveImage); + } else if (mediaPercentageElapsed === 35 && sceneImages[1]) { + setImageScaleY(0); + timer = setTimeout(() => { + textureLoader.load(sceneImages[1].default, setActiveImage); setImageScaleY(3.75); }, 300); - }; + } else if (mediaPercentageElapsed === 70 && sceneImages[2]) { + setImageScaleY(0); + timer = setTimeout(() => { + textureLoader.load(sceneImages[1].default, setActiveImage); + setImageScaleY(3.75); + }, 300); + } - (async () => { - if (mediaPercentageElapsed === 0 && sceneImages[0]) { - textureLoader.load(sceneImages[0].default, setActiveImage); - } else if (mediaPercentageElapsed === 35 && sceneImages[1]) { - loadNewImage(1); - } else if (mediaPercentageElapsed === 70 && sceneImages[2]) { - loadNewImage(2); - } - })(); + return () => { + clearTimeout(timer); + }; }, [mediaPercentageElapsed, sceneImages, textureLoader]); return ( diff --git a/src/components/InputHandler.tsx b/src/components/InputHandler.tsx index 6853d69..b3bc5d8 100644 --- a/src/components/InputHandler.tsx +++ b/src/components/InputHandler.tsx @@ -1,4 +1,4 @@ -import React, { useCallback, useEffect, useMemo, useRef } from "react"; +import React, { useCallback, useEffect, useRef } from "react"; import { getBootSceneContext, getEndSceneContext, @@ -15,8 +15,11 @@ import handleBootSceneInput from "../core/input-handlers/handleBootSceneInput"; import handleEndSceneInput from "../core/input-handlers/handleEndSceneInput"; import handleEvent from "../core/handleEvent"; import { GameEvent } from "../types/types"; -import { useLoader } from "react-three-fiber"; +import { MouseEvent, useLoader } from "react-three-fiber"; import circleButton from "../static/sprites/controller/circle.png"; +import squareButton from "../static/sprites/controller/square.png"; +import triangleButton from "../static/sprites/controller/triangle.png"; +import crossButton from "../static/sprites/controller/cross.png"; import * as THREE from "three"; import { useGesture } from "react-use-gesture"; import IdleManager from "./IdleManager"; @@ -26,6 +29,9 @@ const InputHandler = () => { const inputCooldown = useStore((state) => state.inputCooldown); const circleButtonTex = useLoader(THREE.TextureLoader, circleButton); + const crossButtonTex = useLoader(THREE.TextureLoader, crossButton); + const squareButtonTex = useLoader(THREE.TextureLoader, squareButton); + const triangleButtonTex = useLoader(THREE.TextureLoader, triangleButton); const timeSinceLastKeyPress = useRef(-1); @@ -132,6 +138,13 @@ const InputHandler = () => { [handleKeyPress] ); + const handleVirtualButtonPress = useCallback( + (event: MouseEvent) => { + handleKeyPress(event.object.name); + }, + [handleKeyPress] + ); + useEffect(() => { window.addEventListener("keydown", handleKeyBoardEvent); @@ -152,6 +165,65 @@ const InputHandler = () => { + + + + + + + + + + + + + + + { const generateSqaureGeom = useCallback((row: number, square: number) => { @@ -40,6 +41,7 @@ const Pause = () => { ); const subscene = useStore((state) => state.mainSubscene); + const prevData = usePrevious({ subscene }); const setInputCooldown = useStore((state) => state.setInputCooldown); const [visible, setVisible] = useState(false); @@ -59,15 +61,15 @@ const Pause = () => { setTimeout(() => setInputCooldown(1000), 7600); } - return () => { + if (prevData?.subscene === "pause" && subscene === "site") { setExit(true); setTimeout(() => { setVisible(false); setFinished(false); setExit(false); }, 1200); - }; - }, [setInputCooldown, subscene]); + } + }, [prevData?.subscene, setInputCooldown, subscene]); const whenActive = useCallback((rowIdx: number, colIdx: number) => { switch (rowIdx) { diff --git a/src/core/eventTemplates.ts b/src/core/eventTemplates.ts index 9402b15..be94900 100644 --- a/src/core/eventTemplates.ts +++ b/src/core/eventTemplates.ts @@ -9,6 +9,7 @@ import { import { playMediaElement, resetMediaElement } from "../helpers/media-helpers"; import { ActiveSite, + AuthorizeUserMatrixIndices, EndComponent, GameScene, LeftMediaComponent, @@ -164,9 +165,7 @@ export const knockNode = { export const knockNodeAndFall = { state: [ { mutation: { lainMoveState: "knock_and_fall", inputCooldown: 6000 } }, - { - mutation: { lainMoveState: "standing" }, - }, + { mutation: { lainMoveState: "standing" }, delay: 6000 }, ], effects: [nodeKnockAndFallAnimation], audio: [ @@ -649,7 +648,6 @@ export const enterUserAuthorization = { { mutation: { bootSubscene: "authorize_user", - authorizeUserLetterIdx: 0, inputCooldown: 500, }, }, @@ -664,6 +662,7 @@ export const exitUserAuthorization = { playerName: "", bootSubscene: "main_menu", inputCooldown: 500, + authorizeUserMatrixIndices: { rowIdx: 0, colIdx: 0 }, }, }, ], @@ -690,14 +689,15 @@ export const removePlayerNameLastChar = (calculatedState: { export const failUpdatePlayerName = { audio: [{ sfx: [audio.sound0] }] }; -export const updateAuthorizeUserLetterIdx = (calculatedState: { - authorizeUserLetterIdx: number; +export const updateAuthorizeUserLetterMatrixIndices = (calculatedState: { + authorizeUserLetterMatrixIndices: AuthorizeUserMatrixIndices; }) => ({ state: [ { mutation: { inputCooldown: 300, - authorizeUserLetterIdx: calculatedState.authorizeUserLetterIdx, + authorizeUserMatrixIndices: + calculatedState.authorizeUserLetterMatrixIndices, }, }, ], diff --git a/src/core/input-handlers/handleBootSceneInput.ts b/src/core/input-handlers/handleBootSceneInput.ts index b4c9ca0..b4ea66b 100644 --- a/src/core/input-handlers/handleBootSceneInput.ts +++ b/src/core/input-handlers/handleBootSceneInput.ts @@ -12,7 +12,7 @@ import { loadGameFail, removePlayerNameLastChar, startNewGame, - updateAuthorizeUserLetterIdx, + updateAuthorizeUserLetterMatrixIndices, updatePlayerName, } from "../eventTemplates"; import { BootSceneContext, GameEvent } from "../../types/types"; @@ -26,8 +26,8 @@ const handleBootSceneInput = ( activeMainMenuComponent, activePromptComponent, promptVisible, - authorizeUserLetterIdx, playerName, + authorizeUserMatrixIndices, } = bootSceneContext; if (promptVisible) { @@ -83,119 +83,76 @@ const handleBootSceneInput = ( } else { return exitUserAuthorization; } - case "LEFT": - // if utmost left, break - if ( - [0, 13, 26, 39, 52].includes(authorizeUserLetterIdx) || - authorizeUserLetterIdx === 15 - ) - return; - // skip - else if ( - authorizeUserLetterIdx === 41 || - authorizeUserLetterIdx === 17 || - authorizeUserLetterIdx === 30 || - authorizeUserLetterIdx === 43 || - authorizeUserLetterIdx === 19 || - authorizeUserLetterIdx === 45 - ) { - return updateAuthorizeUserLetterIdx({ - authorizeUserLetterIdx: authorizeUserLetterIdx - 2, - }); - } else { - return updateAuthorizeUserLetterIdx({ - authorizeUserLetterIdx: authorizeUserLetterIdx - 1, - }); - } - case "RIGHT": - // if utmost right, break - if ([12, 25, 38, 51, 64].includes(authorizeUserLetterIdx)) return; - // skip empty - else if ( - authorizeUserLetterIdx === 39 || - authorizeUserLetterIdx === 41 || - authorizeUserLetterIdx === 28 || - authorizeUserLetterIdx === 15 || - authorizeUserLetterIdx === 43 || - authorizeUserLetterIdx === 17 - ) { - return updateAuthorizeUserLetterIdx({ - authorizeUserLetterIdx: authorizeUserLetterIdx + 2, - }); - } else { - return updateAuthorizeUserLetterIdx({ - authorizeUserLetterIdx: authorizeUserLetterIdx + 1, - }); - } - case "DOWN": - // if utmost down, break - if ( - Array.from(new Array(13), (x, i) => i + 52).includes( - authorizeUserLetterIdx - ) - ) { - return; - // skip empty - } else if ( - authorizeUserLetterIdx === 0 || - authorizeUserLetterIdx === 1 || - authorizeUserLetterIdx === 52 || - authorizeUserLetterIdx === 27 || - authorizeUserLetterIdx === 31 || - authorizeUserLetterIdx === 5 - ) { - return updateAuthorizeUserLetterIdx({ - authorizeUserLetterIdx: authorizeUserLetterIdx + 26, - }); - } else if (authorizeUserLetterIdx === 3) { - return updateAuthorizeUserLetterIdx({ - authorizeUserLetterIdx: authorizeUserLetterIdx + 52, - }); - } else { - return updateAuthorizeUserLetterIdx({ - authorizeUserLetterIdx: authorizeUserLetterIdx + 13, - }); - } - case "UP": - // if utmost up, break - if ( - Array.from(new Array(13), (x, i) => i).includes( - authorizeUserLetterIdx - ) - ) { - return; - // skip empty - } else if ( - authorizeUserLetterIdx === 26 || - authorizeUserLetterIdx === 27 || - authorizeUserLetterIdx === 53 || - authorizeUserLetterIdx === 31 || - authorizeUserLetterIdx === 57 - ) { - return updateAuthorizeUserLetterIdx({ - authorizeUserLetterIdx: authorizeUserLetterIdx - 26, - }); - } else if (authorizeUserLetterIdx === 55) { - return updateAuthorizeUserLetterIdx({ - authorizeUserLetterIdx: authorizeUserLetterIdx - 52, - }); - } else { - return updateAuthorizeUserLetterIdx({ - authorizeUserLetterIdx: authorizeUserLetterIdx - 13, - }); - } + case "LEFT": { + const newMatrixIndices = { + ...authorizeUserMatrixIndices, + colIdx: + authorizeUserMatrixIndices.colIdx - 1 < 0 + ? authorizeUserMatrixIndices.colIdx + : authorizeUserMatrixIndices.colIdx - 1, + }; + + return updateAuthorizeUserLetterMatrixIndices({ + authorizeUserLetterMatrixIndices: newMatrixIndices, + }); + } + + case "RIGHT": { + const newMatrixIndices = { + ...authorizeUserMatrixIndices, + colIdx: + authorizeUserMatrixIndices.colIdx + 1 > 12 + ? authorizeUserMatrixIndices.colIdx + : authorizeUserMatrixIndices.colIdx + 1, + }; + + return updateAuthorizeUserLetterMatrixIndices({ + authorizeUserLetterMatrixIndices: newMatrixIndices, + }); + } + + case "DOWN": { + const newMatrixIndices = { + ...authorizeUserMatrixIndices, + rowIdx: + authorizeUserMatrixIndices.rowIdx + 1 > 4 + ? authorizeUserMatrixIndices.rowIdx + : authorizeUserMatrixIndices.rowIdx + 1, + }; + + return updateAuthorizeUserLetterMatrixIndices({ + authorizeUserLetterMatrixIndices: newMatrixIndices, + }); + } + + case "UP": { + const newMatrixIndices = { + ...authorizeUserMatrixIndices, + rowIdx: + authorizeUserMatrixIndices.rowIdx - 1 < 0 + ? authorizeUserMatrixIndices.rowIdx + : authorizeUserMatrixIndices.rowIdx - 1, + }; + + return updateAuthorizeUserLetterMatrixIndices({ + authorizeUserLetterMatrixIndices: newMatrixIndices, + }); + } + case "CIRCLE": const chosenCharacter = - authorize_user_letters[ - authorizeUserLetterIdx.toString() as keyof typeof authorize_user_letters + authorize_user_letters.matrix[authorizeUserMatrixIndices.rowIdx][ + authorizeUserMatrixIndices.colIdx ]; - const newName = handleNameSelection(playerName, chosenCharacter); + if (chosenCharacter) { + const newName = handleNameSelection(playerName, chosenCharacter); - if (newName?.length === 8) return; - if (newName !== undefined) - return updatePlayerName({ playerName: newName }); - else return failUpdatePlayerName; + if (newName?.length === 8) return; + if (newName !== undefined) + return updatePlayerName({ playerName: newName }); + else return failUpdatePlayerName; + } } } } diff --git a/src/resources/authorize_user_letters.json b/src/resources/authorize_user_letters.json index 449566b..3ae9821 100644 --- a/src/resources/authorize_user_letters.json +++ b/src/resources/authorize_user_letters.json @@ -1,67 +1,9 @@ { - "0": "ッ", - "1": "ャ", - "2": "ァ", - "3": "ワ", - "4": "ラ", - "5": "ヤ", - "6": "マ", - "7": "ハ", - "8": "ナ", - "9": "タ", - "10": "サ", - "11": "カ", - "12": "ア", - "13": "", - "14": "", - "15": "ィ", - "16": "", - "17": "リ", - "18": "", - "19": "ミ", - "20": "ヒ", - "21": "ニ", - "22": "チ", - "23": "シ", - "24": "キ", - "25": "イ", - "26": "゛", - "27": "ュ", - "28": "ゥ", - "29": "", - "30": "ル", - "31": "ユ", - "32": "ム", - "33": "フ", - "34": "ヌ", - "35": "ツ", - "36": "ス", - "37": "ク", - "38": "ウ", - "39": "゜", - "40": "", - "41": "ェ", - "42": "", - "43": "レ", - "44": "", - "45": "メ", - "46": "ヘ", - "47": "ネ", - "48": "テ", - "49": "セ", - "50": "ケ", - "51": "エ", - "52": "ー", - "53": "ョ", - "54": "ォ", - "55": "ン", - "56": "ロ", - "57": "ヨ", - "58": "モ", - "59": "ホ", - "60": "ノ", - "61": "ト", - "62": "ソ", - "63": "コ", - "64": "オ" + "matrix": [ + [ "ッ", "ャ", "ァ", "ワ", "ラ", "ヤ", "マ", "ハ", "ナ", "タ", "サ", "カ", "ア"], + [null, null, "ィ", null, "リ", null, "ミ", "ヒ", "ニ", "チ", "シ", "キ", "イ"], + ["゛", "ュ", "ゥ", null, "ル", "ユ", "ム", "フ", "ヌ", "ツ", "ス", "ク", "ウ"], + ["゜", null, "ェ", null, "レ", null, "メ", "ヘ", "ネ", "テ", "セ", "ケ", "エ"], + [ "ー", "ョ", "ォ", "ン", "ロ", "ヨ", "モ", "ホ", "ノ", "ト", "ソ", "コ", "オ" ] + ] } diff --git a/src/scenes/BootScene.tsx b/src/scenes/BootScene.tsx index 48dfa95..e0699d8 100644 --- a/src/scenes/BootScene.tsx +++ b/src/scenes/BootScene.tsx @@ -22,7 +22,7 @@ const BootScene = () => { }, [setInputCooldown]); return ( - + { /> - + ); }; export default BootScene; diff --git a/src/scenes/GateScene.tsx b/src/scenes/GateScene.tsx index 88005ac..33883a2 100644 --- a/src/scenes/GateScene.tsx +++ b/src/scenes/GateScene.tsx @@ -24,12 +24,12 @@ const GateScene = () => { }, [activeNodeName, incrementGateLvl, setInputCooldown, setNodeViewed]); return ( - + - + ); }; export default GateScene; diff --git a/src/scenes/IdleMediaScene.tsx b/src/scenes/IdleMediaScene.tsx index 5956039..0e17d29 100644 --- a/src/scenes/IdleMediaScene.tsx +++ b/src/scenes/IdleMediaScene.tsx @@ -37,7 +37,9 @@ const IdleMediaScene = () => { if (vtt) trackElement.src = vtt.default; }) // some entries have no spoken words, so the file doesnt exist. we catch that here. - .catch(() => console.log("no subtitles for this media")); + .catch(() => { + trackElement.removeAttribute("src"); + }); } if (idleMedia.includes("XA")) { diff --git a/src/scenes/MainScene.tsx b/src/scenes/MainScene.tsx index d49423e..fee6a03 100644 --- a/src/scenes/MainScene.tsx +++ b/src/scenes/MainScene.tsx @@ -117,7 +117,7 @@ const MainScene = () => { }); return ( - + }> @@ -161,7 +161,7 @@ const MainScene = () => { - + ); }; export default MainScene; diff --git a/src/scenes/MediaScene.tsx b/src/scenes/MediaScene.tsx index d07e0fb..4a11bae 100644 --- a/src/scenes/MediaScene.tsx +++ b/src/scenes/MediaScene.tsx @@ -76,7 +76,7 @@ const MediaScene = () => { }, [setInputCooldown]); return ( - + {loaded ? ( @@ -99,7 +99,7 @@ const MediaScene = () => { ) : ( )} - + ); }; diff --git a/src/store.ts b/src/store.ts index a383be2..3532f78 100644 --- a/src/store.ts +++ b/src/store.ts @@ -7,6 +7,7 @@ import { getNodeById } from "./helpers/node-helpers"; import site_a from "./resources/site_a.json"; import { ActiveSite, + AuthorizeUserMatrixIndices, BootSceneContext, BootSubscene, EndComponent, @@ -91,7 +92,7 @@ type State = { playerName: string; activeMainMenuComponent: MainMenuComponent; - authorizeUserLetterIdx: number; + authorizeUserMatrixIndices: AuthorizeUserMatrixIndices; bootSubscene: BootSubscene; promptVisible: boolean; @@ -202,7 +203,10 @@ export const useStore = create( // boot scene activeMainMenuComponent: "authorize_user", - authorizeUserLetterIdx: 0, + authorizeUserMatrixIndices: { + rowIdx: 0, + colIdx: 0, + }, bootSubscene: "main_menu", // prompt @@ -383,7 +387,7 @@ export const getBootSceneContext = (): BootSceneContext => { playerName: state.playerName, subscene: state.bootSubscene, activeMainMenuComponent: state.activeMainMenuComponent, - authorizeUserLetterIdx: state.authorizeUserLetterIdx, + authorizeUserMatrixIndices: state.authorizeUserMatrixIndices, }; }; diff --git a/src/types/types.ts b/src/types/types.ts index ad330de..c99e495 100644 --- a/src/types/types.ts +++ b/src/types/types.ts @@ -129,11 +129,16 @@ export type MediaSceneContext = { activeSite: ActiveSite; }; +export type AuthorizeUserMatrixIndices = { + rowIdx: number; + colIdx: number; +}; + export interface BootSceneContext extends PromptContext { playerName: string; subscene: BootSubscene; activeMainMenuComponent: MainMenuComponent; - authorizeUserLetterIdx: number; + authorizeUserMatrixIndices: AuthorizeUserMatrixIndices; } export type EndSceneContext = {