const ctx = canvas.getContext('2d'); const canvasLeft = canvas.offsetLeft + canvas.clientLeft; const canvasTop = canvas.offsetTop + canvas.clientTop; const cardWidth = 80; const cardHeight = 120; const cards = new Image(); const back = new Image(); let clickableItems = []; // Make all clickableItems sit in the same clickableItems array // Not needed in a child, as loops will be on arrays below clickableItems['board'] = []; clickableItems['hand'] = []; clickableItems['opponentHand'] = []; // 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 let players = 2; // Player, Opponent for now, but will be up to 6 players for 5v1 boss raids? let elements = ['deck','board','hand','mana','shield']; let elementsSizes = {}; // May need to have the base XY WH of board, hand, etc. stored for loop draw // Array of items, the 'Entity Manager' as such let item = []; let itemCount = 0; // Component 1: Where on the board, hand, deck, mana, shield, etc. // send back item, itemCount and individual comp. from server? let boardElement = {}; let cardData = {}; let position = {}; let size = {}; //let shape = {}; let cardStatus = {}; // tapped, attacking, inspected, untargettable let player = {}; let listPosition = {}; let playerHand = []; let opponentHand = []; let playerBoard = []; let opponentBoard = []; let playerDeck = []; let opponentDeck = []; let playerShield = []; let opponentShield = []; let playerMana = []; let opponentManaZone = []; // To disable drawing each time something changes let drawEachEvent = true; let deckCount = 60; let deckCountOpponent = 60; let cardsInOpponentsHand = 0; const maxHandSize = 4; const maxBoardSize = 3; const maxShield = 4; let inspectCard = null; let attackingCard = null; let gameWin = 0; // Gonna need lots of refactoring, and sorting class Board{ constructor(){ console.log('initBoard'); ctx.font = "12px Arial"; canvas.style.backgroundColor = 'rgb(143 153 150)'; cards.src = 'images/deck.svg'; back.src = 'images/uno.svg'; ctx.fillStyle = '#000'; } drawBoard(force = false){ if(drawEachEvent == false && force == false){ return 0; } // Reset board ctx.clearRect(0, 0, canvas.width, canvas.height); // Room Name ctx.fillText(name, 0, 10); this.drawCardsOnBoard(); this.drawCardsOnBoardOpponent(); this.drawDeck(); this.drawDeckOpponent(); this.drawShield(); this.drawShieldOpponent(); this.drawMana(); this.drawPlayerNames('Nathan', 'Evil Nathan'); this.drawCardsECS(); // Atop most everything atm for testing if(gameWin){ this.drawWin(); } this.drawInspectedCard(); } drawWin(){ var winBoard = new Shape({ name: name, x: 0, y: canvas.height/2 - (canvas.height/4)/2, width: canvas.width, height: canvas.height/4, fillStyle: '#CCC', strokeStyle: '#00EEAA' }); winBoard.draw(); ctx.fillStyle = '#000'; ctx.font = "bold 50pt Arial"; ctx.fillText('WINNER', 200, 300); ctx.font = "10pt Arial"; } drawPlayerNames(playerName, opponentName = false){ // Player Name ctx.fillText(playerName, 50, canvas.height - 50); // Opponent's Name if(!opponentName){ // Just clear the name }else{ ctx.fillText(opponentName, canvas.width - (ctx.measureText(opponentName).width + 50), 50); } } drawCardsECS(){ // ALL NON DECK CARDS DO BE DRAWN IN SAME LOOP (ideally) // Loop all items for(let itemKey = 0; itemKey < item.length; itemKey++){ // Loop each element, and player for(let elementCount in elements){ // Don't draw deck TODO:/gy/void // TODO: Unless inspecting let element = elements[elementCount]; if(element == 'deck'){ continue; } // Draw Elements // Loop each item left, and draw if element is currently looped. board,mana,etc. if(itemKey in boardElement && boardElement[itemKey] == element){ if(boardElement[itemKey] == 'hand' && player[itemKey] == 0){ console.log('PLAYER HAND'); } // Get the player the item belongs to let itemPlayer = player[itemKey]; console.log('Element: '+element+', Player: '+itemPlayer); calculateItemSizePosition(itemKey); this.printCardToCanvas(itemKey); } } } } printCardToCanvas(itemKey){ // If the itemKey has cardData, position, size, and boardElement we can draw it // TODO: Add a check for error handling // Check status, and change border colour for display (for tapped atm) let border = null; if(cardStatus[itemKey] == 'tapped'){border = '#E0BC00';} // Set the card 'cardboard' colour based on the card colour type let colourId = cardData[itemKey].colour; let fill = null; if(colourId == 0){ fill = '#EEE'; } else if(colourId == 1){ fill = '#0033EE'; } 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]; // Draw the card shape itself let shape = new Shape({ name: name, x: positionX, y: positionY, width: width, height: height, fillStyle: fill, strokeStyle: border }); shape.draw(); this.printCardImage(itemKey); this.printCardDetails(itemKey); } 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) // Add 'image' shape, will need to blitz sprite here in the future (based on cardData.id) let cardImageContainer = new Shape({ shape: 'semi', name: 'cardImageContainer_'+name, x: positionX+height/3, y: positionY+width/2, width: width*.9, height: height*.9, fillStyle: fill }); cardImageContainer.draw(); // Draw the actual image too } printCardDetails(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]; // Add card name let fontSize = width/cardWidth*10; // 10 = baseFontSize of 10pt ctx.font = "bold "+fontSize+"pt Arial"; ctx.fillStyle = '#000'; ctx.fillText( cardData[itemKey]['name'] , positionX + (ctx.measureText(cardData[itemKey]['name']/2).width) - width/4 , positionY+height*.25 ); // Add card type ctx.fillText( cardData[itemKey]['type'] , positionX + (ctx.measureText(cardData[itemKey]['type']/2).width) - width/4 , positionY+height*.7 ); // Add text/effect area if(cardData[itemKey]['effect'] !== null){ ctx.fillText( cardData[itemKey]['effect'] , positionX + (ctx.measureText(cardData[itemKey]['effect']/2).width) - width/4 , positionY+height*.8 ); } // Attack ctx.fillText( cardData[itemKey]['atk'] , positionX + (ctx.measureText(cardData[itemKey]['atk']).width) , positionY+height*.95 ); // Add cost ctx.fillText( cardData[itemKey]['cost'] , positionX + (ctx.measureText(cardData[itemKey]['cost']).width) , positionY+height*.1 ); // Unbold font for other draws ctx.font = "10pt Arial"; } // Draw Invidual Cards, called by other deck stuff // Might be put into a card class, makes sense, eh. drawCard(array, arrayKey, name, positionX, positionY, width, height, fill, border){ // Card Colour //console.log('drawCard card: '+JSON.stringify(array[arrayKey])); let colourId = array[arrayKey].colour; if(colourId == 0){ fill = '#EEE' } else if(colourId == 1){ fill = '#0033EE' } if(array[arrayKey].tapped){ border = '#E0BC00'; console.log('drawCard tapped'); } var cardClickable = new Shape({ name: name, x: positionX, y: positionY, width: width, height: height, fillStyle: fill, strokeStyle: border }); array[arrayKey]['clickable'] = cardClickable; array[arrayKey]['clickable'].draw(); // Add image // half circle for unit Set start angle to 0 and end angle to Math.PI. // Ellipse for token (near full size) // Octagon for spell let cardImageContainer = new Shape({ shape: 'semi', name: 'cardImageContainer_'+name, x: positionX+height/3, y: positionY+width/2, width: width*.9, height: height*.9, fillStyle: "#BBB" }); cardImageContainer.draw(); // Add card name let fontSize = width/cardWidth*10; // 10 = baseFontSize of 10pt ctx.font = "bold "+fontSize+"pt Arial"; ctx.fillStyle = '#000'; ctx.fillText( array[arrayKey]['name'] , positionX + (ctx.measureText(array[arrayKey]['name']/2).width) - width/4 , positionY+height*.25 ); // Add card type ctx.fillText( array[arrayKey]['type'] , positionX + (ctx.measureText(array[arrayKey]['type']/2).width) - width/4 , positionY+height*.7 ); // Add text/effect area if(array[arrayKey]['effect'] !== null){ ctx.fillText( array[arrayKey]['effect'] , positionX + (ctx.measureText(array[arrayKey]['effect']/2).width) - width/4 , positionY+height*.8 ); } // Attack ctx.fillText( array[arrayKey]['atk'] , positionX + (ctx.measureText(array[arrayKey]['atk']).width) , positionY+height*.95 ); // Add cost ctx.fillText( array[arrayKey]['cost'] , positionX + (ctx.measureText(array[arrayKey]['cost']).width) , positionY+height*.1 ); // Unbold font for other draws ctx.font = "10pt Arial"; } drawDeck(){ // Deck clickableItems['deckSprite'] = new Shape({ name: 'deck', x: canvas.width-cardWidth*1.5-40, y: canvas.height-cardHeight*1.5-60, width: cardWidth*1.5, height: cardHeight*1.5, fillStyle: "#0000FF" }); //ctx.fillRect(canvas.width-cardWidth/2-60, canvas.height/2-cardHeight/4, cardWidth/2, cardHeight/2); clickableItems['deckSprite'].draw(); let deckCounterSprite = new Shape({ shape: 'circle', name: 'deckCounter', x: canvas.width-cardWidth*.6, y: canvas.height-cardHeight*.6, width: cardWidth*.375, height: cardHeight*.375, fillStyle: "#FFF" }); deckCounterSprite.draw(); // TODO: Center in the circle ctx.fillStyle = '#000'; ctx.fillText(playerDeck.length, canvas.width-cardWidth*.6 - (ctx.measureText(playerDeck.length).width) + 7, canvas.height-cardHeight*.6 + 5); } drawDeckOpponent(){ // Opponent's Deck clickableItems['deckOpponentSprite'] = new Shape({ name: 'deckOpponent', x: 40, y: 60, width: cardWidth*1.5, height: cardHeight*1.5, fillStyle: "#FF0000" }); clickableItems['deckOpponentSprite'].draw(); let deckCounterOpponentSprite = new Shape({ shape: 'circle', name: 'deckCounterOpponent', x: cardWidth*1.5+(cardWidth*.375), y: cardHeight*1.5+(cardHeight*.375), width: cardWidth*.375, height: cardHeight*.375, fillStyle: "#FFF" }); deckCounterOpponentSprite.draw(); ctx.fillStyle = '#000'; // TODO: Center in the circle ctx.fillText(opponentDeck.length, cardWidth*1.5 + (ctx.measureText(opponentDeck.length).width) + 10, cardHeight*1.9); } addFromBoardElement(playerFrom, fromPosition, elementFrom, elementTo, toPosition=null, playerTo=null){ if(playerTo == null){ playerTo = playerFrom; } // Move itemKey fromPosition in elementFrom to toPosition in elementTo // Can also switch item between players // Loop all items, get the item with boardElement elementFrom and player playerFrom for(let itemKey = 0; itemKey < item.length; itemKey++){ // Get the item from the element if(itemKey in boardElement && boardElement[itemKey] == elementFrom){ // Check if item belongs to playerFrom if(itemKey in player && player[itemKey] == playerFrom){ // Get item based on fromPosition listPosition if(listPosition[itemKey] == fromPosition){ // Check if a toPostion supplied (likely won't be, dunno if I'll do this) if(toPosition == null){ // Get the new position of item based on new boardElement toPosition = getCurrentPositionAndLength(elementTo, playerTo)[0]+1 //console.log(toPosition); } //console.log('itemKey: '+itemKey+' fromPosition: '+fromPosition+' elementFrom: '+elementFrom+' toPosition: '+toPosition+' playerFrom: '+playerFrom+' playerTo: '+playerTo); listPosition[itemKey] = toPosition; // Move from elementFrom to elementTo //console.log('elementTo: '+elementTo); //console.log(boardElement[itemKey]); boardElement[itemKey] = elementTo; //console.log(itemKey); //console.log(boardElement[itemKey]); // Move down(0) the positions of elementFrom, from fromPosition for player this.moveElementPositions(0, elementFrom, fromPosition, playerFrom); this.drawBoard(); return 1; // Got a loop that calls a loop, and checks the new values atm, so this keeps counting down } } } } } moveElementPositions(direction, elementFrom, fromPosition, playerFrom){ // Move the positions directionally 1 for elementFrom from fromPosition //console.log(listPosition); //console.log('Direction: '+direction+' elementFrom: '+elementFrom+' fromPosition: '+fromPosition+' player: '+playerId); // Loop the elementFrom, and move positions for anything after // item taken from position 34, 35..60 need to be moved down to 34..59 // For each item for(let itemKey = 0; itemKey < item.length; itemKey++){ // If boardElement is elementFrom if(itemKey in boardElement && boardElement[itemKey] == elementFrom){ // And from the playerFrom (id) if(itemKey in player && player[itemKey] == playerFrom){ //console.log(elementFrom); //console.log(boardElement[itemKey]); //console.log(listPosition[itemKey]); //console.log(itemKey); if(listPosition[itemKey] > fromPosition){ //console.log('position: '+listPosition[itemKey]+' fromPosition: '+fromPosition); // Move items up, i.e. added to top of deck if(direction){ listPosition[itemKey]++; } // Move items down, i.e. taken from top of deck listPosition[itemKey]--; } } } } //console.log(listPosition); } // Draw a card, traditional TCG drawACard(cardsToDraw = 1){ for(let draw = 0; draw < cardsToDraw; draw++){ // Check there's space in hand // TODO: Normalise this for all element/player combos let elementLength = getCurrentPositionAndLength('hand', 0)[1]; if(elementLength >= maxHandSize){ alert('Hand full '+elementLength+'/'+maxHandSize); return 0; } // Move from player0, position 0 (top) of deck, to hand this.addFromBoardElement(0, 0, 'deck', 'hand', null, null); } } drawACardOpponent(cardsToDraw = 1){ for(let draw = 0; draw < cardsToDraw; draw++){ // Move from player1, position 0 (top) of deck, to hand // Check there's space in hand // TODO: Normalise this for all element/player combos let elementLength = getCurrentPositionAndLength('hand', 1)[1]; if(elementLength >= maxHandSize){ alert('Hand full '+elementLength+'/'+maxHandSize); return 0; } this.addFromBoardElement(1, 0, 'deck', 'hand', null, null); } } drawCardsOnBoard(){ // DUPE OF DRAW PLAYER HAND FOR NOW!!! for (let i = 0; i < playerBoard.length; i++) { let name = 'cardOnBoard_'+(i+1); let cardPadding = 10; let fill = '#'+i+i+'CC00'; // TODO: fix positionX, actually have some maffs let positionX = canvas.width/2 - (cardWidth * (playerBoard.length - (i+1)) - (cardPadding * (i+1))); let positionY = canvas.height - cardHeight-30-(cardHeight); let width = cardWidth; let height = cardHeight; let border = false; if(attackingCard !== null && playerBoard[i].name == attackingCard[0].name){ border = '#FF0000'; } this.drawCard(playerBoard, i, name, positionX, positionY, width, height, fill, border); } } drawCardsOnBoardOpponent(){ // OLD, being rewritten if(true){ for (let i = 0; i < opponentBoard.length; i++) { let name = 'cardOnBoardOpponent_'+(i+1); let cardPadding = 10; let fill = '#'+i+i+'AA00'; // TODO: fix positionX, actually have some maffs let positionX = canvas.width/2 - (cardWidth * (opponentBoard.length - (i+1)) - (cardPadding * (i+1))); let positionY = cardHeight + 30; let width = cardWidth; let height = cardHeight; this.drawCard(opponentBoard, i, name, positionX, positionY, width, height, fill); } } } // Currently only functionality in hand playCardToBoard(index){ // Get the card data let cardPlayed = playerHand[index]; let manaUsed = []; // Check if there's space on board to play // TODO: Check this in back-end if(playerBoard.length >= maxBoardSize){ alert('No space on board to play card. '+playerBoard.length+'/'+maxBoardSize); return 0; } if(cardPlayed.cost > playerMana.length){ alert('Not enough mana'); return 0; }else{ let canPlay = false; let needsMana = 1; let usedMana = 0; playerMana.forEach(function(manaCard, key){ if(cardPlayed.colour == manaCard.colour && manaCard.tapped == false && needsMana > usedMana){ console.log(manaCard); // Needs changing for multiple colour usage // 2 red, 1 red + 1 blue, etc. // Currently only gets one mana of the cards colour manaUsed.push(key); usedMana++; canPlay = true; } }); if(!canPlay){ alert('Mana conditions not met, right click hand unit to play as mana'); return 0; } } // Tap mana to be used manaUsed.forEach(function(cardKey, key){ playerMana[cardKey].tapped = true; }); console.log(playerMana); // Remove from hand playerHand.splice(index, 1); // Add to board playerBoard.push(cardPlayed); this.drawBoard(); } playCardToBoardFromDeckOpponent(){ if(opponentBoard.length >= maxBoardSize){ alert('No space on board to play card. '+opponentBoard.length+'/'+maxBoardSize); return 0; } // Loop items for opponent deck. boardElement = deck, and player = 1 for(let itemKey = 0; itemKey < item.length; itemKey++){ // Check if item is in deck // 'key' in 'object' if(itemKey in boardElement && boardElement[itemKey] == 'deck'){ // Check if item belongs to opponent if(itemKey in player && player[itemKey] == 1){ // Check list position for top of deck if(listPosition[itemKey] == 0){ // Set the new position (on board) listPosition[itemKey] = getCurrentPositionAndLength('board', 1)[0]+1 // Move from current item to board boardElement[itemKey] = 'board'; } else{ // Move all other items in deck down in position by 1 to get new 0 listPosition[itemKey]--; } } } } this.drawBoard(); } inspectOpponentBoard(index){ // Get the card data inspectCard = [opponentBoard, index]; this.drawBoard(); } drawInspectedCard(){ if(inspectCard != null){ let positionX = canvas.width/2 - cardWidth; let positionY = canvas.height/2 - cardHeight; let width = cardWidth*2; let height = cardHeight*2; this.drawCard(inspectCard[0], inspectCard[1], name, positionX, positionY, width, height, '#D1D100'); console.log('inspect'); } } // Selects the card that will be attacking // Stop other actions besides selecting opponent/opponent unit // Can cancel, will do later startAttack(index){ // Can probably combine attacking/inspect, and set another array element to 'attacking', 'inspecting', etc. attackingCard = [playerBoard[index], index]; this.drawBoard(); } // Do the attack makeAttack(index, array = null, name = null){ if(array == null){ array = opponentBoard; name = 'opponentBoard' } console.log(name); // If card attacked // Compare attackingCard and defendingCard let defendingCard = array[index]; // If hitting shield, don't calc combat damage if(name == 'opponentShield'){ // This should tap the card first, then after all shields // are tapped, THEN attacking destroys them if(array[index].tapped){ // Untap array[index].tapped = false; // Add to hand opponentHand.push(array[index]); // Remove from shield zone array.splice(index, 1); }else{ array[index].tapped = true; } playerBoard[attackingCard[1]].tapped = true; this.endAttack(); return 1; } if(defendingCard.atk <= attackingCard[0].atk){ array.splice(index, 1); // Need to push to grave, etc. here in future too } if(attackingCard[0].atk <= defendingCard.atk){ playerBoard.splice(attackingCard[1], 1); }else{ playerBoard[attackingCard[1]].tapped = true; } console.log('attacking'); this.endAttack(); // If player attacked // Compare life/remove life cards 5/10/15,1/2/3? } endAttack(){ attackingCard = null; if(opponentShield.length <= 0){ gameWin = 1; } this.drawBoard(); } // Like everything else, need to consolidate into one function that // can work for both players, and even more for 2v2 3v1 combats, etc. playShield(shieldsToPlay = 4){ for(let shieldNo = 0; shieldNo < shieldsToPlay; shieldNo++){ if(playerShield.length >= maxShield){ alert('Shield zone full '+playerShield.length+'/'+maxShield); return 0; } // Random card from deck, remove from deck, add to hand let cardToDraw = Math.floor(Math.random() * deckCount); let cardDrawn = playerDeck[cardToDraw]; // Remove from deck playerDeck.splice(cardToDraw, 1); // Add to shield zone playerShield.push(cardDrawn); this.drawBoard(); } } playShieldOpponent(shieldsToPlay = 4){ for(let shieldNo = 0; shieldNo < shieldsToPlay; shieldNo++){ if(opponentShield.length >= maxShield){ alert('Shield zone full '+opponentShield.length+'/'+maxShield); return 0; } // Random card from deck, remove from deck, add to hand let cardToDraw = Math.floor(Math.random() * deckCount); let cardDrawn = opponentDeck[cardToDraw]; // Remove from deck opponentDeck.splice(cardToDraw, 1); // Add to shield zone opponentShield.push(cardDrawn); this.drawBoard(); } } drawShield(){ for (let i = 0; i < playerShield.length; i++) { let name = 'playerShield_'+(i+1); let shieldMargin = 10; let fromX = 60; let fromY = 300; let fill = '#'+i+i+'0000'; let cWidth = cardWidth*.8; let cHeight = cardHeight*.8; let split = 0; if(i>=2){ split = 1; } // i%2 0 = 0, 1 = 1, 2 = 0, 3 = 1 to prevent margin from X/Y axis, and just between cards let positionX = (fromX+((i%2)*shieldMargin)) +(i%2*cWidth); let positionY = canvas.height-fromY+(split*cHeight+(shieldMargin*split)); let width = cWidth; let height = cHeight; this.drawCard(playerShield, i, name, positionX, positionY, width, height, fill); } } drawShieldOpponent(){ for (let i = 0; i < opponentShield.length; i++) { let name = 'opponentShield_'+(i+1); let shieldMargin = 10; let fromX = canvas.width-60; let fromY = 300; let fill = '#'+i+i+'0000'; let cWidth = cardWidth*.8; let cHeight = cardHeight*.8; let split = 0; if(i>=2){ split = 1; } // i%2 0 = 0, 1 = 1, 2 = 0, 3 = 1 to prevent margin from X/Y axis, and just between cards let positionX = (fromX+((i%2)*shieldMargin))+(i%2*cWidth)-(cWidth*2); let positionY = fromY+(split*cHeight+(shieldMargin*split))-(cHeight*2 + shieldMargin); let width = cWidth; let height = cHeight; //console.log('i: '+i+' X: '+positionX+' Y: '+positionY); this.drawCard(opponentShield, i, name, positionX, positionY, width, height, fill); } } playMana(index, fromDeck = 0){ let manaCard = null; if(fromDeck){ let cardToDraw = Math.floor(Math.random() * deckCount); manaCard = playerDeck[cardToDraw]; // Remove from deck playerDeck.splice(cardToDraw, 1); }else{ manaCard = playerHand[index]; playerHand.splice(index, 1); } playerMana.push(manaCard); this.drawBoard(); } drawMana(){ for (let i = 0; i < playerMana.length; i++) { let name = 'playerMana_'+(i+1); let manaMargin = 10; let fromX = 60; let fromY = 60; let fill = '#BBB'; let cWidth = cardWidth*.5; let cHeight = cardHeight*.5; let split = 0; // i%2 0 = 0, 1 = 1, 2 = 0, 3 = 1 to prevent margin from X/Y axis, and just between cards let positionX = (fromX+manaMargin)+(i*cWidth-manaMargin); let positionY = canvas.height-fromY; let width = cWidth; let height = cHeight; this.drawCard(playerMana, i, name, positionX, positionY, width, height, fill); } } } // TEMP!! createDeckList(playerDeck, deckCount, 0); createDeckList(opponentDeck, deckCountOpponent, 1); // Run board commands here for testing let board = new Board; //board.initBoard(); //shuffleDeck(0); //shuffleDeck(1); // TEMP: Play a card on opponents board (from their deck) board.playCardToBoardFromDeckOpponent(); board.playCardToBoardFromDeckOpponent(); //board.drawBoard(); board.playShield(4); board.playShieldOpponent(4); board.drawBoard(true); board.drawACard(3); canvas.addEventListener('contextmenu', function(event) { event.preventDefault(); let specialEvent = false; if(inspectCard !== null || attackingCard !== null || gameWin){ specialEvent = true; } var x = event.pageX - canvasLeft, y = event.pageY - canvasTop; // # PLAYER HAND playerHand.forEach(function(card, index){ let clickable = card.clickable; if(clickableCheck(x,y,clickable) && !specialEvent){ board.playMana(index); board.drawBoard(); } }); // Return false to prevent context opening: https://stackoverflow.com/a/4236294 return false; }, false); canvas.addEventListener('click', function(event) { console.log('EVENT LISTENER'); console.log(''); // specialEvent used to prevent eventTriggers if something specific // is being done, attack needs to be made, inspecting card. // Prevents user from doing other actions until completed or cancelled event let specialEvent = false; if(inspectCard !== null || attackingCard !== null || gameWin){ specialEvent = true; } var x = event.pageX - canvasLeft, y = event.pageY - canvasTop; // Check clicks against itemKey position+size // Will be the new way // TODO:Maybe write this into a function? If XY WH is hit return true, and the itemKey // then it can be re-used in contextclick, hover, etc without rewrite //console.log('X: '+x+' Y: '+y); for(let itemKey = 0; itemKey < item.length; itemKey++){ if(elements[itemKey] == 'deck'){ continue; } // Check the item has a size and position if(itemKey in size && itemKey in position){ // Compare the event XY position to the item if(clickableCheck(x,y,false,itemKey)){ cardStatus[itemKey] = 'tapped'; } } board.drawBoard(); } // Collision detection between clicked offset and clickableItems // https://stackoverflow.com/a/9880302 if(inspectCard !== null){ clickable = inspectCard[0][inspectCard[1]].clickable; if(clickableCheck(x,y,clickable)){ console.log('clicked inspect card'); }else{ console.log('not inspected card'); // Stop inspecting card if player clicks off it inspectCard = null; board.drawBoard(); } } // # PLAYER DECK clickable = clickableItems['deckSprite']; // Want to loop clickables ideally, and call a function // that's set to them for click, hover, etc. // TODO: potentially loop all clickables, and do a check on clickable.name to differ event handling per-item // For now this will be fine, as it functions if(clickableCheck(x,y,clickable) && !specialEvent){ board.drawACard(); } // # OPPONENT DECK clickable = clickableItems['deckOpponentSprite']; if(clickableCheck(x,y,clickable) && !specialEvent){ board.drawACardOpponent(); } // # PLAYER HAND playerHand.forEach(function(card, index){ let clickable = card.clickable; if(clickableCheck(x,y,clickable) && !specialEvent){ board.playCardToBoard(index); // This would actually fire off a socketIO doodad, that would then return // data, and redraw. But for now (UI test) // Add to board board.drawBoard(); } }); // # PLAYER BOARD playerBoard.forEach(function(card, index){ let clickable = card.clickable; if(clickableCheck(x,y,clickable)){ if(attackingCard !== null && card == attackingCard[0]){ board.endAttack(); } if(!specialEvent && card.tapped != true){ board.startAttack(index); } board.drawBoard(); } }); // # OPPONENT BOARD opponentBoard.forEach(function(card, index){ let clickable = card.clickable; if(clickableCheck(x,y,clickable)){ // Check if card if getting attacked if(attackingCard !== null){ board.makeAttack(index); } if(!specialEvent){ board.inspectOpponentBoard(index); } board.drawBoard(); } }); // # OPPONENT SHIELD opponentShield.forEach(function(card, index){ let clickable = card.clickable; if(clickableCheck(x,y,clickable)){ // Check if card if getting attacked if(attackingCard !== null){ board.makeAttack(index, opponentShield, 'opponentShield'); } board.drawBoard(); } }); }, false); function clickableCheck(x,y,clickable=false,itemKey=false){ // Temp solution to add the check while the old way also exists // simultaneously. It works, so that's nice if(clickable === false && itemKey !== false){ clickable = {}; console.log(clickable); console.log(itemKey); clickable.x = position[itemKey][0]; clickable.y = position[itemKey][1]; clickable.width = size[itemKey][0]; clickable.height = size[itemKey][1]; console.log(clickable); } // Debug Stuff let debug = false if(debug){ console.log(clickable.y+' <'); console.log(y+ '<') console.log(clickable.y+clickable.height); } if( y > clickable.y && y < clickable.y + clickable.height && x > clickable.x && x < clickable.x + clickable.width) { return true; } return false; } // TEMP: Create a deck of X different cards that can be drawn/played // for UI development, will be done on server and not shown to clients function createDeckList(deck, deckCount, playerId){ for(let i = 0; i < deckCount; i++){ // Randomise colour let colour = Math.floor(Math.random() * 2); let effect = Math.floor(Math.random() * 5); if(effect == 0){ effect = 'effect here'; } else{ effect = null } item.push(itemCount); boardElement[itemCount] = 'deck'; cardData[itemCount] = { 'name':'CardName '+(i+1) , 'cost':1 , 'atk':1 , 'def':1 , 'rarity': 'common' , 'effect':effect , 'type':'human' , 'colour':colour , 'tapped':false }; player[itemCount] = playerId; listPosition[itemCount] = i; // Previous iteration, kept to prevent errors for now deck.push(cardData[itemCount]); itemCount++; } } function shuffleDeck(playerId){ let tempDeck = []; for(let itemKey = 0; itemKey < item.length; itemKey++){ // Check if item is in deck // 'key' in 'object' if(itemKey in boardElement && boardElement[itemKey] == 'deck'){ // Check if item belongs to opponent if(itemKey in player && player[itemKey] == playerId){ // This will shuffle, but not from OG deck state. // Will need to get the listPosition and order by that first //console.log(itemKey); tempDeck.push(itemKey); } } } // Temporary shuffle until algo selected/written let id, shuffledPile, i; console.log(tempDeck.length); for (i = tempDeck.length - 1; i > 0; i--) { id = Math.floor(Math.random() * (i + 1)); //shuffledPile = tempDeck[i]; //tempDeck[i] = tempDeck[id]; //tempDeck[id] = shuffledPile; // Change the position within the deck listPosition[tempDeck[id]] = i; } } function untap(array){ console.log(array); array.forEach(function(card, key){ array[key].tapped = false; }); board.drawBoard(); } function untapAll(){ untap(playerMana); untap(playerBoard); untap(opponentShield); } function getCurrentPositionAndLength(elementName, playerId){ let highestListPosition = 0; let length = 0; // Loop all the items // Think making the for loop, and the if into something to be called that fires functions would be smart? for(let itemKey = 0; itemKey < item.length; itemKey++){ // Check the item is the correct boardElement // 'key' in 'object' if(itemKey in boardElement && boardElement[itemKey] == elementName){ // Check if item belongs to the player if(itemKey in player && player[itemKey] == playerId){ if(listPosition[itemKey]){ if(listPosition[itemKey] >= highestListPosition){ highestListPosition = listPosition[itemKey]; length++; } } } } } return [highestListPosition, length]; } function calculateItemSizePosition(itemKey){ // Calc position and size of the item // Used for drawing and interacting let itemPlayer = player[itemKey]; let itemElement = boardElement[itemKey]; let itemListPositionLength = getCurrentPositionAndLength(itemElement, itemPlayer); let itemListPositionNext = itemListPositionLength[0]; let itemListLength = itemListPositionLength[1]; let cardPadding = 10; let positionX = 0; let positionY = 0; let width = 0; let height = 0; let i = listPosition[itemKey]; console.log('cardName: '+cardData[itemKey].name+' listPosition/i: '+i); if(itemPlayer == 1 && itemElement == 'board'){ positionX = canvas.width/2 - (cardWidth * (itemListLength - i) - (cardPadding * i)); positionY = cardHeight + 30; width = cardWidth; height = cardHeight; } if(itemPlayer == 1 && itemElement == 'hand'){ positionX = canvas.width/2 - (cardWidth * (itemListLength - (i+1)) - (cardPadding * (i+1))); positionY = 20; width = cardWidth; height = cardHeight; } if(itemPlayer == 0 && itemElement == 'hand'){ positionX = canvas.width/2 - (cardWidth * (itemListLength - (i+1)) - (cardPadding * (i+1))); positionY = canvas.height-cardWidth*1.5-20; width = cardWidth; height = cardHeight; } //console.log('cardName: '+cardData[itemKey].name+', i/listPosition: '+i+', listPosition Length: '+itemListLength); // Set the size/position of the item size[itemKey] = [width, height]; position[itemKey] = [positionX,positionY]; }