import { Container, Graphics, PixiRef, Sprite, Stage, useApp, useTick, } from "@pixi/react" import { PlayerId } from "dusk-games-sdk/multiplayer" import { Texture } from "pixi.js" import { useEffect, useRef, useState } from "react" import selectSoundAudio from "./assets/select.wav" import { GameState } from "./logic.ts" const selectSound = new Audio(selectSoundAudio) function App() { const [game, setGame] = useState() const [yourPlayerId, setYourPlayerId] = useState() useEffect(() => { Dusk.initClient({ onChange: ({ game, action, yourPlayerId }) => { setGame(game) setYourPlayerId(yourPlayerId) if (action && action.name === "claimCell") selectSound.play() }, }) }, []) if (!game) { // Dusk only shows your game after an onChange() so no need for loading screen return } const { winCombo, lastMovePlayerId, playerIds, freeCells } = game return ( <>
) } type BoardProps = { yourPlayerId?: PlayerId game?: GameState } export function Board({ yourPlayerId, game }: BoardProps) { const app = useApp() app.resizeTo = document.getElementById("board") as HTMLElement if (!game) { return null } const { cells, lastMovePlayerId, playerIds } = game return ( <> {cells.map((cell, index) => { const x = index % 3 const y = Math.floor(index / 3) if (cell) { return ( ) } return ( Dusk.actions.claimCell(index)} key={index} /> ) })} ) } function Grid() { const app = useApp() const width = app.view.width / devicePixelRatio return ( { g.lineStyle(4, 0x555555) for (let i = 1; i < 3; i++) { g.moveTo(i * (width / 3), 0) g.lineTo(i * (width / 3), width) g.moveTo(0, i * (width / 3)) g.lineTo(width, i * (width / 3)) } }} /> ) } function OccupiedSpace({ x, y, side, }: { x: number y: number side: "x" | "o" }) { const app = useApp() const spriteRef = useRef>(null) const width = app.view.width / devicePixelRatio / 3 useTick((delta) => { if (spriteRef.current) { if (spriteRef.current.width < width - 20) { spriteRef.current.width += delta * 5 spriteRef.current.height += delta * 5 } } }) return ( ) } function EmptySpace({ x, y, canClaim, onpointerdown, }: { x: number y: number canClaim: boolean onpointerdown: () => void }) { const [hovering, setHovering] = useState(false) const app = useApp() const width = app.view.width / devicePixelRatio / 3 if (!canClaim) { return null } return ( {hovering && } setHovering(true)} onpointerout={() => setHovering(false)} onpointerdown={onpointerdown} /> ) } function Dot() { const app = useApp() const width = app.view.width / devicePixelRatio / 3 return ( { g.beginFill(0xffffff) g.drawCircle(width / 2, width / 2, 10) }} /> ) } export default App