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.
358 lines
8.9 KiB
JavaScript
358 lines
8.9 KiB
JavaScript
const ctx = canvas.getContext('2d');
|
|
const canvasLeft = canvas.offsetLeft + canvas.clientLeft;
|
|
const canvasTop = canvas.offsetTop + canvas.clientTop;
|
|
|
|
const cardWidth = 240;
|
|
const cardHeight = 360;
|
|
|
|
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'] = [];
|
|
|
|
// TODO: Uniform the arrays to player and opponent/different playesr
|
|
let playerHand = [];
|
|
let opponentHand = [];
|
|
let playerBoard = [];
|
|
let opponentBoard = [];
|
|
let playerDeck = [];
|
|
let opponentDeck = [];
|
|
|
|
let deckCount = 60;
|
|
let deckCountOpponent = 60;
|
|
|
|
let cardsInOpponentsHand = 0;
|
|
const maxHandSize = 4;
|
|
const maxBoardSize = 3;
|
|
|
|
|
|
// 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.drawHand();
|
|
this.drawOpponentHand();
|
|
|
|
this.drawPlayerNames('Nathan', 'Evil Nathan');
|
|
}
|
|
|
|
drawPlayerNames(playerName, opponentName = false){
|
|
// Player Name
|
|
ctx.fillText(playerName, 50, canvas.height - 110);
|
|
|
|
// Opponent's Name
|
|
if(!opponentName){
|
|
// Just clear the name
|
|
}else{
|
|
ctx.fillText(opponentName, canvas.width - (ctx.measureText(opponentName).width + 50), 110);
|
|
}
|
|
}
|
|
|
|
// 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){
|
|
var cardClickable = new Shape({
|
|
name: name,
|
|
x: positionX,
|
|
y: positionY,
|
|
width: cardWidth/2,
|
|
height: cardHeight/2,
|
|
fillStyle: fill
|
|
});
|
|
|
|
array[arrayKey]['clickable'] = cardClickable;
|
|
array[arrayKey]['clickable'].draw();
|
|
|
|
// Add card text
|
|
ctx.fillStyle = '#000';
|
|
ctx.fillText(
|
|
array[arrayKey]['name']
|
|
, positionX + (ctx.measureText(array[arrayKey]['name']/2).width)
|
|
, positionY+20
|
|
);
|
|
}
|
|
|
|
drawDeck(){
|
|
// Deck
|
|
clickableItems['deckSprite'] = new Shape({
|
|
name: 'deck',
|
|
x: canvas.width-cardWidth/2-40,
|
|
y: canvas.height-cardHeight/2-60,
|
|
width: cardWidth/2,
|
|
height: cardHeight/2,
|
|
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/5,
|
|
y: canvas.height-cardHeight/5,
|
|
width: cardWidth/8,
|
|
height: cardHeight/8,
|
|
fillStyle: "#FFF"
|
|
});
|
|
deckCounterSprite.draw();
|
|
|
|
// TODO: Center in the circle
|
|
ctx.fillStyle = '#000';
|
|
ctx.fillText(playerDeck.length, canvas.width-cardWidth/5 - (ctx.measureText(playerDeck.length).width) + 7, canvas.height-cardHeight/5 + 5);
|
|
}
|
|
drawDeckOpponent(){
|
|
// Opponent's Deck
|
|
clickableItems['deckOpponentSprite'] = new Shape({
|
|
name: 'deckOpponent',
|
|
x: 40,
|
|
y: 60,
|
|
width: cardWidth/2,
|
|
height: cardHeight/2,
|
|
fillStyle: "#FF0000"
|
|
});
|
|
clickableItems['deckOpponentSprite'].draw();
|
|
let deckCounterOpponentSprite = new Shape({
|
|
shape: 'circle',
|
|
name: 'deckCounterOpponent',
|
|
x: cardWidth/2+(cardWidth/8),
|
|
y: cardHeight/2+(cardHeight/8),
|
|
width: cardWidth/8,
|
|
height: cardHeight/8,
|
|
fillStyle: "#FFF"
|
|
});
|
|
deckCounterOpponentSprite.draw();
|
|
|
|
ctx.fillStyle = '#000';
|
|
// TODO: Center in the circle
|
|
ctx.fillText(opponentDeck.length, cardWidth/2 + (ctx.measureText(opponentDeck.length).width) + 10, cardHeight/1.58);
|
|
}
|
|
|
|
// 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/4 * 2) * (playerHand.length - (i+1)) - (cardPadding * (i+1)));
|
|
let positionY = canvas.height - cardHeight/2-20;
|
|
let width = cardWidth/2;
|
|
let height = cardHeight/2;
|
|
|
|
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/4 * 2) * (opponentHand.length - (i+1)) - (cardPadding * (i+1)));
|
|
let positionY = 20;
|
|
let width = cardWidth/2;
|
|
let height = cardHeight/2;
|
|
|
|
this.drawCard(opponentHand, i, name, positionX, positionY, width, height, fill);
|
|
}
|
|
|
|
}
|
|
|
|
drawCards(){}
|
|
|
|
// Draw a card, traditional TCG
|
|
drawACard(){
|
|
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(){
|
|
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/4 * 2) * (playerBoard.length - (i+1)) - (cardPadding * (i+1)));
|
|
let positionY = canvas.height - cardHeight/2-20-(cardHeight/2);
|
|
let width = cardWidth/2;
|
|
let height = cardHeight/2;
|
|
|
|
this.drawCard(playerBoard, i, name, positionX, positionY, width, height, fill);
|
|
}
|
|
}
|
|
|
|
drawCardsOnBoardOpponent(){
|
|
|
|
}
|
|
|
|
// Currently only functionality in hand
|
|
playCardToBoard(index){
|
|
// Get the card data
|
|
let cardPlayed = playerHand[index];
|
|
|
|
// 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;
|
|
}
|
|
|
|
// Remove from hand
|
|
playerHand.splice(index, 1);
|
|
// Add to board
|
|
playerBoard.push(cardPlayed);
|
|
|
|
this.drawBoard();
|
|
}
|
|
}
|
|
|
|
// TEMP!!
|
|
createDeckList(playerDeck, deckCount);
|
|
createDeckList(opponentDeck, deckCountOpponent);
|
|
|
|
// Run board commands here for testing
|
|
let board = new Board;
|
|
//board.initBoard();
|
|
|
|
board.drawBoard();
|
|
|
|
canvas.addEventListener('click', function(event) {
|
|
var x = event.pageX - canvasLeft,
|
|
y = event.pageY - canvasTop;
|
|
|
|
// Collision detection between clicked offset and clickableItems
|
|
// https://stackoverflow.com/a/9880302
|
|
|
|
// # 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)){
|
|
board.drawACard();
|
|
}
|
|
|
|
// # OPPONENT DECK
|
|
clickable = clickableItems['deckOpponentSprite'];
|
|
|
|
if(clickableCheck(x,y,clickable)){
|
|
board.drawACardOpponent();
|
|
}
|
|
|
|
// # PLAYER HAND
|
|
playerHand.forEach(function(card, index){
|
|
|
|
let clickable = card.clickable;
|
|
|
|
if(clickableCheck(x,y,clickable)){
|
|
|
|
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();
|
|
}
|
|
});
|
|
|
|
|
|
}, 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){
|
|
for(let i = 0; i < deckCount; i++){
|
|
deck.push({'name':'CardName '+(i+1), 'cost':1, 'atk':1, 'def':1, 'rarity': 'common', 'effect':null, 'type':'human'});
|
|
}
|
|
}
|
|
|