about summary refs log tree commit diff stats
path: root/html/cards/script.js
diff options
context:
space:
mode:
Diffstat (limited to 'html/cards/script.js')
-rw-r--r--html/cards/script.js146
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();