diff options
author | elioat <elioat@tilde.institute> | 2025-01-11 12:31:10 -0500 |
---|---|---|
committer | elioat <elioat@tilde.institute> | 2025-01-11 12:31:10 -0500 |
commit | 0db2c0d0c929ff6fc191b9f988ef0ea022afd58f (patch) | |
tree | ec31d13143c6b2905870ac6d6cb9240754bfa0b2 | |
parent | 49338d20b0e95e05cf3502b5394996b97e44ae03 (diff) | |
download | tour-0db2c0d0c929ff6fc191b9f988ef0ea022afd58f.tar.gz |
*
-rw-r--r-- | html/cards/script.js | 136 |
1 files changed, 126 insertions, 10 deletions
diff --git a/html/cards/script.js b/html/cards/script.js index 049f91f..3889678 100644 --- a/html/cards/script.js +++ b/html/cards/script.js @@ -32,6 +32,18 @@ const INITIAL_CARD_Y = 20; const FONT_SIZE = '34px "pokemon-font", monospace'; const CARD_BORDER_COLOR = '#000000'; const CARD_FACE_COLOR = '#FFFFFF'; +const DECK_COUNT = 4; // Can be changed to any number +const BASE_COLORS = [ + { primary: '#FF9900', secondary: '#FFCC00' }, // Original orange deck + { primary: '#6B8E23', secondary: '#9ACD32' }, // Olive green deck + { primary: '#4169E1', secondary: '#87CEEB' }, // Royal blue deck + { primary: '#8B008B', secondary: '#DA70D6' }, // Purple deck + { primary: '#CD853F', secondary: '#DEB887' } // Brown deck +]; + +// Add new constants for pile layout +const PILE_SPACING = CARD_WIDTH + PADDING * 4; // Space between piles +const PILE_OFFSET = 5; // Vertical offset for stacked cards // Canvas setup const canvas = document.getElementById('cards'); @@ -49,7 +61,21 @@ const shuffle = array => { return result; }; -const createDeck = () => SUITS.flatMap(suit => VALUES.map(value => ({ suit, value }))); +const createDeck = (deckIndex) => SUITS.flatMap(suit => + VALUES.map(value => ({ + suit, + value, + deckId: deckIndex // Add deckId to track which deck a card belongs to + })) +); + +// Create multiple decks +const createDecks = (count) => { + if (count > BASE_COLORS.length) { + console.warn(`Only ${BASE_COLORS.length} unique deck colors are defined. Some decks will repeat colors.`); + } + return Array.from({ length: count }, (_, i) => createDeck(i)).flat(); +}; // Create a more functional card factory const createCard = (x, y, cardData) => Object.freeze({ @@ -77,11 +103,14 @@ const drawCardBack = card => { }; const drawRetroPattern = card => { - const checkeredSize = 10; // Size of each square in the checkered pattern + const checkeredSize = 10; + const deckColors = BASE_COLORS[card.card.deckId % BASE_COLORS.length]; + for (let i = 0; i < CARD_WIDTH; i += checkeredSize) { for (let j = 0; j < CARD_HEIGHT; j += checkeredSize) { - // Alternate colors for the checkered pattern - ctx.fillStyle = (Math.floor(i / checkeredSize) + Math.floor(j / checkeredSize)) % 2 === 0 ? '#FF9900' : '#FFCC00'; + ctx.fillStyle = (Math.floor(i / checkeredSize) + Math.floor(j / checkeredSize)) % 2 === 0 + ? deckColors.primary + : deckColors.secondary; ctx.fillRect(card.x + i, card.y + j, checkeredSize, checkeredSize); } } @@ -117,7 +146,8 @@ const renderCard = card => { const renderAllCards = cards => { clearCanvas(); - cards.forEach(renderCard); // Renders cards in the order they are in the array + cards.forEach(renderCard); + // renderDeckStats(); // Add this line to show deck statistics }; // State management @@ -126,16 +156,38 @@ let gameState; const initializeGameState = () => ({ cards: [], draggingCard: null, - deck: shuffle(createDeck()), + deck: shuffle(createDecks(DECK_COUNT)), stackPosition: { x: 0, y: 0 } }); const initializeGame = () => { try { gameState = initializeGameState(); - gameState.cards = gameState.deck.map((cardData, index) => - createCard(INITIAL_CARD_X, INITIAL_CARD_Y + index * 5, cardData) - ); + + // Group cards by deck + const cardsByDeck = gameState.deck.reduce((acc, cardData) => { + const deckId = cardData.deckId; + if (!acc[deckId]) acc[deckId] = []; + acc[deckId].push(cardData); + return acc; + }, {}); + + // Calculate starting X position to center all piles + const totalWidth = PILE_SPACING * DECK_COUNT; + const startX = (canvas.width - totalWidth) / 2; + + // Create cards for each deck in its own pile + gameState.cards = Object.entries(cardsByDeck).flatMap(([deckId, deckCards]) => { + const pileX = startX + (parseInt(deckId) * PILE_SPACING); + + return deckCards.map((cardData, indexInDeck) => + createCard( + pileX, + INITIAL_CARD_Y + (indexInDeck * PILE_OFFSET), + cardData + ) + ); + }); clearCanvas(); renderAllCards(gameState.cards); @@ -239,7 +291,7 @@ const handleMouseDown = e => { // Add this function to handle the reset confirmation const handleResetGame = () => { if (confirm("Would you like to reset the cards?")) { - initializeGame(); // Reset the game state + resetCardsToOriginalPiles(); } }; @@ -254,6 +306,70 @@ const toggleCardFace = card => ({ isFaceUp: !card.isFaceUp }); +// Add a function to get deck statistics +const getDeckStats = () => { + const stats = new Map(); + gameState.cards.forEach(card => { + const deckId = card.card.deckId; + const current = stats.get(deckId) || { total: 0, faceUp: 0 }; + stats.set(deckId, { + total: current.total + 1, + faceUp: current.faceUp + (card.isFaceUp ? 1 : 0) + }); + }); + return stats; +}; + +// Optional: Add a display for deck statistics +const renderDeckStats = () => { + const stats = getDeckStats(); + ctx.font = '16px "pokemon-font", monospace'; + + // Calculate the same starting X position as the piles + const totalWidth = PILE_SPACING * DECK_COUNT; + const startX = (canvas.width - totalWidth) / 2; + + stats.forEach((stat, deckId) => { + const colors = BASE_COLORS[deckId % BASE_COLORS.length]; + const pileX = startX + (deckId * PILE_SPACING); + + ctx.fillStyle = colors.primary; + ctx.textAlign = 'center'; + ctx.fillText( + `Deck ${deckId + 1}: ${stat.faceUp}/${stat.total}`, + pileX + CARD_WIDTH / 2, + INITIAL_CARD_Y - 10 + ); + }); +}; + +// Optional: Add a function to reset cards to their original piles +const resetCardsToOriginalPiles = () => { + const totalWidth = PILE_SPACING * DECK_COUNT; + const startX = (canvas.width - totalWidth) / 2; + + // Group cards by deck + const cardsByDeck = gameState.cards.reduce((acc, card) => { + const deckId = card.card.deckId; + if (!acc[deckId]) acc[deckId] = []; + acc[deckId].push(card); + return acc; + }, {}); + + // Reset position for each deck + Object.entries(cardsByDeck).forEach(([deckId, deckCards]) => { + const pileX = startX + (parseInt(deckId) * PILE_SPACING); + + deckCards.forEach((card, index) => { + card.x = pileX; + card.y = INITIAL_CARD_Y + (index * PILE_OFFSET); + card.isFaceUp = false; + }); + }); + + renderAllCards(gameState.cards); +}; + // Start the game initializeGame(); |