diff --git a/pac-man-board-game/ClientApp/src/components/Button.tsx b/pac-man-board-game/ClientApp/src/components/Button.tsx new file mode 100644 index 0000000..6d3be9b --- /dev/null +++ b/pac-man-board-game/ClientApp/src/components/Button.tsx @@ -0,0 +1,26 @@ +import React from "react"; + +export const Button: Component = ( + { + className, + onClick, + style, + title, + id, + disabled = false, + children, + type = "button", + }) => { + return ( + + ) +} \ No newline at end of file diff --git a/pac-man-board-game/ClientApp/src/components/dice.tsx b/pac-man-board-game/ClientApp/src/components/dice.tsx index d1bb212..f37a015 100644 --- a/pac-man-board-game/ClientApp/src/components/dice.tsx +++ b/pac-man-board-game/ClientApp/src/components/dice.tsx @@ -1,6 +1,7 @@ import React from "react"; -import {useAtom} from "jotai"; -import {selectedDiceAtom} from "../utils/state"; +import {useAtom, useAtomValue} from "jotai"; +import {selectedDiceAtom, thisPlayerAtom} from "../utils/state"; +import {Button} from "./Button"; interface AllDiceProps extends ComponentProps { values?: number[], @@ -41,6 +42,8 @@ export const Dice: Component = ( onClick, }) => { + const thisPlayer = useAtomValue(thisPlayerAtom); + function handleClick() { if (onClick && value) { onClick(value); @@ -48,8 +51,10 @@ export const Dice: Component = ( } return ( - + ); }; diff --git a/pac-man-board-game/ClientApp/src/components/gameBoard.tsx b/pac-man-board-game/ClientApp/src/components/gameBoard.tsx index 146edde..5f888db 100644 --- a/pac-man-board-game/ClientApp/src/components/gameBoard.tsx +++ b/pac-man-board-game/ClientApp/src/components/gameBoard.tsx @@ -1,17 +1,20 @@ -import React, {useEffect, useState} from "react"; +import React, {Fragment, useEffect, useState} from "react"; import {Character} from "../game/character"; import findPossiblePositions from "../game/possibleMovesAlgorithm"; import {GameTile} from "./gameTile"; import {TileType} from "../game/tileType"; -import {useAtomValue} from "jotai"; -import {allCharactersAtom, currentPlayerAtom, selectedDiceAtom} from "../utils/state"; +import {atom, PrimitiveAtom, useAtom, useAtomValue, useSetAtom} from "jotai"; +import {allCharactersAtom, currentPlayerAtom, playersAtom, selectedDiceAtom} from "../utils/state"; import Pellet from "../game/pellet"; +import {Dialog, Transition} from "@headlessui/react"; interface BoardProps extends ComponentProps { onMove?: Action, map: GameMap } +const modalOpenAtom: PrimitiveAtom = atom(false); + const Board: Component = ( { className, @@ -25,6 +28,7 @@ const Board: Component = ( const [selectedCharacter, setSelectedCharacter] = useState(); const [possiblePositions, setPossiblePositions] = useState([]); // TODO reset when other client moves a character const [hoveredPosition, setHoveredPosition] = useState(); + const setModalOpen = useSetAtom(modalOpenAtom); function handleSelectCharacter(character: Character): void { if (character.isPacMan() && currentPlayer?.PacMan.Colour !== character.Colour) { @@ -61,12 +65,8 @@ const Board: Component = ( } } - // TODO steal from other player function stealFromPlayer(): void { - // TODO select player to steal from - // TODO modal to select player - // const victim - // currentPlayer?.stealFrom(victim) + setModalOpen(true); } function pickUpPellets(destination: Path): Position[] { @@ -103,6 +103,7 @@ const Board: Component = ( return (
+ { map.map((row, rowIndex) =>
@@ -128,3 +129,88 @@ const Board: Component = ( }; export default Board; + +const SelectPlayerModal: Component = () => { + const [isOpen, setIsOpen] = useAtom(modalOpenAtom); + const currentPlayer = useAtomValue(currentPlayerAtom); + const allPlayers = useAtomValue(playersAtom).filter(p => p !== currentPlayer); + + if (currentPlayer === undefined) return null; + + function close(): void { + setIsOpen(false); + } + + return ( + <> + + + +
+ + +
+
+ + + + Steal from player + +
+ + Select a player to steal up to 2 pellets from. + +
+ + { + allPlayers.map(player => +
+ {player.Name} has {player.Box.count} pellets + +
+ ) + } + +
+ +
+
+
+
+
+
+
+ + ) +} diff --git a/pac-man-board-game/ClientApp/src/components/gameButton.tsx b/pac-man-board-game/ClientApp/src/components/gameButton.tsx index a1028f4..26c5c18 100644 --- a/pac-man-board-game/ClientApp/src/components/gameButton.tsx +++ b/pac-man-board-game/ClientApp/src/components/gameButton.tsx @@ -2,6 +2,7 @@ import React, {MouseEventHandler} from "react"; import {State} from "../game/player"; import {currentPlayerAtom, rollDiceButtonAtom, thisPlayerAtom} from "../utils/state"; import {useAtomValue} from "jotai"; +import {Button} from "./Button"; interface GameButtonProps extends ComponentProps { onReadyClick?: MouseEventHandler, @@ -19,12 +20,12 @@ const GameButton: Component = ( const activeRollDiceButton = useAtomValue(rollDiceButtonAtom); if (currentPlayer === undefined || currentPlayer.State === State.waitingForPlayers) { - return ; + return ; } if (!thisPlayer?.isTurn()) { // TODO also show when waiting for other players - return ; + return ; } - return ; + return ; }; export default GameButton; diff --git a/pac-man-board-game/ClientApp/src/components/gameComponent.tsx b/pac-man-board-game/ClientApp/src/components/gameComponent.tsx index 31c3cd4..6789d67 100644 --- a/pac-man-board-game/ClientApp/src/components/gameComponent.tsx +++ b/pac-man-board-game/ClientApp/src/components/gameComponent.tsx @@ -13,13 +13,13 @@ import GameButton from "./gameButton"; const wsService = new WebSocketService(import.meta.env.VITE_API); -// TODO ghost should be able to take pacmen +// TODO bug, when taking player on last dice, the currentPlayer changes and the wrong character get to steal +// TODO move stats above dice // TODO don't start game until at least 2 players have joined // TODO join game lobby // TODO sign up player page // TODO sign in page -// TODO steal from other players // TODO show box with collected pellets // TODO layout diff --git a/pac-man-board-game/ClientApp/src/game/player.ts b/pac-man-board-game/ClientApp/src/game/player.ts index 4b4344b..80461f3 100644 --- a/pac-man-board-game/ClientApp/src/game/player.ts +++ b/pac-man-board-game/ClientApp/src/game/player.ts @@ -2,7 +2,7 @@ import {Character, CharacterType} from "./character"; import Box from "./box"; import {Colour} from "./colour"; import {getDefaultStore} from "jotai"; -import {currentPlayerNameAtom} from "../utils/state"; +import {currentPlayerNameAtom, playersAtom} from "../utils/state"; import Pellet from "./pellet"; export enum State { @@ -44,6 +44,8 @@ export default class Player { if (pellet) this.Box.addPellet(pellet); } + const store = getDefaultStore(); + store.set(playersAtom, store.get(playersAtom).map(player => player)); } } diff --git a/pac-man-board-game/ClientApp/src/index.css b/pac-man-board-game/ClientApp/src/index.css index 13ce7d5..81b583e 100644 --- a/pac-man-board-game/ClientApp/src/index.css +++ b/pac-man-board-game/ClientApp/src/index.css @@ -23,10 +23,7 @@ br { @apply my-2; } -button, button[type=submit], input[type=button], input[type=submit] { +.button-default, button[type=submit], input[type=submit] { @apply bg-blue-500 hover:bg-blue-600 text-white font-bold py-2 px-4 rounded; -} - -button[disabled] { - @apply bg-gray-500; + @apply disabled:bg-gray-500; } diff --git a/pac-man-board-game/ClientApp/src/types/props.d.ts b/pac-man-board-game/ClientApp/src/types/props.d.ts index 3e0781c..3d480a9 100644 --- a/pac-man-board-game/ClientApp/src/types/props.d.ts +++ b/pac-man-board-game/ClientApp/src/types/props.d.ts @@ -10,7 +10,13 @@ interface ComponentProps { } interface ChildProps extends ComponentProps { - children?: React.JSX.Element, + children?: React.JSX.Element | string, +} + +interface ButtonProps extends ChildProps { + onClick?: (event: React.MouseEvent) => void, + disabled?: boolean, + type?: "button" | "submit" | "reset", } interface InputProps extends ComponentProps {