From 591ed62ccda8c863e8c82cc996e5c9b9cf69c2ab Mon Sep 17 00:00:00 2001 From: sschwei1 <24sebastian05@gmail.com> Date: Mon, 24 Oct 2022 19:24:16 +0200 Subject: [PATCH] Add handling for buttons --- src/components/button/ButtonGroup.tsx | 2 + src/components/game/ControlPanel.tsx | 50 ++++++++++++++++--- src/components/game/Game.tsx | 71 +++++++++++++++++++++++---- src/styles/game.less | 12 +++++ src/styles/main.less | 3 +- 5 files changed, 122 insertions(+), 16 deletions(-) diff --git a/src/components/button/ButtonGroup.tsx b/src/components/button/ButtonGroup.tsx index bfd8e70..fb1320f 100644 --- a/src/components/button/ButtonGroup.tsx +++ b/src/components/button/ButtonGroup.tsx @@ -9,6 +9,7 @@ export interface ButtonDefinition { text: string|JSX.Element; onClick: React.MouseEventHandler; cssProps: CSSProperties; + buttonProps?: React.ButtonHTMLAttributes } const ButtonGroup = ({buttons, buttonStyleProps}: ButtonGroupProps) => { @@ -23,6 +24,7 @@ const ButtonGroup = ({buttons, buttonStyleProps}: ButtonGroupProps) => { ...buttonStyleProps, ...btn.cssProps }} + {...(btn.buttonProps ?? {})} > <>{btn.text} diff --git a/src/components/game/ControlPanel.tsx b/src/components/game/ControlPanel.tsx index aead576..c9d81d6 100644 --- a/src/components/game/ControlPanel.tsx +++ b/src/components/game/ControlPanel.tsx @@ -1,26 +1,54 @@ import {ButtonDefinition, ButtonGroup} from '../button'; -import {AiOutlineClear, BsFillPlayFill, BsFillStopFill, CiSettings, TbArrowsRandom} from 'react-icons/all'; -import React, {useMemo} from 'react'; +import { + AiOutlineClear, + BsFillPlayFill, + BsFillStopFill, + CiSettings, + IoAdd, + IoRemove, + TbArrowsRandom +} from 'react-icons/all'; +import React, {useCallback, useMemo} from 'react'; +import {GameOptions, GameState} from './Game'; interface ControlPanelProps { + gameOptions: GameOptions; handleStart: React.MouseEventHandler; handleStop: React.MouseEventHandler; handleRandomFill: React.MouseEventHandler; handleClear: React.MouseEventHandler; + handleUpdateSpeed: (newVal: number) => void; } const ControlPanel = ({ + gameOptions, handleStart, handleStop, handleRandomFill, - handleClear + handleClear, + handleUpdateSpeed }: ControlPanelProps) => { const controlButtons: ButtonDefinition[] = useMemo(() => [ - {text: , onClick: handleStart, cssProps: {}}, - {text: , onClick: handleStop, cssProps: {}}, + {text: , onClick: handleStart, cssProps: {}, buttonProps: {disabled: gameOptions.gameState === GameState.Running}}, + {text: , onClick: handleStop, cssProps: {}, buttonProps: {disabled: gameOptions.gameState === GameState.Stopped}}, {text: , onClick: handleRandomFill, cssProps: {}}, {text: , onClick: handleClear, cssProps: {}} - ], [handleStart, handleStop, handleRandomFill, handleClear]); + ], [handleStart, handleStop, handleRandomFill, handleClear, gameOptions]); + + const handleSpeedChange = useCallback((event: React.ChangeEvent) => { + const value = event.target.value; + handleUpdateSpeed(Number(value)); + }, [handleUpdateSpeed]); + + const handleSpeedUp = useCallback((event: React.MouseEvent) => { + const newVal = gameOptions.speed + 100; + handleUpdateSpeed(newVal); + }, [handleUpdateSpeed, gameOptions]); + + const handleSpeedDown = useCallback((event: React.MouseEvent) => { + const newVal = gameOptions.speed - 100; + handleUpdateSpeed(newVal); + }, [handleUpdateSpeed, gameOptions]); return (
@@ -30,6 +58,16 @@ const ControlPanel = ({ width: '50px' }} /> + +
+ + + +
+
); diff --git a/src/components/game/Game.tsx b/src/components/game/Game.tsx index 4e2b48f..9d682ba 100644 --- a/src/components/game/Game.tsx +++ b/src/components/game/Game.tsx @@ -8,30 +8,66 @@ interface GameProps { } -interface GameOptions { +export enum GameState { + Stopped, + Running +} + +export interface GameOptions { + gameState: GameState; width: number; height: number; + speed: number; + minSpeed: number; } const defaultGameOptions: GameOptions = { + gameState: GameState.Stopped, width: 25, - height: 25 + height: 25, + speed: 1000, + minSpeed: 100 } const Game = ({}: GameProps) => { const [gameOptions, setGameOptions] = useState(defaultGameOptions); const [cells, setCells] = useState([]); - useEffect(() => { + const handleStart = useCallback(() => { + setGameOptions(prev => { + prev.gameState = GameState.Running; + return {...prev}; + }); + }, []); + + const handleStop = useCallback(() => { + setGameOptions(prev => { + prev.gameState = GameState.Stopped; + return {...prev}; + }); + }, []); + + const handleRandomFill = useCallback(() => { const newCells: boolean[] = []; const totalCells = gameOptions.width * gameOptions.height; for(let i = 0; i < totalCells; i++) { - newCells.push(false); + newCells.push(Math.random() < 0.5); } setCells(newCells); - }, [gameOptions]); + }, []); + + const handleClear = useCallback(() => { + const newCells: boolean[] = []; + const totalCells = gameOptions.width * gameOptions.height; + + for(let i = 0; i < totalCells; i++) { + newCells.push(false); + } + + setCells(newCells); + }, []); const handleCellUpdate = useCallback((newVal: boolean, position: number) => { setCells(prev => { @@ -40,13 +76,30 @@ const Game = ({}: GameProps) => { }); }, []); + const handleUpdateSpeed = useCallback((newVal: number) => { + if(newVal < gameOptions.minSpeed) { + newVal = gameOptions.minSpeed; + } + + setGameOptions(prev => { + prev.speed = newVal; + return {...prev}; + }) + }, [gameOptions]); + + useEffect(() => { + handleClear(); + }, [handleClear]); + return (
{}} - handleStop={() => {}} - handleRandomFill={() => {}} - handleClear={() => {}} + gameOptions={gameOptions} + handleStart={handleStart} + handleStop={handleStop} + handleRandomFill={handleRandomFill} + handleClear={handleClear} + handleUpdateSpeed={handleUpdateSpeed} />