From 2041108973721dd7da404346d655dcfb5f9fa0b6 Mon Sep 17 00:00:00 2001 From: Nathan Date: Sun, 3 Nov 2024 22:39:58 +0000 Subject: [PATCH] Draw basic cardData to cards in player hand --- cardGen.js | 18 +++- public/js/canvas/draw.js | 199 ++++++++++++++++++++++++++++++++---- public/js/canvas/helpers.js | 17 ++- public/js/global.js | 14 +++ public/js/main.js | 8 -- 5 files changed, 226 insertions(+), 30 deletions(-) diff --git a/cardGen.js b/cardGen.js index 2eccb69..5ab9fcc 100644 --- a/cardGen.js +++ b/cardGen.js @@ -477,13 +477,29 @@ function requestDeck(itemData = null){ // The data to be passed (for basic stat/inspect basically) // atk, mana, cost, etc. will be their own components that alter game by game + + // TODO: Make this the cardData that's important/will be passed to the clients itemData.component.cardData[itemCount] = { 'id': builtCards[deckListItem.cardId].id, 'name': builtCards[deckListItem.cardId].name, - //'effect': builtCards[deckListItem.cardId].effect[0].description, 'cost': builtCards[deckListItem.cardId].cost, + 'attack': builtCards[deckListItem.cardId].atk, + 'type': builtCards[deckListItem.cardId].type, // Unit, Spell, Token, etc. + 'passive': builtCards[deckListItem.cardId].passive, + 'class': builtCards[deckListItem.cardId].cardClass, + 'manaColour': builtCards[deckListItem.cardId].cardManaColour, + 'colour': builtCards[deckListItem.cardId].colourRequirements, + 'rarity': builtCards[deckListItem.cardId].rarity, + 'effect': [] }; + // Effects should just be the description to draw onto the card(s) + for (const [key, effect] of Object.entries(builtCards[deckListItem.cardId].effect)) { + itemData.component.cardData[itemCount]['effect'].push(effect.description); + } + // TODO: Above cardData should be built correctly first off probably. Then clean-up all the + // dupe code created for the tidy up // For above 'builtCards' should be changed I think + // boardElement[itemCount] = 'deck'; // Add all cards to deck at match start diff --git a/public/js/canvas/draw.js b/public/js/canvas/draw.js index fa6bd7c..417d908 100644 --- a/public/js/canvas/draw.js +++ b/public/js/canvas/draw.js @@ -101,6 +101,12 @@ function calculateHandPositions(){ } } +// TODO: Move this function elsewhere, not really a draw function +function calculateCardSpacing(){ + + // TEMP: these spaces should live elsewhere (likely global) + let namePosition = 5; +} function drawEntities(){ @@ -130,15 +136,7 @@ function drawEntities(){ function drawDeck(entity){ // Draw the deck shape - let shape = new Shape({ - x: gameData.position[entity][0], - y: gameData.position[entity][1], - width: gameData.size[entity][0], - height: gameData.size[entity][1], - fillStyle: '#EEE', - strokeStyle: '#AAA', - }); - shape.draw(); + drawCardBack(entity); // Draw circle for deck count to sit in let deckCounterSprite = new Shape({ @@ -167,7 +165,12 @@ function drawCardInHand(entity){ console.log('Draw card in hand'); console.log(gameData.position[entity]); console.log(gameData.size[entity]); + + // TODO: Tapped, Attacking, Targettable, Activatable borders + // TODO: Change card colour based on its colours + // TODO: Not for hand, but cards on board need flight, etc. + // Draw the deck shape let shape = new Shape({ x: gameData.position[entity][0], @@ -179,6 +182,163 @@ function drawCardInHand(entity){ }); shape.draw(); + drawCardDetails(entity); + +} + +// The draw all the card data, name, colour, etc. +function drawCardDetails(entity){ + + console.log(gameData.cardData[entity]); + drawCardImage(entity); // TODO: Use a sprite per card, not just temp. + drawCardText(entity); + /* + this.printColourRequirements(entity); + this.printCardPassives(entity); + */ + +} + +function drawCardImage(entity){ + + let positionX = gameData.position[entity][0]; + let positionY = gameData.position[entity][1]; + let width = gameData.size[entity][0]; + let height = gameData.size[entity][1]; + + // Create the clipping shape + let cardImageContainer = new Shape({ + shape: 'unit', + x: positionX+height/3, + y: positionY+width/2, + width: width*.9, + height: height*.9 + }); + // Save canvas drawing, start the clip + cardImageContainer.startClip(); + + // Print the image to canvas, within the clipping mask + positionX = gameData.position[entity][0]; + positionY = gameData.position[entity][1]; + width = gameData.size[entity][0]; + height = gameData.size[entity][1]; + // Draw the image into the clipping mask + // image, dx,dy,dw,dh + // image, sx,sy, sw,sh,dx,dy,dw,dh + // TODO: give cards/cardData a sprite position and use it [0,0], [1,0], [1,4], etc... + let spriteSheetX = 80;//*cardSprite[entity][0]; + let spriteSheetY = 120;//*cardSprite[entity][1]; + ctx.drawImage(cardArt, spriteSheetX,spriteSheetY, 80,120,positionX,positionY,width,height); + + // Restore the canvas draw post clip applied, to get everything else back too + cardImageContainer.endClip(); + +} + +function drawCardText(entity){ + + let positionX = gameData.position[entity][0]; + let positionY = gameData.position[entity][1]; + let width = gameData.size[entity][0]; + let height = gameData.size[entity][1]; + + // Calculate the fontsize for the card at different 'zooms'/sizes + let fontSize = width/cardWidth*8; // 8pt. 10 = baseFontSize of 10pt + //ctx.font = "bold "+fontSize+"pt Arial"; + let fillStyle = '#000'; + let strokeStyle = '#FFF'; + let strokeSize = fontSize/12; + + // TODO: + // 5px on regular 80px = 80/16, so width/16 = the same spacing. Probbaly just another + // function to calc the spacings like cardSize/actualSizeOfSpace (80/5) = 16, then. sizeOfThisCard/16 = RETURN + // This is fow the positionX + Xs as the Xs will not be that size if the card size is smaller/bigger + // so TODO gotta make it scaled % wise with the 80/16 I wrote above + + // NAME + printText(gameData.cardData[entity]['name'] + , positionX + 5 + 10 // + 5 (spacing for cost) + 10 for more spacing + , positionY + 10 + 5 // + 10pt + 5 as it's the spacing I actually want + , 'left', 'alphabetic', 'normal', 'normal', fontSize, 'Arial', fillStyle, strokeStyle, strokeSize, false + ); + + // COST + printText(gameData.cardData[entity]['cost'] + , positionX + 5 + , positionY + 10 + 5 // + 10pt + 5 as it's the spacing I actually want + , 'left', 'alphabetic', 'normal', 'normal', fontSize, 'Arial', fillStyle, strokeStyle, strokeSize, false + ); + + + // TYPE + printText( + CLASS[gameData.cardData[entity]['type']] + , positionX + 5 + , positionY + width // To be slightly over bottom of image (which uses width to position) + , 'left', 'alphabetic', 'normal', 'normal', fontSize, 'Arial', fillStyle, strokeStyle, strokeSize, false + ); + + // CLASS(ES) + let classes = ''; + // Loop the classes, and add each of them to the card + for(let i = 0; i < gameData.cardData[entity]['class'].length; i++){ + // Add a comma to seperate if it's not the first class + if(i > 0){ classes += ', '; } + // Add the class name to the list to print + classes += CLASS[gameData.cardData[entity]['class'][i]]; + } + + printText( + classes + , positionX + 5 + 5 + ctx.measureText(CLASS[gameData.cardData[entity]['type']]).width // + another 5 and width of type for spacing + , positionY + width // To be slightly over bottom of image (which uses width to position) + , 'left', 'alphabetic', 'normal', 'normal', fontSize, 'Arial', fillStyle, strokeStyle, strokeSize, false + ); + + // EFFECT(S) + // TODO: Split the text onto lines based on character count (but not splitting words) so they fit into the + // bounds of the card element + let effects = ''; + // Loop the classes, and add each of them to the card + for(let i = 0; i < gameData.cardData[entity]['effect'].length; i++){ + // Split effects with an additonal break (any more than 1st effect) + if(i > 0){ classes += '\n'; } + // Add the class name to the list to print + effects += gameData.cardData[entity]['effect'][i]; + } + printText( + effects + , positionX + 5 + , positionY + width + 10 // To be beneath image, and type + classes + , 'left', 'alphabetic', 'normal', 'normal', fontSize, 'Arial', fillStyle, strokeStyle, strokeSize, false + ); + + // ATTACK + printText(gameData.cardData[entity]['attack'] + , positionX + width/2 - ctx.measureText(gameData.cardData[entity]['attack']).width/2 // Should be centred + , positionY + 10 + (height - 10) // + 10pt + 5 as it's the spacing I actually want + , 'left', 'alphabetic', 'normal', 'normal', fontSize, 'Arial', fillStyle, strokeStyle, strokeSize, false + ); + + // Reset font for other draws + // TODO: Probably just use a save/restore for the font draws in here + ctx.font = "10pt Arial"; + +} + + +function drawCardBack(entity){ + ctx.drawImage( + cardBackArt + ,0 // X Position From in Spritesheet + ,0 // Y Position From in Spritesheet + ,80 // Width of image selection from Spritesheet + ,120 // Height of image selection from Spritesheet + ,gameData.position[entity][0] // X + ,gameData.position[entity][1] // Y + ,gameData.size[entity][0] // Width + ,gameData.size[entity][1] // Height + ); } @@ -212,15 +372,18 @@ function drawFakeHand(){ i = opponentHandItem; // Believe value should just be the count of current cardCount.hand for(i; i < itemListLength; i++){ - let shape = new Shape({ - x: canvas.width/2 - (cardWidth * (itemListLength - (i+1)) - (cardMargin * (i+1))), - y: 20, - width: cardWidth, - height: cardHeight, - fillStyle: '#EEE', - strokeStyle: '#AAA', - }); - shape.draw(); + ctx.drawImage( + cardBackArt + ,0 // X Position From in Spritesheet + ,0 // Y Position From in Spritesheet + ,80 // Width of image selection from Spritesheet + ,120 // Height of image selection from Spritesheet + ,canvas.width/2 - (cardWidth * (itemListLength - (i+1)) - (cardMargin * (i+1))) +// X + ,20 // Y + ,cardWidth // Width + ,cardHeight // Height + ); } break; diff --git a/public/js/canvas/helpers.js b/public/js/canvas/helpers.js index ac161c6..3ef55dc 100644 --- a/public/js/canvas/helpers.js +++ b/public/js/canvas/helpers.js @@ -1,4 +1,4 @@ -function printText(text, positionX, positionY, alignment = 'left', baseline = 'alphabetic', style = 'normal', weight = 'normal', size = '10', font = 'Arial', colour = '#000'){ +function printText(text, positionX, positionY, alignment = 'left', baseline = 'alphabetic', style = 'normal', weight = 'normal', size = '10', font = 'Arial', colour = '#000', strokeStyle = false, lineWidth = false, strokeOnly = false){ // Save the styling, and content already on the canvas ctx.save(); @@ -11,9 +11,20 @@ function printText(text, positionX, positionY, alignment = 'left', baseline = 'a ctx.font = style+' '+weight+' '+size+'pt'+' '+font; //ctx.font-style = fontStyle; // normal, italic, oblique ctx.fillStyle = colour; + + if(strokeStyle && lineWidth){ + // Set the stroke styling + ctx.strokeStyle = strokeStyle; + ctx.lineWidth = lineWidth; + + // Add the stroke (first, before fill) as it looks better + ctx.strokeText(text, positionX, positionY); + } - // Actually add the text - ctx.fillText(text, positionX, positionY); + if(!strokeOnly){ + // Actually add the text + ctx.fillText(text, positionX, positionY); + } // Restore the prior existing canvas content ctx.restore(); diff --git a/public/js/global.js b/public/js/global.js index c70bd98..a0e00b0 100644 --- a/public/js/global.js +++ b/public/js/global.js @@ -1,14 +1,28 @@ +const socket = io({autoConnect: false}); +const canvas = document.getElementById('canvas');; + const cardWidth = 80; const cardHeight = 120; const cardArt = new Image(); const cardBackArt = new Image(); +cardArt.src = 'images/cardArt.jpg'; +cardBackArt.src = 'images/cardBack.jpg'; const COLOUR = { 'white':{'id': 1, 'name':'White','colour':'#EEE'}, 'blue':{'id':2, 'name':'Blue','colour':'#0033EE'}, 'red':{'id':3, 'name':'Red','colour':'#ED344A'}, }; +const CLASS = { + 1: 'Goblin' + ,2: 'Human' +}; +const TYPE = { + 1: 'Unit' + ,2: 'Spell' + ,3: 'Token' +}; // To disable drawing each time something changes let drawEachEvent = true; // For disabling draw each time and only occuring where I want to test diff --git a/public/js/main.js b/public/js/main.js index 8a84e82..bd3324b 100644 --- a/public/js/main.js +++ b/public/js/main.js @@ -1,11 +1,3 @@ -const socket = io({autoConnect: false}); -const canvas = document.getElementById('canvas');; - -let room; -let hand = []; -let turn; -let playerName; - // Canvas Initialisation init(); function init() {