diff options
-rw-r--r-- | html/cards/script.js | 146 |
1 files changed, 59 insertions, 87 deletions
diff --git a/html/cards/script.js b/html/cards/script.js index 50c4287..b851a6d 100644 --- a/html/cards/script.js +++ b/html/cards/script.js @@ -6,6 +6,9 @@ const SUITS = ['❤️', '♦️', '♣️', '♠️']; const VALUES = ['2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K', 'A']; const CARD_BACK_COLOR = '#0066cc'; const PATTERN_SIZE = 10; +const INITIAL_CARD_X = 20; +const INITIAL_CARD_Y = 20; +const FONT_SIZE = '30px Arial'; // Canvas setup const canvas = document.getElementById('cards'); @@ -14,29 +17,24 @@ canvas.width = window.innerWidth; canvas.height = window.innerHeight; // Pure functions -const shuffle = array => [...array] - .reduce((acc, _, i) => { - const j = Math.floor(Math.random() * (i + 1)); - [acc[i], acc[j]] = [acc[j], acc[i]]; - return acc; - }, [...array]); +const shuffle = array => [...array].reduce((acc, _, i) => { + const j = Math.floor(Math.random() * (i + 1)); + [acc[i], acc[j]] = [acc[j], acc[i]]; + return acc; +}, [...array]); -const createDeck = () => - SUITS.flatMap(suit => VALUES.map(value => ({ suit, value }))); +const createDeck = () => SUITS.flatMap(suit => VALUES.map(value => ({ suit, value }))); const createCard = (x, y, cardData) => ({ - x: x + 20, - y: y + 20, + x: x + PADDING, + y: y + PADDING, card: cardData, isFaceUp: false // Cards start face down }); // Function to check if a point is within a card const isPointInCard = (x, y, card) => - x >= card.x && - x <= card.x + CARD_WIDTH && - y >= card.y && - y <= card.y + CARD_HEIGHT; + x >= card.x && x <= card.x + CARD_WIDTH && y >= card.y && y <= card.y + CARD_HEIGHT; // Rendering functions const clearCanvas = () => { @@ -44,12 +42,15 @@ const clearCanvas = () => { ctx.fillRect(0, 0, canvas.width, canvas.height); }; -// Update renderCardBack to use regular rectangles -const renderCardBack = card => { +const drawCardBack = card => { ctx.fillStyle = CARD_BACK_COLOR; - ctx.fillRect(card.x, card.y, CARD_WIDTH, CARD_HEIGHT); // Revert to regular rectangle - - // Draw checkered pattern + ctx.fillRect(card.x, card.y, CARD_WIDTH, CARD_HEIGHT); + drawCheckeredPattern(card); + ctx.strokeStyle = 'black'; + ctx.strokeRect(card.x, card.y, CARD_WIDTH, CARD_HEIGHT); +}; + +const drawCheckeredPattern = card => { ctx.strokeStyle = '#003366'; for (let i = 0; i < CARD_WIDTH; i += PATTERN_SIZE) { for (let j = 0; j < CARD_HEIGHT; j += PATTERN_SIZE) { @@ -59,42 +60,33 @@ const renderCardBack = card => { } } } - - // Draw border - ctx.strokeStyle = 'black'; - ctx.strokeRect(card.x, card.y, CARD_WIDTH, CARD_HEIGHT); // Revert to regular rectangle }; -// Update renderCardFront to use regular rectangles -const renderCardFront = card => { +const drawCardFront = card => { ctx.fillStyle = 'white'; - ctx.fillRect(card.x, card.y, CARD_WIDTH, CARD_HEIGHT); // Regular rectangle + ctx.fillRect(card.x, card.y, CARD_WIDTH, CARD_HEIGHT); ctx.fillStyle = 'black'; - - // Set a larger font size - ctx.font = '30px Arial'; // Increased font size for better visibility + ctx.font = FONT_SIZE; ctx.strokeRect(card.x, card.y, CARD_WIDTH, CARD_HEIGHT); - // Draw value in the top left corner - ctx.textAlign = 'left'; // Ensure left alignment for the value - ctx.fillText(card.card.value, card.x + 10, card.y + 40); // Adjusted y position for larger font - - // Draw suit in the center of the card - ctx.textAlign = 'center'; // Center the text for the suit - ctx.fillText(card.card.suit, card.x + CARD_WIDTH / 2, card.y + CARD_HEIGHT / 2 + 10); // Centered position - - // Draw value in the bottom right corner with adjusted padding - ctx.textAlign = 'right'; // Ensure right alignment for the bottom value - ctx.fillText(card.card.value, card.x + CARD_WIDTH - 20, card.y + CARD_HEIGHT - 10); // Reduced padding + // Draw value and suit + drawCardValue(card.card.value, card.x + 10, card.y + 40, 'left'); + drawCardSuit(card.card.suit, card.x + CARD_WIDTH / 2, card.y + CARD_HEIGHT / 2 + 10); + drawCardValue(card.card.value, card.x + CARD_WIDTH - 20, card.y + CARD_HEIGHT - 10, 'right'); +}; + +const drawCardValue = (value, x, y, alignment) => { + ctx.textAlign = alignment; + ctx.fillText(value, x, y); +}; + +const drawCardSuit = (suit, x, y) => { + ctx.textAlign = 'center'; + ctx.fillText(suit, x, y); }; const renderCard = card => { - // Always render the card based on its current state - if (card.isFaceUp) { - renderCardFront(card); - } else { - renderCardBack(card); - } + card.isFaceUp ? drawCardFront(card) : drawCardBack(card); }; const renderAllCards = cards => { @@ -103,14 +95,29 @@ const renderAllCards = cards => { }; // State management -const gameState = { +let gameState; + +const initializeGameState = () => ({ cards: [], draggingCard: null, deck: shuffle(createDeck()), - stackPosition: { - x: 0, - y: 0 - } + stackPosition: { x: 0, y: 0 } +}); + +const initializeGame = () => { + gameState = initializeGameState(); + gameState.cards = gameState.deck.map(cardData => createCard(INITIAL_CARD_X, INITIAL_CARD_Y, cardData)); + + gameState.cards.forEach((card, index) => { + card.y += index * 5; // Stack cards with a slight offset for visibility + }); + + clearCanvas(); + renderAllCards(gameState.cards); + + // Add event listeners + canvas.addEventListener('mousedown', handleMouseDown); + canvas.addEventListener('contextmenu', e => e.preventDefault()); }; // Event handlers @@ -130,19 +137,14 @@ const handleMouseUp = () => { document.removeEventListener('mouseup', handleMouseUp); }; -// Define handleMouseDown before using it const handleMouseDown = e => { const rect = canvas.getBoundingClientRect(); const x = e.clientX - rect.left; const y = e.clientY - rect.top; - // Handle right click for card flipping if (e.button === 2) { // Right click e.preventDefault(); - const clickedCard = gameState.cards.find(card => - isPointInCard(x, y, card) && - (card.x !== gameState.stackPosition.x || card.y !== gameState.stackPosition.y) - ); + const clickedCard = gameState.cards.find(card => isPointInCard(x, y, card)); if (clickedCard) { clickedCard.isFaceUp = !clickedCard.isFaceUp; // Toggle card face renderAllCards(gameState.cards); // Re-render all cards @@ -150,44 +152,14 @@ const handleMouseDown = e => { return; } - // Find the top-most clicked card const clickedCard = gameState.cards.slice().reverse().find(card => isPointInCard(x, y, card)); - if (clickedCard) { - // If it's a card in the stack, handle drawing it - if (clickedCard.x === gameState.stackPosition.x && - clickedCard.y === gameState.stackPosition.y) { - clickedCard.isFaceUp = true; - } - - // Allow dragging regardless of where the card is gameState.draggingCard = clickedCard; document.addEventListener('mousemove', handleMouseMove); document.addEventListener('mouseup', handleMouseUp); } }; -// Initialize game -const initializeGame = () => { - // Create a full deck of cards - gameState.deck = shuffle(createDeck()); - gameState.cards = gameState.deck.map(cardData => createCard(0, 0, cardData)); - - // Draw cards in a pile with their reverse side showing - gameState.cards.forEach((card, index) => { - card.x = 20; // Pile at 20 pixels from the left - card.y = 20 + index * 5; // Stack cards with a slight offset for visibility - card.isFaceUp = false; // Ensure cards start face down - }); - - clearCanvas(); - renderAllCards(gameState.cards); - - // Add event listeners - canvas.addEventListener('mousedown', handleMouseDown); - canvas.addEventListener('contextmenu', e => e.preventDefault()); -}; - // Start the game initializeGame(); |