Showing
3 changed files
with
111 additions
and
17 deletions
| ... | @@ -3,7 +3,11 @@ import { Vector } from './types'; | ... | @@ -3,7 +3,11 @@ import { Vector } from './types'; |
| 3 | 3 | ||
| 4 | // 참고 : https://basketdeveloper.tistory.com/79 | 4 | // 참고 : https://basketdeveloper.tistory.com/79 |
| 5 | 5 | ||
| 6 | -export const Canvas: React.FC = () => { | 6 | +interface CanvasProps { |
| 7 | + isDrawer: boolean; | ||
| 8 | +} | ||
| 9 | + | ||
| 10 | +export const Canvas: React.FC<CanvasProps> = ({ isDrawer }) => { | ||
| 7 | const canvasRef = useRef<HTMLCanvasElement>(null); | 11 | const canvasRef = useRef<HTMLCanvasElement>(null); |
| 8 | 12 | ||
| 9 | const [mousePosition, setMousePosition] = useState<Vector>({ x:0, y:0 }); | 13 | const [mousePosition, setMousePosition] = useState<Vector>({ x:0, y:0 }); |
| ... | @@ -77,7 +81,7 @@ export const Canvas: React.FC = () => { | ... | @@ -77,7 +81,7 @@ export const Canvas: React.FC = () => { |
| 77 | }, []); | 81 | }, []); |
| 78 | 82 | ||
| 79 | useEffect(() => { | 83 | useEffect(() => { |
| 80 | - if (canvasRef.current) { | 84 | + if (canvasRef.current && isDrawer) { |
| 81 | const canvas: HTMLCanvasElement = canvasRef.current; | 85 | const canvas: HTMLCanvasElement = canvasRef.current; |
| 82 | 86 | ||
| 83 | canvas.addEventListener('mousedown', startPaint); | 87 | canvas.addEventListener('mousedown', startPaint); |
| ... | @@ -91,8 +95,10 @@ export const Canvas: React.FC = () => { | ... | @@ -91,8 +95,10 @@ export const Canvas: React.FC = () => { |
| 91 | canvas.removeEventListener('mouseup', exitPaint); | 95 | canvas.removeEventListener('mouseup', exitPaint); |
| 92 | canvas.removeEventListener('mouseleave', exitPaint); | 96 | canvas.removeEventListener('mouseleave', exitPaint); |
| 93 | }; | 97 | }; |
| 98 | + } else { | ||
| 99 | + // 받아서 그리기 | ||
| 94 | } | 100 | } |
| 95 | - }, [startPaint, paint, exitPaint]); | 101 | + }, [isDrawer, startPaint, paint, exitPaint]); |
| 96 | 102 | ||
| 97 | return ( | 103 | return ( |
| 98 | <div className='mx-3 px-2 py-1 rounded shadow'> | 104 | <div className='mx-3 px-2 py-1 rounded shadow'> | ... | ... |
web/src/components/room/GameBoard.tsx
0 → 100644
| 1 | +import React, { useCallback, useContext, useEffect, useState } from 'react'; | ||
| 2 | +import { useLocation } from 'react-router'; | ||
| 3 | +import SocketContext from '../../contexts/SocketContext'; | ||
| 4 | +import { MessageType, RawMessage } from '../common/types'; | ||
| 5 | +import { Canvas } from './Canvas'; | ||
| 6 | +import { Role, RoundData } from './types'; | ||
| 7 | +import { Word } from './Word'; | ||
| 8 | + | ||
| 9 | +interface GameBoardLocation { | ||
| 10 | + state: { username: string } | ||
| 11 | +} | ||
| 12 | + | ||
| 13 | +interface GameBoardProps { | ||
| 14 | + isInGame: boolean | ||
| 15 | +} | ||
| 16 | + | ||
| 17 | +export const GameBoard: React.FC<GameBoardProps> = ({ isInGame }) => { | ||
| 18 | + const socket = useContext(SocketContext); | ||
| 19 | + const location: GameBoardLocation = useLocation(); | ||
| 20 | + | ||
| 21 | + const [ isDrawer, setIsDrawer ] = useState(false); | ||
| 22 | + const [ words, setWords ] = useState<string[]>([]); | ||
| 23 | + const [ wordChosen, setWordChosen ] = useState(''); | ||
| 24 | + | ||
| 25 | + const handleWordSet = useCallback((rawMessage: RawMessage) => { | ||
| 26 | + if (rawMessage.type === MessageType.GAME_WORDSET) { | ||
| 27 | + console.log('단어 도착'); | ||
| 28 | + const { words } = rawMessage.message as { words: string[] }; | ||
| 29 | + setWords(words); | ||
| 30 | + } | ||
| 31 | + }, []); | ||
| 32 | + | ||
| 33 | + const handleStart = useCallback((rawMessage: RawMessage) => { | ||
| 34 | + if (rawMessage.type === MessageType.GAME_START) { | ||
| 35 | + setWords([]); | ||
| 36 | + | ||
| 37 | + const data = rawMessage.message as RoundData; | ||
| 38 | + console.log('테스트 location ', location.state.username); | ||
| 39 | + console.log('테스트 rolse ', data.roles); | ||
| 40 | + const index = data.roles.findIndex(x => x.username === location.state.username); | ||
| 41 | + setIsDrawer(data.roles[index].role === 'drawer'); | ||
| 42 | + setWordChosen(''); | ||
| 43 | + } | ||
| 44 | + }, []); | ||
| 45 | + | ||
| 46 | + const handleGetWordLength = useCallback((rawMessage: RawMessage) => { | ||
| 47 | + if (rawMessage.type === MessageType.GAME_WORD) { | ||
| 48 | + if (wordChosen !== '') { | ||
| 49 | + const { length } = rawMessage.message as { length: number }; | ||
| 50 | + setWordChosen('_'.repeat(length)); | ||
| 51 | + } | ||
| 52 | + } | ||
| 53 | + }, [wordChosen]); | ||
| 54 | + | ||
| 55 | + useEffect(() => { | ||
| 56 | + socket.on('msg', handleStart); | ||
| 57 | + socket.on('msg', handleGetWordLength); | ||
| 58 | + socket.on('msg', handleWordSet); | ||
| 59 | + | ||
| 60 | + return () => { | ||
| 61 | + socket.off('msg', handleStart); | ||
| 62 | + socket.off('msg', handleGetWordLength); | ||
| 63 | + socket.off('msg', handleWordSet); | ||
| 64 | + } | ||
| 65 | + }, []); | ||
| 66 | + | ||
| 67 | + return ( | ||
| 68 | + <div className={`w-auto ${isInGame ? '' : 'hidden'}`}> | ||
| 69 | + <div className='w-full flex flex-col justify-center items-center'> | ||
| 70 | + {words.map((word, i) => (<Word key={word} index={i} word={word} setWordChosen={setWordChosen} setWords={setWords} />))} | ||
| 71 | + </div> | ||
| 72 | + <Canvas isDrawer={isDrawer && wordChosen !== ''}/> | ||
| 73 | + </div> | ||
| 74 | + ); | ||
| 75 | +} | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file |
| ... | @@ -4,6 +4,7 @@ import { Main } from '../components/common/Main'; | ... | @@ -4,6 +4,7 @@ import { Main } from '../components/common/Main'; |
| 4 | import { MessageResponse, MessageType, RawMessage } from '../components/common/types'; | 4 | import { MessageResponse, MessageType, RawMessage } from '../components/common/types'; |
| 5 | import { Canvas } from '../components/room/Canvas'; | 5 | import { Canvas } from '../components/room/Canvas'; |
| 6 | import { Chat } from '../components/room/Chat'; | 6 | import { Chat } from '../components/room/Chat'; |
| 7 | +import { GameBoard } from '../components/room/GameBoard'; | ||
| 7 | import { Ready } from '../components/room/Ready'; | 8 | import { Ready } from '../components/room/Ready'; |
| 8 | import { RoomInfo } from '../components/room/RoomInfo'; | 9 | import { RoomInfo } from '../components/room/RoomInfo'; |
| 9 | import { RoomData, UpdateRoomUser } from '../components/room/types'; | 10 | import { RoomData, UpdateRoomUser } from '../components/room/types'; |
| ... | @@ -29,6 +30,14 @@ export const Room: React.FC = () => { | ... | @@ -29,6 +30,14 @@ export const Room: React.FC = () => { |
| 29 | }); | 30 | }); |
| 30 | const [ isInGame, setIsInGame ] = useState(false); | 31 | const [ isInGame, setIsInGame ] = useState(false); |
| 31 | 32 | ||
| 33 | + const handleInGame = useCallback((rawMessage: RawMessage) => { | ||
| 34 | + if (rawMessage.type === MessageType.GAME_START) { | ||
| 35 | + setIsInGame(true); | ||
| 36 | + } else if (rawMessage.type === MessageType.GAME_FINISH_GAME) { | ||
| 37 | + setIsInGame(false); | ||
| 38 | + } | ||
| 39 | + }, []); | ||
| 40 | + | ||
| 32 | const handleUpdateRoomUser = useCallback((rawMessage: RawMessage) => { | 41 | const handleUpdateRoomUser = useCallback((rawMessage: RawMessage) => { |
| 33 | if (rawMessage.type == MessageType.ROOM_USER_UPDATE) { | 42 | if (rawMessage.type == MessageType.ROOM_USER_UPDATE) { |
| 34 | const data = rawMessage.message as UpdateRoomUser; | 43 | const data = rawMessage.message as UpdateRoomUser; |
| ... | @@ -81,8 +90,11 @@ export const Room: React.FC = () => { | ... | @@ -81,8 +90,11 @@ export const Room: React.FC = () => { |
| 81 | } | 90 | } |
| 82 | 91 | ||
| 83 | setRoomData(location.state.roomData); | 92 | setRoomData(location.state.roomData); |
| 93 | + socket.on('msg', handleInGame); | ||
| 84 | 94 | ||
| 85 | return () => { | 95 | return () => { |
| 96 | + socket.off('msg', handleInGame); | ||
| 97 | + | ||
| 86 | const rawMessage: RawMessage = { | 98 | const rawMessage: RawMessage = { |
| 87 | type: MessageType.ROOM_LEAVE, | 99 | type: MessageType.ROOM_LEAVE, |
| 88 | message: '' | 100 | message: '' |
| ... | @@ -94,20 +106,21 @@ export const Room: React.FC = () => { | ... | @@ -94,20 +106,21 @@ export const Room: React.FC = () => { |
| 94 | return ( | 106 | return ( |
| 95 | <Main> | 107 | <Main> |
| 96 | <RoomInfo roomData={roomData}/> | 108 | <RoomInfo roomData={roomData}/> |
| 97 | - { | 109 | + <div className='w-full flex'> |
| 98 | - isInGame ? ( | 110 | + {/* 게임보드를 계속 살려둬서 리스너를 항상 열어놓도록 하자 */} |
| 99 | - <div className='w-full flex'> | 111 | + <GameBoard isInGame={isInGame} /> |
| 100 | - <Canvas /> | 112 | + { |
| 101 | - <Chat w='w-4/12' h='h-80' /> | 113 | + isInGame ? ( |
| 102 | - </div> | 114 | + <Chat w='w-4/12' h='h-80' /> |
| 103 | - ) : ( | 115 | + ) : ( |
| 104 | - <div className='w-full flex flex-col justify-center items-center'> | 116 | + <div className='w-full flex flex-col justify-center items-center'> |
| 105 | - <UserInfo users={roomData.users}/> | 117 | + <UserInfo users={roomData.users}/> |
| 106 | - <Ready users={roomData.users} /> | 118 | + <Ready users={roomData.users} /> |
| 107 | - <Chat w='w-7/12' h='h-96' /> | 119 | + <Chat w='w-7/12' h='h-96' /> |
| 108 | - </div> | 120 | + </div> |
| 109 | - ) | 121 | + ) |
| 110 | - } | 122 | + } |
| 123 | + </div> | ||
| 111 | </Main> | 124 | </Main> |
| 112 | ); | 125 | ); |
| 113 | } | 126 | } |
| ... | \ No newline at end of file | ... | \ No newline at end of file | ... | ... |
-
Please register or login to post a comment