diff --git a/packages/client/src/assets/images/sprites/bullet.png b/packages/client/src/assets/images/sprites/bullet.png new file mode 100644 index 0000000..d2a21d5 Binary files /dev/null and b/packages/client/src/assets/images/sprites/bullet.png differ diff --git a/packages/client/src/assets/images/win-screen.png b/packages/client/src/assets/images/win-screen.png new file mode 100644 index 0000000..bf99438 Binary files /dev/null and b/packages/client/src/assets/images/win-screen.png differ diff --git a/packages/client/src/components/Game/Game.scss b/packages/client/src/components/Game/Game.scss index 2da9d4d..da84990 100644 --- a/packages/client/src/components/Game/Game.scss +++ b/packages/client/src/components/Game/Game.scss @@ -14,8 +14,6 @@ $img_default-canvas-background: '@/assets/images/ground.png'; } canvas { - border-radius: $border-radius--default; - box-shadow: 0 4px 8px rgba($c_black, 0.5); background-image: url($img_default-canvas-background); background-repeat: repeat; } diff --git a/packages/client/src/components/Game/Game.tsx b/packages/client/src/components/Game/Game.tsx index abedf67..00eacc8 100644 --- a/packages/client/src/components/Game/Game.tsx +++ b/packages/client/src/components/Game/Game.tsx @@ -1,4 +1,4 @@ -import React, { useCallback, useEffect, useRef, useState } from 'react' +import { useCallback, useEffect, useRef, useState } from 'react' import './Game.scss' import { initializeCampanyEnemies, @@ -6,43 +6,66 @@ import { } from '@/components/Game/enemy' import { PLAYER_DEFAULT_PARAMS } from '@/components/Game/player' import { gameLoop } from '@/components/Game/gameLoop' -import { handleKeyDown, handleKeyUp } from '@/components/Game/controls' -import { AbstractEntity, Effect, Obstacle } from '@/components/Game/gameTypes' +import { + AbstractEntity, + Effect, + Obstacle, + BtnStates, +} from '@/components/Game/gameTypes' import { initializeCompanyMapObstacle, initializeRandomObstacle, } from '@/components/Game/obstacle' -import { Modal } from '../common/Modal/Modal' +import { handleKeyDownUp, resetButtonsStates } from '@/components/Game/controls' + +type GamePropsType = { + lives: number + isGameStarted: boolean + isCompanyStarted: boolean + isGamePaused: boolean + onDeath: (lives: number) => void + onGameOver: (isVictory: boolean) => void + onKeyDownUp: (btnStates: BtnStates) => void +} -const livesUse = 3 +export const Game = (props: GamePropsType) => { + const { + lives, + isGameStarted, + isCompanyStarted, + isGamePaused, + onDeath, + onGameOver, + onKeyDownUp, + } = props + + // TODO: Нужно обработать победу в игре -export const Game: React.FC = () => { const canvasRef = useRef(null) const playerRef = useRef(PLAYER_DEFAULT_PARAMS) const enemiesRef = useRef(initializeRandomEnemies(5)) const bulletsRef = useRef([]) const obstaclesRef = useRef(initializeRandomObstacle(20)) const effectsRef = useRef([]) - const livesRef = useRef(livesUse) - const [gameStarted, setGameStarted] = useState(false) - const [isPaused, setIsPaused] = useState(false) + const livesRef = useRef(lives) const isPausedRef = useRef(false) - const [isGameOver, setIsGameOver] = useState(false) + const isStartedLoopRef = useRef(false) - const togglePause = useCallback(() => { - setIsPaused(prev => !prev) - isPausedRef.current = !isPausedRef.current // Обновляем ref для паузы - }, []) + const [isGameRunning, setIsGameRunning] = useState(false) + const [isGameOver, setIsGameOver] = useState(false) const handleGameOver = useCallback(() => { + onGameOver(false) setIsGameOver(true) - setIsPaused(true) + setIsGameRunning(false) + isPausedRef.current = true - }, []) + }, [onGameOver]) const loop = useCallback(() => { if (!isPausedRef.current && !isGameOver && canvasRef.current) { const context = canvasRef.current.getContext('2d') + if (context) { gameLoop( context, @@ -53,76 +76,87 @@ export const Game: React.FC = () => { obstaclesRef, effectsRef, livesRef, + onDeath, handleGameOver ) } + requestAnimationFrame(loop) } - }, [isGameOver, handleGameOver, livesRef]) + }, [isGameOver, onDeath, handleGameOver]) + + const startGame = useCallback(() => { + setIsGameRunning(true) + setIsGameOver(false) + + isPausedRef.current = false + livesRef.current = lives + playerRef.current = PLAYER_DEFAULT_PARAMS + enemiesRef.current = initializeRandomEnemies(5) + obstaclesRef.current = initializeRandomObstacle(20) + isStartedLoopRef.current = false + }, [lives]) + + const startCompany = useCallback(() => { + setIsGameRunning(true) + setIsGameOver(false) + + isPausedRef.current = false + livesRef.current = lives + playerRef.current = PLAYER_DEFAULT_PARAMS + enemiesRef.current = initializeCampanyEnemies() + obstaclesRef.current = initializeCompanyMapObstacle() + isStartedLoopRef.current = false + }, [lives]) useEffect(() => { - const handleKeyDownWrapper = (event: KeyboardEvent) => - handleKeyDown(event.key) - const handleKeyUpWrapper = (event: KeyboardEvent) => handleKeyUp(event.key) + const handleKeyDownUpWrapper = (event: KeyboardEvent) => { + handleKeyDownUp(event.type, event.key, onKeyDownUp) + } - window.addEventListener('keydown', handleKeyDownWrapper) - window.addEventListener('keyup', handleKeyUpWrapper) + window.addEventListener('keydown', handleKeyDownUpWrapper) + window.addEventListener('keyup', handleKeyDownUpWrapper) + window.addEventListener('blur', resetButtonsStates) return () => { - window.removeEventListener('keydown', handleKeyDownWrapper) - window.removeEventListener('keyup', handleKeyUpWrapper) + window.removeEventListener('keydown', handleKeyDownUpWrapper) + window.removeEventListener('keyup', handleKeyDownUpWrapper) + window.removeEventListener('blur', resetButtonsStates) } - }, []) + }, [onKeyDownUp]) useEffect(() => { - if (gameStarted && !isPaused) { + if (isGameRunning && !isGamePaused && !isStartedLoopRef.current) { + isStartedLoopRef.current = true + requestAnimationFrame(loop) } - }, [gameStarted, isPaused, loop]) + }, [isGameRunning, isGamePaused, loop]) - const startGame = () => { - setGameStarted(true) - setIsPaused(false) - isPausedRef.current = false - setIsGameOver(false) - livesRef.current = livesUse - playerRef.current = { ...PLAYER_DEFAULT_PARAMS } - enemiesRef.current = initializeRandomEnemies(5) - obstaclesRef.current = initializeRandomObstacle(20) - } + useEffect(() => { + livesRef.current = lives + isPausedRef.current = isGamePaused - const startCompany = () => { - setGameStarted(true) - setIsPaused(false) - isPausedRef.current = false - setIsGameOver(false) - livesRef.current = livesUse - playerRef.current = { ...PLAYER_DEFAULT_PARAMS } - enemiesRef.current = initializeCampanyEnemies() - obstaclesRef.current = initializeCompanyMapObstacle() - } - - return ( -
-
{`Жизни: ${livesRef.current.toString()}`}
- - - {!gameStarted ? ( - <> - - - - ) : ( - - )} - - setIsGameOver(false)}> -

Игра окончена

- - -
-
- ) + if (!isGamePaused) { + isStartedLoopRef.current = false + } + + if (isGameRunning === false) { + if (isGameStarted) { + startGame() + } else if (isCompanyStarted) { + startCompany() + } + } + }, [ + lives, + isGameStarted, + isGamePaused, + isGameRunning, + startGame, + isCompanyStarted, + startCompany, + ]) + + return } diff --git a/packages/client/src/components/Game/controls.tsx b/packages/client/src/components/Game/controls.tsx index 1a1945f..9e86443 100644 --- a/packages/client/src/components/Game/controls.tsx +++ b/packages/client/src/components/Game/controls.tsx @@ -1,7 +1,14 @@ -import { ControlsProps } from '@/components/Game/gameTypes' +import { BtnStates, ControlsProps } from '@/components/Game/gameTypes' import { detectCollision } from '@/components/Game/collision' import { createBullet } from '@/components/Game/bullet' +const btnStates: BtnStates = { + up: false, + down: false, + left: false, + right: false, + fire: false, +} let pressedKeys: string[] = [] let shootPressed = false // Флаг для стрельбы let lastShotTime = 0 // Время последнего выстрела @@ -36,24 +43,47 @@ const VECTORS: Record = { [Action.Shoot]: { x: 0, y: 0 }, } -export const handleKeyDown = (key: string) => { - if (!pressedKeys.includes(key)) { - pressedKeys.push(key) - } +const checkPressedKeys = (keys: string[]): BtnStates => { + keys.forEach((key: string) => { + btnStates.up = ACTION_CONTROLS[Action.MoveUp].includes(key) + btnStates.down = ACTION_CONTROLS[Action.MoveDown].includes(key) + btnStates.left = ACTION_CONTROLS[Action.MoveLeft].includes(key) + btnStates.right = ACTION_CONTROLS[Action.MoveRight].includes(key) + btnStates.fire = ACTION_CONTROLS[Action.Shoot].includes(key) + }) - // Устанавливаем флаг, если нажата клавиша пробела (стрельба) - if (key === ' ') { - shootPressed = true - } + return btnStates } -export const handleKeyUp = (key: string) => { - pressedKeys = pressedKeys.filter(currentKey => currentKey !== key) +export const handleKeyDownUp = ( + type: string, + key: string, + onKeyDownUp: (state: BtnStates) => void +) => { + const isKeydown = type === 'keydown' + + if (isKeydown) { + if (!pressedKeys.includes(key)) { + pressedKeys.push(key) + + if (key === ' ') { + shootPressed = true + } + } + } else { + pressedKeys = pressedKeys.filter(currentKey => currentKey !== key) - // Сбрасываем флаг, если клавиша пробела отпущена - if (key === ' ') { - shootPressed = false + if (key === ' ') { + shootPressed = false + } } + + onKeyDownUp(checkPressedKeys(pressedKeys)) +} + +export const resetButtonsStates = () => { + pressedKeys = [] + shootPressed = false } const getActionControlByKey = (key: string): Action | null => { diff --git a/packages/client/src/components/Game/enemy.tsx b/packages/client/src/components/Game/enemy.tsx index 7c8a3fc..6c2bec0 100644 --- a/packages/client/src/components/Game/enemy.tsx +++ b/packages/client/src/components/Game/enemy.tsx @@ -1,3 +1,4 @@ +import React from 'react' import { getRandomEdgePosition } from './utils' import { AbstractEntity, Enemy, Obstacle } from '@/components/Game/gameTypes' import { createBullet } from '@/components/Game/bullet' diff --git a/packages/client/src/components/Game/gameLoop.tsx b/packages/client/src/components/Game/gameLoop.tsx index e1c8833..88fe83f 100644 --- a/packages/client/src/components/Game/gameLoop.tsx +++ b/packages/client/src/components/Game/gameLoop.tsx @@ -44,6 +44,7 @@ export const gameLoop = ( obstaclesRef: React.MutableRefObject, effectsRef: React.MutableRefObject, livesRef: React.MutableRefObject, + handleDeath: (lives: number) => void, handleGameOver: () => void ) => { clearCanvas(context) @@ -112,6 +113,8 @@ export const gameLoop = ( // Проверка на окончание игры if (livesRef.current <= 0) { handleGameOver() + } else { + handleDeath(livesRef.current) } } }) @@ -121,6 +124,13 @@ export const gameLoop = ( ) if (collidedEnemy) { - HandlePlayerHit(livesRef, playerRef, enemiesRef, canvasRef, handleGameOver) + HandlePlayerHit( + livesRef, + playerRef, + enemiesRef, + canvasRef, + handleGameOver, + handleDeath + ) } } diff --git a/packages/client/src/components/Game/gameTypes.tsx b/packages/client/src/components/Game/gameTypes.tsx index b28238a..d313fea 100644 --- a/packages/client/src/components/Game/gameTypes.tsx +++ b/packages/client/src/components/Game/gameTypes.tsx @@ -46,6 +46,15 @@ export interface Effect { animation: AnimationParams } +export interface BtnStates { + [key: string]: boolean + up: boolean + down: boolean + left: boolean + right: boolean + fire: boolean +} + export interface ControlsProps { playerRef: React.MutableRefObject bulletsRef: React.MutableRefObject diff --git a/packages/client/src/components/Game/player.tsx b/packages/client/src/components/Game/player.tsx index c432ff7..057eb5e 100644 --- a/packages/client/src/components/Game/player.tsx +++ b/packages/client/src/components/Game/player.tsx @@ -38,14 +38,14 @@ export const HandlePlayerHit = ( playerRef: React.MutableRefObject, enemiesRef: React.MutableRefObject, canvasRef: React.MutableRefObject, - handleGameOver: () => void + handleGameOver: () => void, + handleDeath: (lives: number) => void ) => { livesRef.current -= 1 if (livesRef.current <= 0) { handleGameOver() } else { - resetPlayerPosition(playerRef) - respawnEnemies(enemiesRef, canvasRef) + handleDeath(livesRef.current) } } diff --git a/packages/client/src/components/common/Modal/Modal.tsx b/packages/client/src/components/common/Modal/Modal.tsx index 0f9db62..de42403 100644 --- a/packages/client/src/components/common/Modal/Modal.tsx +++ b/packages/client/src/components/common/Modal/Modal.tsx @@ -17,9 +17,9 @@ export const Modal = (props: ModalPropsType) => { useEffect(() => { const handleEscape = (event: KeyboardEvent) => { - event.preventDefault() + if (event.key === 'Escape' && show) { + event.preventDefault() - if (event.key === 'Escape') { onClose() } } @@ -29,7 +29,7 @@ export const Modal = (props: ModalPropsType) => { return () => { document.removeEventListener('keydown', handleEscape) } - }, [onClose]) + }, [onClose, show]) return ReactDOM.createPortal(
diff --git a/packages/client/src/layouts/PrivateLayout/PrivateLayout.tsx b/packages/client/src/layouts/PrivateLayout/PrivateLayout.tsx index 63aa846..c4cbe46 100644 --- a/packages/client/src/layouts/PrivateLayout/PrivateLayout.tsx +++ b/packages/client/src/layouts/PrivateLayout/PrivateLayout.tsx @@ -1,16 +1,53 @@ +import './PrivateLayout.scss' import { Header } from '@/components/common/Header/Header' -import { Outlet } from 'react-router-dom' +import { Loader } from '@/components/ui/Loader/Loader' +import { RootState, useAppDispatch } from '@/store' +import { actions, getUser, UserType } from '@/store/reducers/auth-reducer' +import { useEffect } from 'react' +import { useSelector } from 'react-redux' +import { Outlet, useNavigate } from 'react-router-dom' +import { toast } from 'react-toastify' import withAuthUser from '@/components/hoc/withAuthUser' import './PrivateLayout.scss' -const PrivateLayout = () => { - return ( -
-
-
- -
-
- ) +export function PrivateLayout() { + const user = useSelector(state => state.authReducer.user) + const navigate = useNavigate() + const userIsLogged = window.sessionStorage.getItem('userIsLogged') === '1' + const dispatch = useAppDispatch() + + useEffect(() => { + if (!userIsLogged) { + dispatch(getUser()) + .unwrap() + .then(data => { + dispatch(actions.setUser(data)) + window.sessionStorage.setItem('userIsLogged', '1') // 0 + }) + .catch(() => { + window.sessionStorage.setItem('userIsLogged', '0') // 0 + + toast.error('Необходимо авторизоваться', { + autoClose: 1500, + onClose: () => { + navigate('/sign-in') + }, + }) + }) + } + }, [dispatch, navigate, userIsLogged]) + + if (userIsLogged) { + return ( +
+
+
+ +
+
+ ) + } + return user === null ? : } + export default withAuthUser(PrivateLayout) diff --git a/packages/client/src/pages/Game/Game.scss b/packages/client/src/pages/Game/Game.scss index 74732fb..8ce909d 100644 --- a/packages/client/src/pages/Game/Game.scss +++ b/packages/client/src/pages/Game/Game.scss @@ -18,7 +18,7 @@ $border-color: #70842f; .game-wrapper { position: relative; - width: 800px; + width: 832px; height: auto; background-color: $c_black; border-radius: 8px; @@ -142,35 +142,3 @@ $border-color: #70842f; margin-right: auto; } } - -.start-screen { - display: flex; - align-items: center; - justify-content: center; - position: absolute; - inset: 12px; - background-color: $overlay-color; - - &_hide { - display: none; - } -} - -.game-over-screen { - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - position: absolute; - inset: 12px; - background-color: $overlay-color; - background-image: url('@/assets/images/game-over.png'); - background-size: cover; - - &__title { - font-size: 40px; - font-weight: 900; - text-transform: uppercase; - margin-bottom: 16px; - } -} diff --git a/packages/client/src/pages/Game/Game.tsx b/packages/client/src/pages/Game/Game.tsx index 1fc7b0e..a46ef03 100644 --- a/packages/client/src/pages/Game/Game.tsx +++ b/packages/client/src/pages/Game/Game.tsx @@ -1,78 +1,143 @@ import GameInfo from '@/assets/images/game-info.jpg' import { Modal } from '@/components/common/Modal/Modal' import { Game as GamePrototype } from '@/components/Game/Game' -import { Button } from '@/components/ui/Button/Button' import { CustomPageTitle } from '@/components/ui/CustomPageTitle/CustomPageTitle' -import { useEffect, useState } from 'react' +import { useCallback, useEffect, useState } from 'react' import { Arrows } from './components/Arrows/Arrows' import { FireControll } from './components/FireControll/FireControll' import { KillsCounter } from './components/KillsCounter/KillsCounter' import { PauseHelpFullscreen } from './components/PauseHelp/PauseHelpFullscreen' import './Game.scss' +import { Icon } from '@/components/ui/Icon/Icon' +import { BtnStates } from '@/components/Game/gameTypes' +import { StatusScreen } from './components/StatusScreen/StatusScreen' +import { Button } from '@/components/ui/Button/Button' + +interface GameState { + lives: number + isGameStarted: boolean + isCompanyStarted: boolean + isGamePaused: boolean + isGameOver: boolean + isGameWinning: boolean +} + +const DEFAULT_LIVES_COUNT = 3 export const Game = () => { const [isInfoModalOpen, setIsInfoModalOpen] = useState(false) - const [buttonsState, setButtonsState] = useState({ - upButton: false, - downButton: false, - leftButton: false, - rightButton: false, - fireButton: false, + const [buttonsState, setButtonsState] = useState({ + up: false, + down: false, + left: false, + right: false, + fire: false, + }) + const [gameState, setGameState] = useState({ + lives: DEFAULT_LIVES_COUNT, + isGameStarted: false, + isCompanyStarted: false, + isGamePaused: false, + isGameOver: false, + isGameWinning: false, }) - const [isStartedGame, setIsStartedGame] = useState(false) - const pauseHandler = () => { - console.log('pauseHandler') + const startGameHandler = () => { + setGameState({ + lives: DEFAULT_LIVES_COUNT, + isGameStarted: true, + isCompanyStarted: false, + isGamePaused: false, + isGameOver: false, + isGameWinning: false, + }) } - const helpHandler = () => { - setIsInfoModalOpen(true) + const startCompanyHandler = () => { + setGameState({ + lives: DEFAULT_LIVES_COUNT, + isGameStarted: false, + isCompanyStarted: true, + isGamePaused: false, + isGameOver: false, + isGameWinning: false, + }) } - const arrowClickHandler = () => { - return + const pauseHandler = useCallback(() => { + setGameState(state => ({ + ...state, + isGamePaused: !state.isGamePaused, + })) + }, []) + + const deathHandler = useCallback((lives: number) => { + setGameState(state => ({ + ...state, + lives, + })) + }, []) + + const gameOverHandler = useCallback((isVictory: boolean) => { + setGameState({ + lives: 0, + isGameOver: !isVictory, + isGameWinning: isVictory, + isGameStarted: false, + isCompanyStarted: false, + isGamePaused: true, + }) + }, []) + + const arrowClickHandler = ( + eventName: string, + key: string, + keyCode: number + ) => { + const event = new KeyboardEvent(eventName, { + key, + code: key, + keyCode, + which: keyCode, + bubbles: true, + cancelable: true, + }) + + window.dispatchEvent(event) } - const toggleButton = (event: Event, buttonName: string, state: boolean) => { - event.preventDefault() + const changeButtonsState = useCallback( + (state: typeof buttonsState) => { + setButtonsState({ ...state }) + }, + [setButtonsState] + ) - setButtonsState({ ...buttonsState, [buttonName]: state }) + const getPauseIcon = () => { + if ( + gameState.isGamePaused && + gameState.isGameStarted && + !gameState.isGameOver && + !gameState.isGameWinning + ) { + return + } + return } - // TODO: Заменить на финальное решение для отслеживания кнопок useEffect(() => { - const handleKey = (event: KeyboardEvent) => { - const isKeydown = event.type === 'keydown' - - switch (event.key) { - case 'ArrowUp': - toggleButton(event, 'upButton', isKeydown) - break - case 'ArrowDown': - toggleButton(event, 'downButton', isKeydown) - break - case 'ArrowLeft': - toggleButton(event, 'leftButton', isKeydown) - break - case 'ArrowRight': - toggleButton(event, 'rightButton', isKeydown) - break - case ' ': - toggleButton(event, 'fireButton', isKeydown) - break - default: - break + const escapeKeyDownHandler = (event: KeyboardEvent) => { + if (event.key === 'Escape') { + pauseHandler() } } - window.addEventListener('keydown', handleKey) - window.addEventListener('keyup', handleKey) + window.addEventListener('keydown', escapeKeyDownHandler) return () => { - window.removeEventListener('keydown', handleKey) - window.removeEventListener('keyup', handleKey) + window.removeEventListener('keydown', escapeKeyDownHandler) } - }) + }, [pauseHandler]) return (
@@ -85,22 +150,57 @@ export const Game = () => {
- -
+ + + +
-
- Game Over -
+
@@ -109,26 +209,27 @@ export const Game = () => { setIsInfoModalOpen(true)} />
diff --git a/packages/client/src/pages/Game/components/Arrows/Arrows.tsx b/packages/client/src/pages/Game/components/Arrows/Arrows.tsx index dd59aab..1e77498 100644 --- a/packages/client/src/pages/Game/components/Arrows/Arrows.tsx +++ b/packages/client/src/pages/Game/components/Arrows/Arrows.tsx @@ -5,34 +5,36 @@ import './Arrows.scss' type ArrowsPropsType = { className?: string buttonsState: { - upButton: boolean - downButton: boolean - leftButton: boolean - rightButton: boolean - fireButton: boolean + up: boolean + down: boolean + left: boolean + right: boolean + fire: boolean } - clickHandler: () => void + mouseDownUpHandler: (eventName: string, key: string, keyCode: number) => void } export const Arrows = (props: ArrowsPropsType) => { - const { className, buttonsState, clickHandler } = props + const { className, buttonsState, mouseDownUpHandler } = props return (
+ onMouseDown={mouseDownUpHandler.bind({}, 'keydown', 'ArrowLeft', 37)} + onMouseUp={mouseDownUpHandler.bind({}, 'keyup', 'ArrowLeft', 37)}> + onMouseDown={mouseDownUpHandler.bind({}, 'keydown', 'ArrowRight', 39)} + onMouseUp={mouseDownUpHandler.bind({}, 'keyup', 'ArrowRight', 39)}>
@@ -40,17 +42,19 @@ export const Arrows = (props: ArrowsPropsType) => {
+ onMouseDown={mouseDownUpHandler.bind({}, 'keydown', 'ArrowUp', 38)} + onMouseUp={mouseDownUpHandler.bind({}, 'keyup', 'ArrowUp', 38)}> + onMouseDown={mouseDownUpHandler.bind({}, 'keydown', 'ArrowDown', 40)} + onMouseUp={mouseDownUpHandler.bind({}, 'keyup', 'ArrowDown', 40)}>
diff --git a/packages/client/src/pages/Game/components/ControllBtn/ControllBtn.tsx b/packages/client/src/pages/Game/components/ControllBtn/ControllBtn.tsx index d842884..902811f 100644 --- a/packages/client/src/pages/Game/components/ControllBtn/ControllBtn.tsx +++ b/packages/client/src/pages/Game/components/ControllBtn/ControllBtn.tsx @@ -3,15 +3,17 @@ import './ControllBtn.scss' type ControllBtnPropsType = { children: React.ReactNode className?: string - onClick: () => void + onClick?: () => void + onMouseDown?: () => void + onMouseUp?: () => void } export const ControllBtn = (props: ControllBtnPropsType) => { - const { children, className, onClick } = props + const { className, ...rest } = props return ( - ) } diff --git a/packages/client/src/pages/Game/components/FireControll/FireControll.tsx b/packages/client/src/pages/Game/components/FireControll/FireControll.tsx index 48fdeb0..77e2a31 100644 --- a/packages/client/src/pages/Game/components/FireControll/FireControll.tsx +++ b/packages/client/src/pages/Game/components/FireControll/FireControll.tsx @@ -5,11 +5,11 @@ import './FireControll.scss' type FireControllPropsType = { className?: string buttonPressed: boolean - fireHandler: () => void + mouseDownUpHandler: (eventName: string, key: string, code: number) => void } export const FireControll = (props: FireControllPropsType) => { - const { fireHandler, buttonPressed, className = '' } = props + const { mouseDownUpHandler, buttonPressed, className = '' } = props return (
@@ -18,7 +18,8 @@ export const FireControll = (props: FireControllPropsType) => { className={`controll-btn_middle controll-btn_red ${ buttonPressed ? 'controll-btn_active' : '' }`} - onClick={fireHandler}> + onMouseDown={mouseDownUpHandler.bind({}, 'keydown', ' ', 32)} + onMouseUp={mouseDownUpHandler.bind({}, 'keyup', ' ', 32)}>
diff --git a/packages/client/src/pages/Game/components/PauseHelp/PauseHelpFullscreen.tsx b/packages/client/src/pages/Game/components/PauseHelp/PauseHelpFullscreen.tsx index 9d9714c..bcf8a3f 100644 --- a/packages/client/src/pages/Game/components/PauseHelp/PauseHelpFullscreen.tsx +++ b/packages/client/src/pages/Game/components/PauseHelp/PauseHelpFullscreen.tsx @@ -1,15 +1,17 @@ import { Icon } from '@/components/ui/Icon/Icon' import { ControllBtn } from '../ControllBtn/ControllBtn' import './PauseHelpFullscreen.scss' +import { ReactNode } from 'react' type PauseHelpPropsType = { className?: string + pauseIcon: ReactNode pauseHandler: () => void helpHandler: () => void } export const PauseHelpFullscreen = (props: PauseHelpPropsType) => { - const { pauseHandler, helpHandler, className = '' } = props + const { pauseHandler, helpHandler, pauseIcon, className = '' } = props const toggleFullscreen = () => { const isFullscreenMode = document.fullscreenElement @@ -33,7 +35,7 @@ export const PauseHelpFullscreen = (props: PauseHelpPropsType) => { - + {pauseIcon} { + const { isVisible, children, title = '', type = '' } = props + + return ( +
+ {title ? {title} : ''} + {children} +
+ ) +}