From 2a3250d932aba353360a4e2e431630b8f573ae3d Mon Sep 17 00:00:00 2001 From: Nathan Date: Tue, 15 Oct 2024 21:57:35 +0100 Subject: [PATCH] Add cardFace/Sprite + print card front/back images Added ECS elements for cardFace and cardSprite Added spritesheet print into a clipping mask for cards Added spritesheet print for cardBacks Added a 'flip' function --- public/board.js | 119 ++++++++++++++++++++++++++++++------- public/images/cardArt.jpg | Bin 0 -> 6920 bytes public/images/cardBack.jpg | Bin 0 -> 1854 bytes public/shapes.js | 59 ++++++++++++++++++ 4 files changed, 158 insertions(+), 20 deletions(-) create mode 100644 public/images/cardArt.jpg create mode 100644 public/images/cardBack.jpg diff --git a/public/board.js b/public/board.js index 8a237f9..a1383b6 100644 --- a/public/board.js +++ b/public/board.js @@ -5,8 +5,8 @@ const canvasTop = canvas.offsetTop + canvas.clientTop; const cardWidth = 80; const cardHeight = 120; -const cards = new Image(); -const back = new Image(); +const cardArt = new Image(); +const cardBackArt = new Image(); // Counters to keep track of players, and boardElements, may be changed in future // But once game starts, will be const anyway, so shouldn't need passing @@ -26,6 +26,8 @@ let size = {}; let cardStatus = {}; // tapped, attacking, inspected, untargettable (TODO:maybe used this instead of inEvent later) let player = {}; let listPosition = {}; +let cardFace = {}; +let cardSprite = {}; let inEvent = null; // To disable drawing each time something changes @@ -43,8 +45,8 @@ class Board{ console.log('initBoard'); ctx.font = "12px Arial"; canvas.style.backgroundColor = 'rgb(143 153 150)'; - cards.src = 'images/deck.svg'; - back.src = 'images/uno.svg'; + cardArt.src = 'images/cardArt.jpg'; + cardBackArt.src = 'images/cardBack.jpg'; ctx.fillStyle = '#000'; } @@ -164,10 +166,16 @@ class Board{ }); shape.draw(); - if(boardElement[itemKey] != 'realDeck'){ // TODO: isset, or differ between types - this.printCardImage(itemKey); + // Draw the card face-up + if(this.isFaceUp(itemKey)){ + this.addCardImage(itemKey); this.printCardDetails(itemKey); - }else{ + } + if(!this.isFaceUp(itemKey)){ + this.addCardBack(itemKey); + } + // If it's the deck, draw the circle surrounding it + if(boardElement[itemKey] == 'realDeck'){ // TODO: For realDeck only atm, also janked in. Seperate this... let counterx= positionX; let countery= positionY; @@ -194,33 +202,75 @@ class Board{ ctx.fillStyle = '#000'; ctx.fillText(deckLength, textx, texty); } - - + } + isFaceUp(itemKey){ + if(cardFace[itemKey] == 1){ + return true; + } + return false; + } + flipCard(itemKey){ + if(cardFace[itemKey] == 1){ + cardFace[itemKey] = 0; + }else{ + cardFace[itemKey] = 1; + } + // TODO:Activate any flip effects, etc. } printCardImage(itemKey){ - let name = itemKey; // Not needed really anymore, but keeping for now let positionX = position[itemKey][0]; let positionY = position[itemKey][1]; let width = size[itemKey][0]; let height = size[itemKey][1]; - let fill = '#BBB'; - let shape = 'semi'; // Will be decided based on cardData.something? (for unit, spell, etc) + // Draw the image into the clipping mask + // image, dx,dy,dw,dh + // image, sx,sy, sw,sh,dx,dy,dw,dh + let spriteSheetX = 80*cardSprite[itemKey][0]; + let spriteSheetY = 120*cardSprite[itemKey][1]; + ctx.drawImage(cardArt, spriteSheetX,spriteSheetY, 80,120,positionX,positionY,width,height); + } + addCardImage(itemKey){ + + let positionX = position[itemKey][0]; + let positionY = position[itemKey][1]; + let width = size[itemKey][0]; + let height = size[itemKey][1]; - // Add 'image' shape, will need to blitz sprite here in the future (based on cardData.id) + // Create the clipping shape let cardImageContainer = new Shape({ - shape: 'semi', + shape: 'unit', name: 'cardImageContainer_'+name, x: positionX+height/3, y: positionY+width/2, width: width*.9, - height: height*.9, - fillStyle: fill + height: height*.9 }); - cardImageContainer.draw(); + // Save canvas drawing, start the clip + cardImageContainer.startClip(); + + // Print the image to canvas, within the clipping mask + this.printCardImage(itemKey); - // Draw the actual image too + // Restore the canvas draw post clip applied, to get everything else back too + cardImageContainer.endClip(); + } + addCardBack(itemKey){ + let positionX = position[itemKey][0]; + let positionY = position[itemKey][1]; + let width = size[itemKey][0]; + let height = size[itemKey][1]; + // Print the sleeve image to cardPosition + this.printCardBack(itemKey); + } + printCardBack(itemKey){ + let positionX = position[itemKey][0]; + let positionY = position[itemKey][1]; + let width = size[itemKey][0]; + let height = size[itemKey][1]; + // TODO: CardBack/Sleeves as spritesheet like cardArt + ctx.drawImage(cardBackArt, 0,0, 80,120,positionX,positionY,width,height); } printCardDetails(itemKey){ let name = itemKey; // Not needed really anymore, but keeping for now @@ -425,8 +475,10 @@ class Board{ alert('Hand full '+elementLength+'/'+maxHandSize); return false; } + let card = this.getItemKey('deck', 1, playerId); // Move from players deck to hand, from position 1 (bottom deck) this.addFromBoardElement(playerId, 1, 'deck', 'hand', null, null); + this.flipCard(card); } } @@ -759,7 +811,11 @@ for(let currentPlayer = 0; currentPlayer <= players-1; currentPlayer++){ } // Draw the graphics of the board/game -board.drawBoard(true); +// Wait for the cardArt to load on first load +// Otherwise it'll be boxes, and art will flash in on first click event triggered +cardArt.onload = function(){ + board.drawBoard(true); +}; // Right Click, Rightclick, rightclick, right click @@ -961,6 +1017,7 @@ function createDecks(){ // In future want to remove, and add isset checks for non-used data cardStatus[itemCount] = null; listPosition[itemCount] = null; + cardFace[itemCount] = 0; // Deck is facedown, as there's no cardArt itemCount++; } @@ -994,6 +1051,26 @@ function createDeckList(playerId){ player[itemCount] = playerId; // Set the position in the deck (as was added), will be shuffled on game start listPosition[itemCount] = deckItem+1; + cardFace[itemCount] = 0; // Start with all cards face down + cardSprite[itemCount] = [0,0]; + // Temp sprite set based on colour TODO: Change to set correct sprite from DB + console.log(cardData[itemCount].colour); + switch (cardData[itemCount].colour){ + case 0: // White + cardSprite[itemCount] = [0,0]; + break; + case 1: // Blue + cardSprite[itemCount] = [0,1]; + break; + case 2: // Red + cardSprite[itemCount] = [1,0]; + break; + case 3: // Green + cardSprite[itemCount] = [1,1]; + break; + default: + break; + } // Increment the itemCount to prevent overwriting stuff itemCount++; @@ -1220,13 +1297,15 @@ function printECSData(items){ for(let item = 0; item < items.length; item++){ let itemKey = items[item]; console.log( + 'itemId: '+itemKey+"\n"+ 'boardElement: '+boardElement[itemKey]+"\n"+ 'cardData: '+cardData[itemKey]+"\n"+ 'position: '+position[itemKey]+"\n"+ 'size: '+size[itemKey]+"\n"+ 'cardStatus: '+cardStatus[itemKey]+"\n"+ 'player: '+player[itemKey]+"\n"+ - 'listPosition: '+listPosition[itemKey] + 'listPosition: '+listPosition[itemKey]+"\n"+ + 'cardFace: '+cardFace[itemKey] ); } } diff --git a/public/images/cardArt.jpg b/public/images/cardArt.jpg new file mode 100644 index 0000000000000000000000000000000000000000..490d648deec27f93e292992132d51ba19c641d8b GIT binary patch literal 6920 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 literal 0 HcmV?d00001 diff --git a/public/shapes.js b/public/shapes.js index d8db346..8313964 100644 --- a/public/shapes.js +++ b/public/shapes.js @@ -64,8 +64,67 @@ class Shape extends Path2D{ }else if (this.shape == 'rectangle'){ context.strokeRect(this.x, this.y, this.width, this.height); } + else if (this.shape == 'unit'){ + context.beginPath(); + context.arc(this.x, this.y, this.width/2, Math.PI, 0); + + // Start at bottom left of the semi + context.moveTo(this.x-this.width/2, this.y); + // Draw accross to bottom right of semi + context.lineTo(this.x+this.width/2, this.y); + // Draw down to the desired height + context.lineTo(this.x+this.width/2, this.y+this.height/3); + // Draw accross to that height, but aligned to left of semi + context.lineTo(this.x-this.width/2, this.y+this.height/3); + + context.stroke(); + context.closePath(); + } context.strokeStyle = defaultFillStyle; } } + startClip(shape = null){ + // https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/clip#creating_a_complex_clipping_region + if(this.shape == 'circle'){ + // X,Y,Radius, start, end + context.beginPath(); + context.arc(this.x, this.y, this.width/2, 0, 2 * Math.PI); + context.fill(); + context.closePath(); + }else if(this.shape == 'semi'){ + context.beginPath(); + context.arc(this.x, this.y, this.width/2, Math.PI, 0); + context.fill(); + context.closePath(); + }else if (this.shape == 'rectangle'){ + context.fillRect(this.x, this.y, this.width, this.height); + } + // This is one of the shapes for the card images to sit it + // TODO: Will be: unit,token,spell, etc. ALSO will have each shape for UI elements too + else if (this.shape == 'unit'){ + + context.beginPath(); + context.arc(this.x, this.y, this.width/2, Math.PI, 0); + + // Start at bottom left of the semi + context.moveTo(this.x-this.width/2, this.y); + // Draw accross to bottom right of semi + context.lineTo(this.x+this.width/2, this.y); + // Draw down to the desired height + context.lineTo(this.x+this.width/2, this.y+this.height/3); + // Draw accross to that height, but aligned to left of semi + context.lineTo(this.x-this.width/2, this.y+this.height/3); + + context.fill(); + context.closePath(); + + } + + ctx.save(); // Save the canvas draw before the clip is applied + context.clip(); + } + endClip(){ + ctx.restore(); // Restore the canvas draw post clip applied, to get everything else back too + } }