UNPKG

slanted-gamedev-toolz

Version:

A slanted mix of tools for your brilliant ideas in game design.

219 lines (218 loc) 10.5 kB
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime"; import { useCallback, useEffect, useState } from "react"; import { getModdedDeck, getRandomMods, levelCards, } from "../../cardDecks/catsDeck"; import { CardHand } from "../CardHand/CardHand"; import { DiscardBtn } from "./DiscardBtn"; import { GameHeader } from "./GameHeader"; import { HandScore } from "./HandScore"; import { MatchScore } from "./MatchScore"; import { OutComes } from "./OutComes"; import { PlayHandBtn } from "./PlayHandBtn"; import { ShuffleDealBtn } from "./ShuffleDealBtn"; import { useCatDeckHandScore } from "./hooks/useCatDeckHandScore"; import { useSpeech } from "./hooks/useSpeech"; import { bgGradient } from "./style/catDeskSx"; import "./style/CatDeck.css"; import "@fontsource/nova-cut"; import "@fontsource-variable/alegreya"; import { BtnWrapRow } from "./BtnWrapRow"; import { HandFooter } from "./HandFooter"; import { IntroScreen } from "./IntroScreen"; import { useCardOverlap } from "./hooks/useCardOverlap"; import useCatInterval from "./hooks/useCatInterval"; import { usePlayCatMusicFile } from "./hooks/usePlayCatMusicFile"; export const CatDeckDealer = ({ deck, handSize, }) => { const [tick, setTick] = useState(0); const [hasInteracted, setHasInteracted] = useState(false); useCatInterval(() => { setTick((t) => t + 1); }, 75); usePlayCatMusicFile({ hasInteracted, }); // const [gamepads, setGamepads] = useState({}); // useGamepadCatDeck((gamepads) => setGamepads(gamepads)); // const isAPressed = gamepads[0]?.buttons[0].pressed; // if (isAPressed) { // console.log("isAPressed"); // } const { speak, cancelSpeaking } = useSpeech({ isMuteSpeech: false }); const level1Target = 100; // LEVEL const [runLevel, setRunLevel] = useState(1); const [levelTarget, setLevelTarget] = useState(level1Target); const [levelScore, setLevelScore] = useState(0); const [isLevelBeaten, setIsLevelBeaten] = useState(false); const [discardsRemainingMax, setDiscardsRemainingMax] = useState(3); const [discardsRemaining, setDiscardsRemaining] = useState(discardsRemainingMax); //prettier-ignore const [maxHands, setMaxHands] = useState(3); const [handsRemaining, setHandsRemaining] = useState(maxHands); // Deck const [modCards, setModCards] = useState([]); const [remainingDeck, setRemainingDeck] = useState(getModdedDeck({ deck, modCards })); //prettier-ignore // HAND const [hand, setHand] = useState([]); const [selectedHand, setSelectedHand] = useState([]); const [selectedHandIndexes, setSelectedHandIndexes] = useState([]); const [lastHand, setLastHand] = useState([]); const [lastHandScore, setLastHandScore] = useState(0); const [lastOutcomes, setLastOutcomes] = useState([ levelCards[0], ]); const hasSelectedCards = selectedHandIndexes.length > 0; const { handScore, outcomes, multiplier, baseScore, clearOutcomes } = useCatDeckHandScore({ hand: selectedHand, modCards, lastHand, lastOutcomes, }); //prettier-ignore const clickDiscard = useCallback(() => { if (!hasSelectedCards) return; // reduce remaining discard plays setDiscardsRemaining((p) => { const def = 3; if (p === 0) return def; return p - 1; }); // discard card in hand setHand((prevHand) => { return prevHand.filter((_, index) => !selectedHandIndexes.includes(index)); }); setSelectedHandIndexes([]); setSelectedHand([]); // draw new cards const discardCount = selectedHandIndexes.length; const shuffledDeck = [...remainingDeck].sort(() => Math.random() - 0.5); const draw = shuffledDeck.slice(0, discardCount); const updatedRemainingDeck = [...shuffledDeck.slice(discardCount)]; setRemainingDeck(updatedRemainingDeck); setHand((prevHand) => { return [...prevHand, ...draw]; }); }, [hasSelectedCards, remainingDeck, selectedHandIndexes]); const clickPlayHand = useCallback(() => { // reduce remaining plays setHandsRemaining((p) => { const def = 3; if (p === 0) return def; return p - 1; }); setLastHand(selectedHand); setLastHandScore(handScore); setLastOutcomes(outcomes); setHand([]); setSelectedHand([]); setSelectedHandIndexes([]); setLevelScore((p) => { const newMatchScore = p + handScore; if (newMatchScore >= levelTarget) { setIsLevelBeaten(true); } return newMatchScore; }); const readTextString = outcomes.map((o) => `${o.headName}`).join(" "); cancelSpeaking(); speak(readTextString); }, [cancelSpeaking, handScore, levelTarget, outcomes, selectedHand, speak]); const shuffleDeck = useCallback(() => { setRemainingDeck(getModdedDeck({ deck, modCards })); }, [deck, modCards]); const restartGame = useCallback(() => { console.log("restartGame"); shuffleDeck(); setIsLevelBeaten(false); setHandsRemaining(maxHands); setLevelTarget(level1Target); setLevelScore(0); setRunLevel(1); setLastHand([]); setLastOutcomes([]); clearOutcomes(); setLastHandScore(0); setModCards([]); setSelectedHand([]); setSelectedHandIndexes([]); setDiscardsRemaining(discardsRemainingMax); }, [clearOutcomes, discardsRemainingMax, maxHands, shuffleDeck]); const isNeedShuffle = remainingDeck.length < handSize; const isAllowDealing = isNeedShuffle || hand.length === 0; const nextHand = useCallback(() => { if (!isAllowDealing) return; setHasInteracted(true); clearOutcomes(); setLastOutcomes([]); setLastHand([]); setLastHandScore(0); setSelectedHand([]); setSelectedHandIndexes([]); const shuffledDeck = [...remainingDeck].sort(() => Math.random() - 0.5); const newHand = shuffledDeck.slice(0, handSize); const updatedRemainingDeck = [...shuffledDeck.slice(handSize)]; setHand([...newHand]); setRemainingDeck(updatedRemainingDeck); }, [isAllowDealing, clearOutcomes, remainingDeck, handSize]); const nextLevel = useCallback(() => { setModCards(getRandomMods(runLevel)); setIsLevelBeaten(false); setHandsRemaining(maxHands); setLevelTarget((p) => p * 2); setRunLevel((p) => p + 1); setLevelScore(0); setDiscardsRemaining(discardsRemainingMax); nextHand(); }, [nextHand, discardsRemainingMax, maxHands, runLevel]); const isHandDealt = hand.length > 1; const showTurnBtns = isHandDealt && !isNeedShuffle; const isOutOfHands = handsRemaining === 0; const showNextLevelBtn = isOutOfHands || isLevelBeaten; const isGameOver = isOutOfHands && !isLevelBeaten; const modMyCards = useCallback(() => { setHand((p) => getModdedDeck({ deck: p, modCards })); setRemainingDeck((p) => getModdedDeck({ deck: p, modCards })); }, []); useEffect(() => { if (runLevel) speak(`Level ${runLevel}`); // eslint-disable-next-line react-hooks/exhaustive-deps }, [runLevel]); useEffect(() => { if (levelTarget) speak(`Target: ${levelTarget} cats`); // eslint-disable-next-line react-hooks/exhaustive-deps }, [levelTarget]); useEffect(() => { if (lastHandScore) speak(`${lastHandScore} cats join`); // eslint-disable-next-line react-hooks/exhaustive-deps }, [lastHandScore]); useEffect(() => { if (isLevelBeaten) { speak("Level Complete!"); } // eslint-disable-next-line react-hooks/exhaustive-deps }, [isLevelBeaten]); useEffect(() => { if (isGameOver) speak("Game Over"); // eslint-disable-next-line react-hooks/exhaustive-deps }, [isGameOver]); const isHandInPlay = hand.length > 0; const { overlap } = useCardOverlap(); if (!hasInteracted) { return (_jsx(IntroScreen, { setHasInteracted: setHasInteracted, overlap: overlap })); } return (_jsxs("div", { style: deckStyle, children: [_jsx(GameHeader, { runLevel: runLevel, isLevelBeaten: isLevelBeaten, isGameOver: isGameOver }), _jsx(MatchScore, { score: levelScore, target: levelTarget }), _jsx(BtnWrapRow, { children: _jsx(ShuffleDealBtn, { levelScore: levelScore, isHandDealt: isHandDealt, showNextLevelBtn: showNextLevelBtn, isGameOver: isGameOver, isAllowDealing: isAllowDealing, shuffleDeck: shuffleDeck, remainingDeck: remainingDeck, nextLevel: nextLevel, isLevelBeaten: isLevelBeaten, nextHand: nextHand, handsRemaining: handsRemaining, isOutOfHands: isOutOfHands, restartGame: restartGame }) }), _jsxs(CardHand, { cards: hand, overlap: overlap, chaos: 2, selectedLift: -20, isUnSelectable: false, selectedHandIndexes: selectedHandIndexes, setSelectedHandIndexes: setSelectedHandIndexes, setSelectedHand: setSelectedHand, children: [_jsx(HandFooter, { hand: hand }), _jsxs(BtnWrapRow, { children: [_jsx(DiscardBtn, { clickDiscard: clickDiscard, discardsRemaining: discardsRemaining, hasSelectedCards: hasSelectedCards, showTurnBtns: showTurnBtns }), _jsx(PlayHandBtn, { clickPlayHand: clickPlayHand, selectedHand: selectedHand, handsRemaining: handsRemaining, showTurnBtns: showTurnBtns })] }), _jsx(HandScore, { score: handScore, baseScore: baseScore, multiplier: multiplier }), _jsx(OutComes, { levelTarget: levelTarget, isLevelBeaten: isLevelBeaten, outcomes: outcomes, levelScore: levelScore, overlap: overlap, lastHand: lastHand, lastOutcomes: lastOutcomes, isHandInPlay: isHandInPlay, lastHandScore: lastHandScore })] }), _jsx(_Fragment, { children: modCards.length ? (_jsxs(_Fragment, { children: [_jsxs("h1", { style: { textAlign: "center" }, children: ["Mods: ", modCards.length] }), _jsx(CardHand, { cards: modCards, overlap: 20 })] })) : null })] })); }; const deckStyle = { backgroundImage: bgGradient, paddingTop: "15px", borderRadius: "2px", minHeight: "100vh", body: { fontFamily: "'Nova Cut', system-ui", }, };