diff --git a/packages/client/package.json b/packages/client/package.json index 808f345..f40f0e7 100644 --- a/packages/client/package.json +++ b/packages/client/package.json @@ -26,7 +26,8 @@ "react-three-fiber": "^5.2.1", "three": "^0.122.0", "typescript": "^4.0.5", - "web-vitals": "^0.2.4" + "web-vitals": "^0.2.4", + "zustand": "^3.1.4" }, "scripts": { "start": "cross-env PORT=4000 CI=true react-scripts start", diff --git a/packages/client/src/3d/Controls.tsx b/packages/client/src/3d/Controls.tsx new file mode 100644 index 0000000..dda034d --- /dev/null +++ b/packages/client/src/3d/Controls.tsx @@ -0,0 +1,30 @@ +import React, { useEffect, useRef } from 'react' +import { PointerLockControls } from '@react-three/drei' + +import api from '../Store' + +const Controls: React.FC = () => { + const ref = useRef(null) + const setPointerLockControls = api.getState().setPointerLockControls + const setPointerLockStatus = api.getState().setPointerLockStatus + + useEffect(() => { + if (ref.current) { + setPointerLockControls(ref.current) + + const onLock = () => setPointerLockStatus(true) + const onUnlock = () => setPointerLockStatus(false) + + ref.current.addEventListener?.('lock', onLock) + ref.current.addEventListener?.('unlock', onUnlock) + return () => { + ref.current?.removeEventListener?.('lock', onLock) + ref.current?.removeEventListener?.('unlock', onUnlock) + } + } + }, [ref, ref.current]) + + return +} + +export default Controls diff --git a/packages/client/src/3d/Player.tsx b/packages/client/src/3d/Player.tsx index edf5a7c..b9fb77e 100644 --- a/packages/client/src/3d/Player.tsx +++ b/packages/client/src/3d/Player.tsx @@ -29,7 +29,6 @@ const usePlayerControls = () => { }) useEffect(() => { const handleKeyDown = (e: Event) => { - console.log(e.code) setMovement((m) => ({ ...m, [moveFieldByKey(e.code)]: true })) } const handleKeyUp = (e: Event) => diff --git a/packages/client/src/3d/index.tsx b/packages/client/src/3d/index.tsx index 0b394ac..e1938ca 100644 --- a/packages/client/src/3d/index.tsx +++ b/packages/client/src/3d/index.tsx @@ -1,12 +1,12 @@ import React, { Suspense } from 'react' import { Physics } from '@react-three/cannon' -import { PointerLockControls } from '@react-three/drei' import World from './models/World' import WorldCollisions from './models/WorldCollisions' import Player from './Player' import Lighting from './Lighting' import Effects from './Effects' +import Controls from './Controls' const Scene: React.FC = () => { return ( @@ -30,7 +30,7 @@ const Scene: React.FC = () => { - + ) } diff --git a/packages/client/src/Store.ts b/packages/client/src/Store.ts new file mode 100644 index 0000000..02ebad1 --- /dev/null +++ b/packages/client/src/Store.ts @@ -0,0 +1,18 @@ +import create from 'zustand' +import { PointerLockControls } from '@react-three/drei' + +type State = { + pointerLockControls: PointerLockControls | undefined + pointerLocked: boolean + setPointerLockStatus: (status: boolean) => void + setPointerLockControls: (controls: PointerLockControls) => void +} + +const useStore = create((set) => ({ + pointerLockControls: undefined, + pointerLocked: false, + setPointerLockStatus: (status) => set(() => ({ pointerLocked: status })), + setPointerLockControls: (controls) => set(() => ({ pointerLockControls: controls })), +})) + +export default useStore diff --git a/packages/client/src/components/MenuOverlay.tsx b/packages/client/src/components/MenuOverlay.tsx new file mode 100644 index 0000000..efabd63 --- /dev/null +++ b/packages/client/src/components/MenuOverlay.tsx @@ -0,0 +1,60 @@ +import React, { useEffect, useState } from 'react' +import { + Modal, + ModalOverlay, + ModalContent, + ModalHeader, + ModalFooter, + ModalBody, + Button, + Kbd, + useToast, +} from '@chakra-ui/react' + +import useStore from '../Store' + +const MenuOverlay: React.FC = () => { + const [helpToastShown, setHelpToastShown] = useState(false) + const pointerLockControls = useStore((state) => state.pointerLockControls) + const pointerLocked = useStore((state) => state.pointerLocked) + const toast = useToast() + + useEffect(() => { + if (!helpToastShown && pointerLocked) { + toast({ + description: 'Para volver al menú, pulsá ESC', + duration: 5000, + isClosable: false, + }) + setHelpToastShown(true) + } + }, [pointerLocked, helpToastShown]) + + const lockControls = () => { + if (pointerLockControls && !pointerLocked) { + pointerLockControls.lock?.() + } + } + + return ( + <> + undefined}> + + + museo.red + + Usa las teclas W, A S y D para + moverte. Usá el mouse para mirar al rededor + + + + + + + + ) +} + +export default MenuOverlay diff --git a/packages/client/src/components/Museo.tsx b/packages/client/src/components/Museo.tsx index 4fc1daf..6765532 100644 --- a/packages/client/src/components/Museo.tsx +++ b/packages/client/src/components/Museo.tsx @@ -3,11 +3,13 @@ import React from 'react' import { Box } from '@chakra-ui/react' import { Canvas } from 'react-three-fiber' +import MenuOverlay from './MenuOverlay' import Scene from '../3d' const Museo: React.FC = () => { return ( +