From fba354686190363378deb0f12c76ec8419294cbc Mon Sep 17 00:00:00 2001 From: ColorFilter Date: Sat, 17 Feb 2024 23:11:18 +0900 Subject: [PATCH] feat: Add draw label and animation (#3) --- public/favicon.png | Bin 5285 -> 3303 bytes public/icon-512.png | Bin 0 -> 3610 bytes public/manifest.json | 7 ++++++- src/components/common/fade.tsx | 2 +- src/components/game/draw-label.tsx | 25 +++++++++++++++++++++++++ src/components/game/index.ts | 1 + src/components/game/square.tsx | 15 +++++++++++---- src/components/game/winner-label.tsx | 2 +- src/hooks/use-game-sound.ts | 19 +++++++------------ src/hooks/use-game.ts | 11 ++++++----- src/pages/game-history.tsx | 2 +- src/pages/game.tsx | 16 +++++++++++++--- tailwind.config.js | 6 ++++-- 13 files changed, 76 insertions(+), 30 deletions(-) create mode 100644 public/icon-512.png create mode 100644 src/components/game/draw-label.tsx diff --git a/public/favicon.png b/public/favicon.png index 87f378ae188a87b5ec93a4534220ab7b4de032bf..9ab2fef67d5402f1582c9baba821778248720d61 100644 GIT binary patch literal 3303 zcmeHKZA?>F7`_-#go#f40CdzPo4QTy46wpNsXA~l(K)7w%9nh!c2z3nqb&t$Fa{l9 z=ZGRwZnvpp3uw_RumwxQPzcWUj#a@HZfjd@?dS*4kK5XE+135q|0OfwBq#54-ke|0 zd*0`L&e^?tK3x(N5d;9hl9c4cGyqtD!v#R#LOeJ)4`1NHzhpY!?aeT8`Z*P+ihSj|*I&&{HDqU9X?9Cy}ReK3`qJM|Q zYP2?JFt^|^S&{#MGS(8WFv=tIQwh8E?c(afO2-KQ;<5e&ZqZn9CwOXLAWPhNeqi8A zmKYEPkwR|3kThe{pf*O;vj+gSeFFd|*ZBd!cAU-{f1Ja`01&tw0G7Q20PB+HFZ^$K zc%ECowMa6hyMc1nubQk>I68WMSxYL4v{amKn5e*99LyCbYG<&}mW;`$9tMwN8`G(~ z%ldhI?78cib-EtubN&_^A3NcUm?M?g&cfqyR)U65H>SCSvB?VGwM`eZ)R&C{i6OeA zJJ0oJYr3qNDwj8tc?k(zn_#Jm>bm7=V%ZoEG%wL=P@?q(%d%tm3T3+?b5uf^KGZHB ztFjrTL-b)!1Vr$twunq!?1=HI?okjjm6Qd*j{9+5cWO=nW;W9;-mLO!rRaL0aXenJ zdbY~&`RnxPjusnt<%r59cf;~G8A8xJXh>$|g1b0`T9ROpA$>7xW{@Z7m*aR(eLo{@ z9u&&BWz(GvZ>P?gYc=7_IlI{I&AhgfErnXs4?68gD8m9Rf~`Bz@&IqP!^lCe@$^QG z*O?AG!tAhfJ?!`uqF|~X{)}w8Upf5kW)Q>5%;QlX(v&t?)*&ua5w^(I=jmxzo!-1Q z5>YvW)^O2Qegj)QqpUfO#NuVgGj>EOXjJI4#QhOIywB(ReO~wG_5VK^b0O9VNzde4 zgRkVFtzE6Fgm|EFxq3(|yJE?C8ia67!FsdVp_LL#nN3ITA+}>}`>8IZhdidDEd`MV zt0l-Kc@9rMgR8MLlrw5odvxw6<^l;b+pb0};g_Jtr(j=Wx_Uf%Q0FB5Xwp&)*||#M z)fkw-lhKFMc2S84{gIGvFbkECQQwGS?(dFMi7ov1(7r+6E2LGfkxTzD@3)g$C11%4 z5pSrt>#s@#t;Tr5i$d{M?|HFhra7C}b`zm7EO9Lf2M$c7iiMB>b|e{KIXK#JjQtj;98LSO;8>k(ZXRp}!j5|()$e44~Fz31buW2hqXPSnH{HfmSplPc?G`Slz zmC*RUF6JFq*FVZ#p8Lr5pwl~q4)urSua&a-W4$NN4M2*QHcgKb>QRC_v%gzS;dV~0 z{AlKhTT;xbxHB1(af;$MZ`WQUSDG1006{D6&V(Rnt_X1Ni}g;ui1#X@8x)M&OoZ>J YSeJKL=2>_W|C9hJNqZ7+?8vS88)}|@F8}}l literal 5285 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 Fe*n-~<6!^* diff --git a/public/icon-512.png b/public/icon-512.png new file mode 100644 index 0000000000000000000000000000000000000000..821cbbc7dcd0d91e1b4a5ad9a891780003eedefc GIT binary patch literal 3610 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 Q&$Vcrw*HyYQ&#u>2IMXR=l}o! literal 0 HcmV?d00001 diff --git a/public/manifest.json b/public/manifest.json index 4de99ef..4101304 100644 --- a/public/manifest.json +++ b/public/manifest.json @@ -9,7 +9,12 @@ "src": "/icon-maskable-512.png", "sizes": "512x512", "type": "image/png", - "purpose": "any" + "purpose": "maskable" + }, + { + "src": "/icon-512.png", + "sizes": "512x512", + "type": "image/png" } ], "start_url": "/", diff --git a/src/components/common/fade.tsx b/src/components/common/fade.tsx index e9aa01b..aacedfc 100644 --- a/src/components/common/fade.tsx +++ b/src/components/common/fade.tsx @@ -41,7 +41,7 @@ export default function Fade({ return ( {children} diff --git a/src/components/game/draw-label.tsx b/src/components/game/draw-label.tsx new file mode 100644 index 0000000..0003dbb --- /dev/null +++ b/src/components/game/draw-label.tsx @@ -0,0 +1,25 @@ +import { clsx } from 'clsx'; + +import { Box } from '@/components'; + +interface DrawLabelProps { + isDraw: boolean; + className?: string; +} + +export default function DrawLabel({ isDraw, className }: DrawLabelProps) { + return ( + + draw + + ); +} diff --git a/src/components/game/index.ts b/src/components/game/index.ts index be73d9b..54aab57 100644 --- a/src/components/game/index.ts +++ b/src/components/game/index.ts @@ -7,3 +7,4 @@ export { default as TurnIndicator } from './turn-indicator'; export { default as UndoStatus } from './undo-status'; export { default as OrderToggle } from './order-toggle'; export { default as WinnerLabel } from './winner-label'; +export { default as DrawLabel } from './draw-label'; diff --git a/src/components/game/square.tsx b/src/components/game/square.tsx index c9154e7..6ea0d84 100644 --- a/src/components/game/square.tsx +++ b/src/components/game/square.tsx @@ -27,14 +27,21 @@ export default function Square({ ...buttonProps }: SquareProps) { const buttonClasses = clsx( - 'relative transition-all duration-500', - highlight && 'bg-slate-600', + 'relative transition-all duration-300', + { 'bg-slate-600': highlight }, className, ); - const markClasses = clsx('inline-block', dim && 'opacity-50'); + const markClasses = clsx('inline-block', { + 'animate-blink-2': highlight && !buttonProps.disabled, + 'opacity-50': dim, + }); const sequenceClasses = clsx( 'absolute right-0 top-0 grid size-5 place-content-center text-xs font-medium transition-all duration-300', - [highlight ? 'text-slate-400' : 'text-slate-500', hideSequence && 'invisible opacity-0'], + { + 'text-slate-400': highlight, + 'text-slate-500': !highlight, + 'invisible opacity-0': hideSequence, + }, ); return ( diff --git a/src/components/game/winner-label.tsx b/src/components/game/winner-label.tsx index cd57d20..58c6eea 100644 --- a/src/components/game/winner-label.tsx +++ b/src/components/game/winner-label.tsx @@ -13,7 +13,7 @@ export default function WinnerLabel({ target, winner, className }: WinnerLabelPr diff --git a/src/hooks/use-game-sound.ts b/src/hooks/use-game-sound.ts index e24fbb6..19f6834 100644 --- a/src/hooks/use-game-sound.ts +++ b/src/hooks/use-game-sound.ts @@ -13,37 +13,32 @@ type SoundPath = (typeof soundPath)[number]; export const useGameSound = () => { const isMuted = useIsMuted(); const audioRef = useRef>(new Map()); - // const currentPlaying = useRef(null); + const loaded = useRef(false); - // 오디오 파일을 미리 로드 useEffect(() => { + if (loaded.current) return; + const preload = (soundPath: SoundPath) => { - const audio = new Audio(soundPath); + const audio = new Audio(soundPath); // 오디오 파일 미리 로드 audioRef.current.set(soundPath, audio); }; soundPath.forEach(preload); + loaded.current = true; }, []); const playSound = (soundPath: SoundPath) => { const audio = audioRef.current.get(soundPath); if (isMuted || !audio) return; - // // 오디오가 재생중이면 - // if (currentPlaying.current?.paused === false) { - // currentPlaying.current.pause(); - // currentPlaying.current.currentTime = 0; - // } - audio.play().catch((error) => console.error('Failed to play sound', error)); - // .finally(() => (currentPlaying.current = audio)); }; const mark = (identifier: BasePlayer) => playSound(identifier === BasePlayer.X ? soundX : soundO); - const end = (isTied: boolean) => { + const end = (isDraw: boolean) => { // 마지막 마크 사운드와 안겹치도록 딜레이 추가 - setTimeout(() => playSound(isTied ? gameOverTie : gameOver), 350); + setTimeout(() => playSound(isDraw ? gameOverTie : gameOver), 350); }; return { mark, end }; diff --git a/src/hooks/use-game.ts b/src/hooks/use-game.ts index 643c53d..6527115 100644 --- a/src/hooks/use-game.ts +++ b/src/hooks/use-game.ts @@ -60,13 +60,13 @@ export const useGame = ({ newBoard[boardIdx] = createSquare(identifier, mark, updatedSequence.length, color); setBoard(newBoard); - const isTied = updatedSequence.length === newBoard.length; + const isDraw = updatedSequence.length === newBoard.length; const winIndices = checkWin(newBoard, size, winCondition, boardIdx, identifier); if (winIndices) winner.current = { identifier, indices: winIndices, mark }; - if (winIndices || isTied) { + if (winIndices || isDraw) { addHistory(createHistory(newBoard, winner.current, size)); - playSound.end(isTied); + playSound.end(isDraw); } else togglePlayer(); }, [addHistory, board, playSound, playerConfigs, size, togglePlayer, winCondition], @@ -112,12 +112,12 @@ export const useGame = ({ }, [board, isSinglePlay, onBoardClick, size, winCondition]); const hasMark = sequence.current.length > 0; - const isTied = sequence.current.length === board.length; + const isDraw = sequence.current.length === board.length; const hasWinner = Boolean(winner.current.identifier); const hasUndoCount = undoControls.getUndoCountBy(currentPlayer.current) > 0; const enabledReset = hasMark || isUndoUsed; - const enableUndo = !hasWinner && hasMark && hasUndoCount && !isTied; + const enableUndo = !hasWinner && hasMark && hasUndoCount && !isDraw; return { board, @@ -126,5 +126,6 @@ export const useGame = ({ controlStates: { undo: enableUndo, reset: enabledReset }, winner: winner.current, undoCounts, + isDraw, }; }; diff --git a/src/pages/game-history.tsx b/src/pages/game-history.tsx index 0e7f867..6be8b8a 100644 --- a/src/pages/game-history.tsx +++ b/src/pages/game-history.tsx @@ -6,7 +6,7 @@ export default function GameHistory() { const { toggle: toggleShowOrder, isOpen: showOrder } = useDisclosure(true); return ( - +