diff --git a/components.js b/components.js index db55f8b..c39e3e8 100644 --- a/components.js +++ b/components.js @@ -29,6 +29,7 @@ const component = { tapped : {}, attacking : {}, inspected : {}, + targetable : {}, }, cardAttack : {}, cardColours : {}, // Replace with colour diff --git a/gameHelper.js b/gameHelper.js index 1c7e150..d607a48 100644 --- a/gameHelper.js +++ b/gameHelper.js @@ -47,8 +47,46 @@ function moveElementPositions(roomId, player, direction, element, position){ } +function canAttack(roomId, playerId, cardId){ + + if(cardId in global.roomData[roomId].itemData.component.cardStatus.tapped){ + return false; + } + + return true; + +} +function getTargetableCards(roomId, playerId, cardId){ + + // i.e. If no flight/reach, you cant attack flight, if not all shield tapped, cant attack tapped shield + // TODO: The above, for now just letting all units/shields targetable + + let targetable = {}; + // Board + for (const [key, value] of Object.entries(global.roomData[roomId].itemData.component.board)) { + // If not the players card (for now, will need better checks in future) + if(global.roomData[roomId].itemData.player[key] !== playerId){ + targetable[key] = key; + } + } + // Shield + for (const [key, value] of Object.entries(global.roomData[roomId].itemData.component.shield)) { + // If not the players card (for now, will need better checks in future) + if(global.roomData[roomId].itemData.player[key] !== playerId){ + //if(!(key in global.roomData[roomId].itemData.player[playerId])){ + targetable[key] = key; + } + } + + console.log(targetable); + return targetable; + +} + module.exports = { - setCardPosition + setCardPosition + ,canAttack + ,getTargetableCards }; diff --git a/gameMod.js b/gameMod.js index 50c7eda..74c749f 100644 --- a/gameMod.js +++ b/gameMod.js @@ -539,6 +539,27 @@ function untapCard(roomId, playerId, cardId){ } +function startAttack(roomId, playerId, cardId){ + + console.log('start attack'); + if(!gameHelper.canAttack){ + return false; + } + + // Set the card to 'attacking' + global.roomData[roomId].itemData.component.cardStatus.attacking[cardId] = cardId; + + // TODO: Maybe set targetable as component and return that + global.roomData[roomId].itemData.component.cardStatus.targetable = gameHelper.getTargetableCards(roomId, playerId, cardId); + + // Return the available targets (give them a border in UI) + global.socketResponseUpdateTargetable(roomId, playerId, + global.roomData[roomId].itemData.component.cardStatus.targetable + ); + +} + + // DATA RETURNER DUDES // TODO: Where to put this? Kind of a helper, kind of functionality. Hmmmmm // maybe do a dataHelper? then anything to return data can be included there? @@ -599,6 +620,7 @@ module.exports = { ,playManaFromHand ,acceptResolveStack ,gameStart + ,startAttack // TEMP ,tapCard ,untapCard diff --git a/public/index.html b/public/index.html index adde21e..cdd5a5f 100644 --- a/public/index.html +++ b/public/index.html @@ -22,6 +22,7 @@ +


