Rewrite attack logic to ECS

develop
Nathan Steel 1 year ago
parent 75aea0308b
commit 6f3ae033ac

@ -30,9 +30,10 @@ let cardData = {};
let position = {}; let position = {};
let size = {}; let size = {};
//let shape = {}; //let shape = {};
let cardStatus = {}; // tapped, attacking, inspected, untargettable let cardStatus = {}; // tapped, attacking, inspected, untargettable (TODO:maybe used this instead of inEvent later)
let player = {}; let player = {};
let listPosition = {}; let listPosition = {};
let inEvent = null;
let playerHand = []; let playerHand = [];
let opponentHand = []; let opponentHand = [];
@ -58,7 +59,6 @@ const maxShield = 4;
let inspectCard = null; let inspectCard = null;
let attackingCard = null; let attackingCard = null;
let gameWin = 0;
// Gonna need lots of refactoring, and sorting // Gonna need lots of refactoring, and sorting
class Board{ class Board{
@ -88,13 +88,23 @@ class Board{
this.drawCardsECS(); // Atop most everything atm for testing this.drawCardsECS(); // Atop most everything atm for testing
if(gameWin){ if(this.checkGameWin == true){
this.drawWin(); this.drawWin();
} }
this.drawInspectedCard(); this.drawInspectedCard();
} }
checkGameWin(){
// TODO: Change logic to ECSey, and move into main loop (for other win-cons besides direct attack)
if(false){
if(opponentShield.length <= 0){
return true;
}
}
return false;
}
drawWin(){ drawWin(){
var winBoard = new Shape({ var winBoard = new Shape({
name: name, name: name,
@ -165,6 +175,7 @@ class Board{
// Check status, and change border colour for display (for tapped atm) // Check status, and change border colour for display (for tapped atm)
let border = null; let border = null;
if(cardStatus[itemKey] == 'tapped'){border = '#E0BC00';} if(cardStatus[itemKey] == 'tapped'){border = '#E0BC00';}
if(cardStatus[itemKey] == 'attacking'){border = '#C92D22';}
// Set the card 'cardboard' colour based on the card colour type // Set the card 'cardboard' colour based on the card colour type
let colourId = cardData[itemKey].colour; let colourId = cardData[itemKey].colour;
@ -472,7 +483,7 @@ class Board{
toPosition = getCurrentPositionAndLength(elementTo, playerTo)[0]+1 toPosition = getCurrentPositionAndLength(elementTo, playerTo)[0]+1
//console.log(toPosition); //console.log(toPosition);
} }
console.log('itemKey: '+itemKey+' fromPosition: '+fromPosition+' elementFrom: '+elementFrom+' elementTo: '+elementTo+' toPosition: '+toPosition+' playerFrom: '+playerFrom+' playerTo: '+playerTo); //console.log('itemKey: '+itemKey+' fromPosition: '+fromPosition+' elementFrom: '+elementFrom+' elementTo: '+elementTo+' toPosition: '+toPosition+' playerFrom: '+playerFrom+' playerTo: '+playerTo);
listPosition[itemKey] = toPosition; listPosition[itemKey] = toPosition;
// Move from elementFrom to elementTo // Move from elementFrom to elementTo
@ -483,11 +494,11 @@ class Board{
//console.log(boardElement[itemKey]); //console.log(boardElement[itemKey]);
// Move down(0) the positions of elementFrom, from fromPosition for player // Move down(0) the positions of elementFrom, from fromPosition for player
console.log(JSON.stringify(boardElement)); //console.log(JSON.stringify(boardElement));
console.log(JSON.stringify(listPosition)); //console.log(JSON.stringify(listPosition));
this.moveElementPositions(0, elementFrom, fromPosition, playerFrom); this.moveElementPositions(0, elementFrom, fromPosition, playerFrom);
console.log(JSON.stringify(boardElement)); //console.log(JSON.stringify(boardElement));
console.log(JSON.stringify(listPosition)); //console.log(JSON.stringify(listPosition));
this.drawBoard(); this.drawBoard();
return 1; // Got a loop that calls a loop, and checks the new values atm, so this keeps counting down return 1; // Got a loop that calls a loop, and checks the new values atm, so this keeps counting down
@ -675,60 +686,95 @@ class Board{
// Selects the card that will be attacking // Selects the card that will be attacking
// Stop other actions besides selecting opponent/opponent unit // Stop other actions besides selecting opponent/opponent unit
// Can cancel, will do later // Can cancel, will do later
startAttack(index){ // Rename to attack intent?
startAttack(itemAttacking){
// Can probably combine attacking/inspect, and set another array element to 'attacking', 'inspecting', etc. // Can probably combine attacking/inspect, and set another array element to 'attacking', 'inspecting', etc.
attackingCard = [playerBoard[index], index];
// Do error/legal checks here
if(cardStatus[itemAttacking] == 'tapped'){
alert('Cannot attack, as tapped');
return false;
}
// Set event
inEvent = ['attack', itemAttacking];
// Set the status of card to attacking for drawing.
// In future this may be what's used for check (or other in case you can attack with multiple units at once)
cardStatus[itemAttacking] = 'attacking';
this.drawBoard(); this.drawBoard();
} }
// Do the attack // Do the attack
makeAttack(index, array = null, name = null){ makeAttack(itemDefending, itemAttacking = 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; // If itemAttacking not defined, use the item from inEvent
this.endAttack(); if(itemAttacking == null){
return 1; itemAttacking = inEvent[1];
} }
if(defendingCard.atk <= attackingCard[0].atk){ if(cardStatus[itemAttacking] == 'tapped'){
array.splice(index, 1); alert('Cannot attack, as tapped');
// Need to push to grave, etc. here in future too return false;
} }
if(attackingCard[0].atk <= defendingCard.atk){
playerBoard.splice(attackingCard[1], 1); switch (boardElement[itemDefending]) {
}else{ // If card on 'board' attacked
playerBoard[attackingCard[1]].tapped = true; // Compare attackingCard and defendingCard
case 'board':
let atkAttacker = cardData[itemAttacking].attack;
let atkDefender = cardData[itemDefending].attack;
// Does Attacker kill Defender
if(atkDefender <= atkAttacker){
// TODO:Send the item to grave, boardElement = 'grave'
}
// Does Defender kill Attacker
if(atkAttacker <= atkDefender){
// TODO:Send the item to grave
this.endAttackFor(itemAttacking);
}else{
// If not, end the attacker cards attack 'phase'
this.endAttackFor(itemAttacking);
}
break;
case 'shield':
// If the shield is tapped 'destroy' it
if(cardStatus[itemDefending] == 'tapped'){
// Remove from shield, add to hand
// Untap, add to hand (when moving item between status, ANY ITEM. remove status)
this.destroyShield(itemDefending);
}
else{
this.tapCard(itemDefending);
}
// End the attacker card attack 'phase'
this.endAttackFor(itemAttacking);
break;
} }
console.log('attacking');
this.endAttack();
// If player attacked
// Compare life/remove life cards 5/10/15,1/2/3? this.drawBoard();
}
endAttackFor(itemAttacking){
// Tap the card (this would check if after attack cards taps or not.
this.tapCard(itemAttacking);
// If the item attacking was from the 'attack' event, remove the event
if(itemAttacking == inEvent[1]){
inEvent = null;
}
} }
endAttack(){ cancelAttackFor(itemAttacking){
attackingCard = null; if(itemAttacking != inEvent[1]){
if(opponentShield.length <= 0){ return false;
gameWin = 1;
} }
// If the card to attack is from inEvent of 'attack', remove it and its cardStatus
cardStatus[itemAttacking] = null;
inEvent = null;
this.drawBoard(); this.drawBoard();
} }
@ -791,6 +837,23 @@ class Board{
this.drawBoard(); this.drawBoard();
} }
} }
// HELPER METHODS, to simplify code-base for me in the future
destroyShield(itemKey){
// Adds from 'shield' to 'hand' boardElement
// Sets the listPosition to the next in line for new boardElement
// Changes the listPosition of each item in previous boardElement
// All for same player, although below playerFrom/playerTo can be set to switch between players
// TODO: Removes any cardStatus
//addFromBoardElement(playerFrom, fromPosition, elementFrom, elementTo, toPosition=null, playerTo=null)
this.addFromBoardElement(player[itemKey], listPosition[itemKey], boardElement[itemKey], 'hand', null, null);
}
tapCard(itemKey){
// Set the cardStatus to tapped
cardStatus[itemKey] = 'tapped';
// Do any other 'on tap' effects, etc. in the future
}
} }
// TEMP!! // TEMP!!
@ -816,14 +879,10 @@ board.drawBoard(true);
//board.drawACard(3); //board.drawACard(3);
// Right Click, Rightclick, rightclick, right click
canvas.addEventListener('contextmenu', function(event) { canvas.addEventListener('contextmenu', function(event) {
event.preventDefault(); event.preventDefault();
let specialEvent = false;
if(inspectCard !== null || attackingCard !== null || gameWin){
specialEvent = true;
}
var x = event.pageX - canvasLeft, var x = event.pageX - canvasLeft,
y = event.pageY - canvasTop; y = event.pageY - canvasTop;
@ -845,8 +904,15 @@ canvas.addEventListener('contextmenu', function(event) {
switch(boardElement[itemKey]){ switch(boardElement[itemKey]){
// Check item location, and trigger events based on it // Check item location, and trigger events based on it
case 'board': case 'board':
// Untap // TODO: If the current event is attack, right clicking same item in event
cardStatus[itemKey] = null; // will end the attack event
// If there's an attack event, target other cards
// If there is an event, the event is attack event, and the item currently loop
// is the same one as currently in the event
console.log(inEvent);
if(inEvent && inEvent[0] == 'attack' && itemKey == inEvent[1]){
board.cancelAttackFor(itemKey);
}
board.drawBoard(); board.drawBoard();
break; break;
case 'hand': case 'hand':
@ -860,21 +926,13 @@ canvas.addEventListener('contextmenu', function(event) {
} }
} }
// # PLAYER HAND // Return false to prevent context opening:
playerHand.forEach(function(card, index){ // https://stackoverflow.com/a/4236294
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; return false;
}, false); }, false);
// Left Click, Leftclick, leftclick, left click
canvas.addEventListener('click', function(event) { canvas.addEventListener('click', function(event) {
console.log('EVENT LISTENER'); console.log('EVENT LISTENER');
console.log(''); console.log('');
@ -882,9 +940,23 @@ canvas.addEventListener('click', function(event) {
// specialEvent used to prevent eventTriggers if something specific // specialEvent used to prevent eventTriggers if something specific
// is being done, attack needs to be made, inspecting card. // is being done, attack needs to be made, inspecting card.
// Prevents user from doing other actions until completed or cancelled event // Prevents user from doing other actions until completed or cancelled event
let specialEvent = false;
if(inspectCard !== null || attackingCard !== null || gameWin){ // If there is a 'specialEvent', and specialEvent is set to inspect
specialEvent = true; // TODO: Inspect event
if(false){
if(inEvent && inEvent[0] == 'inspect'){
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();
}
}
} }
var x = event.pageX - canvasLeft, var x = event.pageX - canvasLeft,
@ -916,11 +988,33 @@ canvas.addEventListener('click', function(event) {
// Check the location of element // Check the location of element
switch(boardElement[itemKey]){ switch(boardElement[itemKey]){
// Check item location, and trigger events based on it // Check item location, and trigger events based on it
// TODO: Change inEvent locations, and checks elsewhere?
// TODO: Make existing mechanics ECSey
case 'board': case 'board':
// player/opponentBoard not seperated, as want to have
// each player able to have effects, etc. to make others attack
// etc.
// playerBoard
// Can attack // Can attack
// board.startAttack(index); console.log(inEvent);
// Get tapped console.log(cardStatus[itemKey] != 'tapped');
cardStatus[itemKey] = 'tapped'; if(!inEvent && cardStatus[itemKey] != 'tapped'){
board.startAttack(itemKey);
}
// opponentBoard
// If there's an attack event, target other cards
if(inEvent && inEvent[0] == 'attack' && inEvent[1] != itemKey){
// Make attack on the card clicked, with card in inEvent[1]
board.makeAttack(itemKey);
}
// If no event, and clicked an OPPONENT CARD (for now)
// inspect the card (zoom in on it)
if(!inEvent){
board.inspectOpponentBoard(itemKey);
}
board.drawBoard(); board.drawBoard();
break; break;
case 'hand': case 'hand':
@ -930,96 +1024,39 @@ canvas.addEventListener('click', function(event) {
board.playCardToBoard(listPosition[itemKey], 'hand', 'board', playerId, playerId, 1); board.playCardToBoard(listPosition[itemKey], 'hand', 'board', playerId, playerId, 1);
board.drawBoard(); board.drawBoard();
break; break;
case 'shield':
// TODO:
// If you have an attack, and click opponent shield,
// destroy (unless they can block, etc.)
if(inEvent && inEvent[0] == 'attack' && inEvent[1] != itemKey){
board.makeAttack(itemKey);
}
break;
} }
} }
} }
} }
// Decks kept as-is for now
// TODO: boardElement realDeck, or smth and add these to the loop
// 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 // # PLAYER DECK
clickable = clickableItems['deckSprite']; clickable = clickableItems['deckSprite'];
if(clickableCheck(x,y,clickable) && !inEvent){
// 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(); board.drawACard();
} }
// TODO:
// # OPPONENT DECK // # OPPONENT DECK
clickable = clickableItems['deckOpponentSprite']; clickable = clickableItems['deckOpponentSprite'];
if(clickableCheck(x,y,clickable) && !inEvent){
if(clickableCheck(x,y,clickable) && !specialEvent){
board.drawACardOpponent(); board.drawACardOpponent();
} }
// # 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); }, false);
function clickableCheck(x,y,clickable=false,itemKey=false){ function clickableCheck(x,y,clickable=false,itemKey=false){
// Collision detection between clicked offset and clickableItems
// https://stackoverflow.com/a/9880302
// Temp solution to add the check while the old way also exists // Temp solution to add the check while the old way also exists
// simultaneously. It works, so that's nice // simultaneously. It works, so that's nice

Loading…
Cancel
Save