You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1014 lines
26 KiB
JavaScript
1014 lines
26 KiB
JavaScript
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'] = [];
|
|
|
|
// 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 = [];
|
|
|
|
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(){
|
|
// 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.drawHand();
|
|
this.drawOpponentHand();
|
|
|
|
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(){
|
|
// Loop all items
|
|
for(let itemKey = 0; itemKey < item.length; itemKey++){
|
|
// Check if item is not in deck, deck items aren't to be drawn
|
|
// 'key' in 'object'
|
|
if(itemKey in boardElement && boardElement[itemKey] != 'deck'){
|
|
// Check if item belongs to opponent for now
|
|
// this will just be used to set positioning in the future
|
|
if(itemKey in player && player[itemKey] == 1){
|
|
// Just for opponentBoard atm
|
|
// This method will need to draw all cards, calcing their positions
|
|
// Which sounds hard
|
|
let opponentBoardLength = getCurrentPositionAndLength('board', 1)[1];
|
|
|
|
// I know it's redundant, just need to get my head around it all
|
|
// Setting position, will be moved elsewhere when working fully
|
|
let cardPadding = 10;
|
|
let i = listPosition[itemKey];
|
|
console.log('cardName: '+cardData[itemKey].name);
|
|
console.log('i/listPosition: '+i);
|
|
console.log('boardLength: '+opponentBoardLength);
|
|
let positionX = canvas.width/2 - (cardWidth * (opponentBoardLength - i) - (cardPadding * i));
|
|
console.log('posX: '+positionX);
|
|
let positionY = cardHeight + 30;
|
|
let width = cardWidth;
|
|
let height = cardHeight;
|
|
|
|
position[itemKey] = [positionX,positionY];
|
|
size[itemKey] = [width, height];
|
|
|
|
// Check status (for tapped atm)
|
|
let border = null;
|
|
if(cardStatus[itemKey] == 'tapped'){border = '#E0BC00';}
|
|
let name = itemKey; // Not needed really anymore, but keeping for now
|
|
positionX = position[itemKey][0];
|
|
positionY = position[itemKey][1];
|
|
width = size[itemKey][0];
|
|
height = size[itemKey][1];
|
|
let fill = '#CCC';
|
|
|
|
let shape = new Shape({
|
|
name: name,
|
|
x: positionX,
|
|
y: positionY,
|
|
width: width,
|
|
height: height,
|
|
fillStyle: fill,
|
|
strokeStyle: border
|
|
});
|
|
|
|
shape.draw();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
// 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);
|
|
}
|
|
|
|
// Naming's getting awkward here...
|
|
// Draw the cards in hand
|
|
drawHand(){
|
|
// Player Hand/Cards in Hand
|
|
for (let i = 0; i < playerHand.length; i++) {
|
|
|
|
let name = 'cardInHand_'+(i+1);
|
|
|
|
let cardPadding = 10;
|
|
let fill = '#'+i+i+'FF00';
|
|
|
|
// TODO: fix positionX, actually have some maffs
|
|
let positionX = canvas.width/2 - (cardWidth * (playerHand.length - (i+1)) - (cardPadding * (i+1)));
|
|
let positionY = canvas.height-cardWidth*1.5-20;
|
|
let width = cardWidth;
|
|
let height = cardHeight;
|
|
|
|
this.drawCard(playerHand, i, name, positionX, positionY, width, height, fill);
|
|
}
|
|
|
|
}
|
|
|
|
drawOpponentHand(){
|
|
// Opponents Hand/Cards in Hand
|
|
for (let i = 0; i < opponentHand.length; i++) {
|
|
|
|
let name = 'cardInOpponentsHand_'+(i+1);
|
|
|
|
let cardPadding = 10;
|
|
let fill = '#'+i+i+'DD00';
|
|
|
|
// TODO: fix positionX, actually have some maffs
|
|
let positionX = canvas.width/2 - (cardWidth * (opponentHand.length - (i+1)) - (cardPadding * (i+1)));
|
|
let positionY = 20;
|
|
let width = cardWidth;
|
|
let height = cardHeight;
|
|
|
|
this.drawCard(opponentHand, i, name, positionX, positionY, width, height, fill);
|
|
}
|
|
|
|
}
|
|
|
|
drawCards(){}
|
|
|
|
// Draw a card, traditional TCG
|
|
drawACard(cardsToDraw = 1){
|
|
// For loop so that animations will play each time (when they exist)
|
|
for(let draw = 0; draw < cardsToDraw; draw++){
|
|
if(playerHand.length >= maxHandSize){
|
|
alert('Hand full '+playerHand.length+'/'+maxHandSize);
|
|
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 hand
|
|
playerHand.push(cardDrawn);
|
|
this.drawBoard();
|
|
}
|
|
}
|
|
drawACardOpponent(cardsToDraw = 1){
|
|
for(let draw = 0; draw < cardsToDraw; draw++){
|
|
if(opponentHand.length >= maxHandSize){
|
|
alert('Hand full '+opponentHand.length+'/'+maxHandSize);
|
|
return 0;
|
|
}
|
|
// Random card from deck, remove from deck, add to hand
|
|
let cardToDraw = Math.floor(Math.random() * deckCountOpponent);
|
|
let cardDrawn = opponentDeck[cardToDraw];
|
|
// Remove from deck
|
|
opponentDeck.splice(cardToDraw, 1);
|
|
// Add to hand
|
|
opponentHand.push(cardDrawn);
|
|
this.drawBoard();
|
|
}
|
|
}
|
|
|
|
|
|
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.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;
|
|
|
|
// 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){
|
|
|
|
// 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];
|
|
|
|
}
|
|
|