diff --git a/public/js/canvas/draw.js b/public/js/canvas/draw.js index 286280b..6f09840 100644 --- a/public/js/canvas/draw.js +++ b/public/js/canvas/draw.js @@ -350,13 +350,15 @@ function drawCardInHand(entity){ // TODO: Change card colour based on its colours // Draw the card shape + let strokeStyle = '#AAA'; + if(entity in gameData.cardStatus.targetable){ strokeStyle = '#222'; } let shape = new Shape({ x: gameData.position[entity][0], y: gameData.position[entity][1], width: gameData.size[entity][0], height: gameData.size[entity][1], fillStyle: '#EEE', - strokeStyle: '#AAA', + strokeStyle: strokeStyle, }); shape.draw(); @@ -370,7 +372,9 @@ function drawCardOnBoard(entity){ // TODO: Passives, flight, etc. effects let strokeStyle = '#AAA'; - if(entity in gameData.cardStatus.tapped){ strokeStyle = '#555'; } + if(entity in gameData.cardStatus.tapped){ strokeStyle = '#6D0202'; } + if(entity in gameData.cardStatus.targetable){ strokeStyle = '#FF9A00'; } + if(entity in gameData.cardStatus.targetted){ strokeStyle = '#EC5300'; } // Draw the card shape let shape = new Shape({ x: gameData.position[entity][0], @@ -392,6 +396,7 @@ function drawShield(entity){ let strokeStyle = '#AAA'; if(entity in gameData.cardStatus.tapped){ strokeStyle = '#555'; } + if(entity in gameData.cardStatus.targetable){ strokeStyle = '#222'; } // Draw the card shape let shape = new Shape({ x: gameData.position[entity][0], @@ -416,6 +421,7 @@ function drawMana(entity){ let strokeStyle = '#AAA'; if(entity in gameData.cardStatus.tapped){ strokeStyle = '#555'; } + if(entity in gameData.cardStatus.targetable){ strokeStyle = '#222'; } // Draw the card shape let shape = new Shape({ x: gameData.position[entity][0], diff --git a/public/js/canvas/interactionMenu.js b/public/js/canvas/interactionMenu.js index 0ad0d25..992151e 100644 --- a/public/js/canvas/interactionMenu.js +++ b/public/js/canvas/interactionMenu.js @@ -35,6 +35,18 @@ function openInteractionMenu(entity){ // Interact // Attack + // Start Attack + if(entity in gameData.board && !(entity in gameData.cardStatus.tapped)){ + + // TODO: Make the object within each interationOption a function to return instead of duping + gameData.interactionOption['Attack'] = { + x: gameData.position[entity][0] + gameData.size[entity][0]*.1/2, + y: gameData.position[entity][1] + gameData.size[entity][1] - (35 * (Object.entries(gameData.interactionOption).length + 1)), + width: gameData.size[entity][0]*.9, + height: 30 + } + } + // Target Attack Target // Tap // TAP (TEMP TODO: remove or add in a statement to hide) @@ -77,6 +89,28 @@ function openInteractionMenu(entity){ } + // If selectable, give option to select. If selected, deselect + if(gameData.cardStatus.targetable[entity] !== undefined){ + + gameData.interactionOption['Target'] = { + x: gameData.position[entity][0] + gameData.size[entity][0]*.1/2, + y: gameData.position[entity][1] + gameData.size[entity][1] - (35 * (Object.entries(gameData.interactionOption).length + 1)), + width: gameData.size[entity][0]*.9, + height: 30 + } + + } + if(gameData.cardStatus.targetable[entity] !== undefined && gameData.cardStatus.targetted[entity] !== undefined){ + + gameData.interactionOption['Untarget'] = { + x: gameData.position[entity][0] + gameData.size[entity][0]*.1/2, + y: gameData.position[entity][1] + gameData.size[entity][1] - (35 * (Object.entries(gameData.interactionOption).length + 1)), + width: gameData.size[entity][0]*.9, + height: 30 + } + + } + drawGameBoard(); } @@ -117,6 +151,19 @@ function doiMenuPressed(iMenuKey){ iMenuUntap(); } + // Attack + // Start Attack (Card that's to attack) + if(iMenuKey == 'Attack'){ + iMenuStartAttack(); + } + + // Target + if(iMenuKey == 'Target'){ + iMenuTarget(); + } + if(iMenuKey == 'Untarget'){ + iMenuUntarget(); + } } function iMenuPlayToBoard(){ @@ -143,4 +190,16 @@ function iMenuUntap(){ console.log(Object.keys(gameData.inInteractionMenu)[0]); requestUntapCard(gameData.inInteractionMenu[Object.keys(gameData.inInteractionMenu)[0]]); } +function iMenuStartAttack(){ + requestStartAttack(Object.keys(gameData.inInteractionMenu)[0]); +} +function iMenuTarget(){ + gameData.cardStatus.targetted[Object.keys(gameData.inInteractionMenu)[0]] = Object.keys(gameData.inInteractionMenu)[0]; + clearInteractionMenu(); // Clears and redraws the board + console.log('target'); +} +function iMenuUntarget(){ + delete(gameData.cardStatus.targetted[Object.keys(gameData.inInteractionMenu)[0]]); + console.log('UNtarget'); +} diff --git a/public/js/game/components.js b/public/js/game/components.js index c7f874c..eae0173 100644 --- a/public/js/game/components.js +++ b/public/js/game/components.js @@ -34,6 +34,8 @@ let gameData = { tapped : {}, attacking : {}, inspected : {}, + targetable : {}, + targetted : {}, }, diff --git a/public/js/game/dataUpdate.js b/public/js/game/dataUpdate.js index df9324d..ba35e2b 100644 --- a/public/js/game/dataUpdate.js +++ b/public/js/game/dataUpdate.js @@ -104,6 +104,13 @@ function updateTapped(data){ gameData.cardStatus.tapped = data; console.log(gameData.cardStatus.tapped); } +// Targetable +function updateTargetable(data){ + console.log(data); + // Clear targetable if null returned + if(data == null){ gameData.cardStatus.targetable = {}; } + gameData.cardStatus.targetable = data; +} // To prevent typical functionality (draw, etc.) // if there's a stack in play. diff --git a/public/js/game/socket.js b/public/js/game/socket.js index 4d525c7..f0a3c9f 100644 --- a/public/js/game/socket.js +++ b/public/js/game/socket.js @@ -121,6 +121,19 @@ socket.on('responseUntapped', function (data) { }); +function requestStartAttack(card){ + console.log('>> startAttack'); + socket.emit('requestStartAttack', gameData.roomId, gameData.playerId, card); +} +socket.on('responseTargetable', function (data) { + // The playerId that played it for animations + console.log('<< responseTargetable'); + console.log(data); + updateTargetable(data); + drawGameBoard(); +}); + + // Stack socket.on('responseAddToStack', function (data) { console.log('<< addToStack'); @@ -148,7 +161,6 @@ function requestResolveStack(){ socket.emit('requestResolveStack', gameData.roomId, gameData.playerId); } - // Functions like this would be elsewhere, do client-side // validation THEN request stuff from the server? // This is here for now, as it's used by the button diff --git a/server.js b/server.js index eed3f07..b7c079f 100644 --- a/server.js +++ b/server.js @@ -84,6 +84,10 @@ function onConnection(socket){ gameMod.untapCard(roomId, playerId, card); }); + socket.on('requestStartAttack', function(roomId, playerId, card) { + gameMod.startAttack(roomId, playerId, card); + }); + } global.getPlayerSocketFromRoom = function(playerId, roomId){ @@ -246,6 +250,22 @@ global.socketResponseUntapped = function(roomId, card){ global.sendToEachSocket(roomId, 'responseUntapped', data); } + +/* +global.socketResponseStartAttack = function(roomId, playerId, targetable){ + global.socketResponseUpdateTargetable(roomId, playerId, targetable); +} +*/ +global.socketResponseUpdateTargetable = function(roomId, playerId, targetable){ + + global.io.to(global.getPlayerSocketFromRoom(playerId, roomId)).emit( + 'responseTargetable' + ,targetable + ); + +} +// Attack (return the attacking and 'defending' card and allow for interactions/stack + // Stack global.socketResponseAddToStack = function(roomId){ global.sendToEachSocket(roomId, 'responseAddToStack', 'testData');