Changes to 'drawACard', serverdata, and UI changes

Return data from server for each client (cardCounts)
Return data for client that drew (cardData, listPos. etc.)
UI changes on client to display the temporary 'cards'
feature/clientSideSimplify
Nathan Steel 1 year ago
parent f69d5a8907
commit be96e46166

@ -490,7 +490,7 @@ function requestDeck(itemData = null){
// Add the entity into 'inDeck' component
// also add a listPosition based on current deckLength
itemData.component.inDeck[itemCount] = true; // Not sure what to store here
itemData.component.listPosition[itemCount] = itemData.component.cardCount.deck[forPlayer];
itemData.component.listPosition[itemCount] = itemData.component.cardCount.deck[forPlayer] + 1;
// Associate the card with the deck
// TODO: Change deckIn to something more sensical

@ -10,6 +10,7 @@ const component = {
roomId : null,
turn : 0,
playerTurn : 0,
player : {},
cardCount : {
deck : {},

@ -0,0 +1,53 @@
// Moves card positions down/up for the old/new element for player in room
function setCardPosition(roomId, player, card, newPosition, newElement, oldPosition, oldElement){
// Move anything in the old boardElement after the old listPosition down by one
moveElementPositions(roomId, player, 0, oldElement, oldPosition);
// Move anything in the new boardElement after (including) the new listPosition up by one
moveElementPositions(roomId, player, 1, newElement, newPosition);
// Then fit the card into the new gap that's opened up
listPosition[card] = newPosition;
// Remove from oldElement
delete oldElement[card]
// Add to newElement
newElement[card] = newPosition;
}
// direction 0 up, 1 down
function moveElementPositions(roomId, player, direction, element, position){
position = position;
listPosition = global.roomData[roomId].itemData.component.listPosition;
for (const [key, value] of Object.entries(element)) {
if(global.roomData[roomId].itemData.component.player[key] != player){
continue;
}
// Move down from (not including) the position passed
if(direction == 0 && listPosition[key] > position){
listPosition[key]--;
}
// Move everything from (including) the new position up
if(direction == 1 && listPosition[key] >= position){
console.log('hit');
console.log(listPosition[key]);
console.log(position);
listPosition[key]++;
}
}
}
module.exports = {
setCardPosition
};

@ -1,3 +1,5 @@
const gameHelper = require('./gameHelper');
// For anything related to the actual game itself (kinda)
// this will be split into different bits, but should be what manages a rooms
// game states, and alladat
@ -17,7 +19,7 @@ function passTurn(roomId, playerId){
//global.socketAlert(roomData[roomId].playerData[playerId].socketId, playerTurn, 'log');
if(playerTurn != playerId){
global.socketAlert(roomData[roomId].playerData[playerId].socketId, 'Not your turn', 'alert');
global.socketAlert(global.getPlayerSocketFromRoom(playerId, roomId), 'Not your turn', 'alert');
return false;
};
@ -32,30 +34,14 @@ function passTurn(roomId, playerId){
}
// Send turn data to each player
// Probably via the sockets in room (as could be spectators in future)
let clients = global.io.sockets.adapter.rooms.get(roomId);
for (const clientId of clients) {
const clientSocket = global.io.sockets.sockets.get(clientId);
console.log('>> '+clientSocket.playerId+' passed turn');
// Send the data back
let turnData = {
'playerTurn': newPlayerTurn,
'turn': global.roomData[roomId].itemData.component.turn,
};
global.io.to(clientSocket.id).emit('responsePassTurn', turnData);
}
global.socketResponsePassTurn(roomId);
// Let the player know it's their turn via alert too (in case tabbed out)
// TODO: This could probably be done front-end from the newPlayerTurn in socketResponsePassTurn
global.socketAlert(roomData[roomId].playerData[newPlayerTurn].socketId, 'Your turn', 'alert');
// Start of the new players turn, draw a card
drawACard(roomId, newPlayerTurn);
}
@ -65,49 +51,104 @@ function drawACard(roomId, playerId){
global.socketAlert(roomData[roomId].playerData[playerId].socketId, 'Hand full; cannot draw card', 'alert');
return false;
}
if(global.roomData[roomId].itemData.component.cardCount.deck[playerId] <= 0){
global.socketAlert(roomData[roomId].playerData[playerId].socketId, 'Deck empty; cannot draw card', 'alert');
return false;
}
// TODO: Check no card event/trigger occured that prevents/change draw card
// Change position to last position available in hand
let fromPosition = global.roomData[roomId].itemData.component.cardCount.deck[playerId]; // 'Bottom' of deck
let toPosition = global.roomData[roomId].itemData.component.cardCount.hand[playerId]; // Rightmost hand pos
let fromPosition = global.roomData[roomId].itemData.component.cardCount.deck[playerId]; // 'top' of deck
let toPosition = global.roomData[roomId].itemData.component.cardCount.hand[playerId] + 1; // Rightmost hand pos (starting at 1)
// ECSey att2, there's surely a better way of getting playerX top card within inDeck?
// Tried unions but it messes up the object data. Maybe need to have no data in each object
// and have it literally just be keys?
// Get each card from the deck
for (const [key, value] of Object.entries(global.roomData[roomId].itemData.component.inDeck)) {
// Key is the entity here
// If the card inDeck does not belongs to the player, skip over it
if(global.roomData[roomId].itemData.component.player[key] != playerId){
continue;
}
// If the card isn't the last (bottom) card of deck, skip over it
// TODO: -1 is jank, sort so listPositions all start from 1..x
if(global.roomData[roomId].itemData.component.listPosition[key] != fromPosition){
continue;
}
// The main man
// Move positions in hand/deck, and put the item from the deck into the hand
gameHelper.setCardPosition(roomId, playerId, key, toPosition, global.roomData[roomId].itemData.component.hand, fromPosition, global.roomData[roomId].itemData.component.inDeck);
}
// from inDeck to hand
// change the listPositions of both (only return listPosition of hand ids?)
// Reduce deckSize by 1 for the player that drew
global.roomData[roomId].itemData.component.cardCount.deck[playerId]--;
// And increase the hand size by 1
global.roomData[roomId].itemData.component.cardCount.hand[playerId]++;
// Then emit the deckSize and hand size to all the player's sockets
global.socketResponseDrawCard(roomId, playerId);
// TODO: Move card from deck to hand for the player. Dupe what I've got in board for
// this, but tidy it up
//global.roomData[roomId].itemData.component.inDeck = newPlayerTurn;
//global.roomData[roomId].itemData.component.hand = newPlayerTurn;
// Emit the 'hand' and related cardData for cards in the players hand
// Could merge this with the top?
global.socketResponsePlayerDrewCard(roomId, playerId);
}
// Then emit the deckSize and hand size to all the player's sockets
let clients = global.io.sockets.adapter.rooms.get(roomId);
for (const clientId of clients) {
const clientSocket = global.io.sockets.sockets.get(clientId);
console.log('>> '+clientSocket.playerId+' drew card');
// 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?
// TODO: May get all the data from hand, board, grave, etc. in functions
// like this, then union all the data and return that in one swoomp
// Probably better to just get all the keys from the boardlemenets and do
// the loop once though...
function getPlayerHandData(roomId, playerId){
let handEntities = {};
let handPositions = {};
let handCardData = {};
for (const [key, value] of Object.entries(global.roomData[roomId].itemData.component.hand)) {
// Key is entity ID here
// If the entity in hand belongs to the player, then they are allowed its data
if(global.roomData[roomId].itemData.component.player[key] == playerId){
// Send the data back
global.io.to(clientSocket.id).emit(
'responseDrawCard'
,global.roomData[roomId].itemData.component.cardCount
);
// Get entity of items in the hand
handEntities[key] = global.roomData[roomId].itemData.component.hand[key];
// Get listPosition of just items in the hand
handPositions[key] = global.roomData[roomId].itemData.component.listPosition[key];
// Same for cardData
handCardData[key] = global.roomData[roomId].itemData.component.cardData[key]; // TODO: Nothing on client side?
// Leaving other bits for now
}
}
// Emit the 'hand' and related cardData for cards in the players hand
return {
'handEntities': handEntities,
'handPositions': handPositions,
'handCardData': handCardData
};
}
module.exports = {
passTurn
,getPlayerHandData
,drawACard
};

@ -19,6 +19,7 @@
<hr>
<button onclick="passTurn()">Pass Turn</button>
<button onclick="requestDrawACard()">Draw Card</button>
<br><br>
<hr>

@ -5,9 +5,14 @@ function drawGameBoard(){
drawPlayerNames();
calculateDeckPositions();
calculateHandPositions();
drawEntities();
// TEMP. Likely want to pass entities, but if you don't have cardData for them
// then don't draw the card face up?
drawFakeHand();
}
function drawPlayerNames(){
@ -68,6 +73,35 @@ function calculateDeckPositions(){
}
}
// TODO: Move from draw into somewhere else
function calculateHandPositions(){
for (const [key, value] of Object.entries(gameData.hand)) {
// key is entity Id here
switch(gameData.player[key]){
// Set position for player hand (all the time at current)
case gameData.playerId:
let cardsInHand = gameData.cardCount.hand[gameData.playerId];
let positionInHand = gameData.listPosition[key];
gameData.position[key] = [
canvas.width/2 - (cardWidth * (cardsInHand - (positionInHand+1)) - (cardMargin * (positionInHand+1)))
,canvas.height-cardWidth*1.5-20
];
gameData.size[key] = [cardWidth, cardHeight];
break;
// Opponent, currently done in fakeHand
}
}
}
function drawEntities(){
@ -79,10 +113,15 @@ function drawEntities(){
if(gameData.size[key] !== undefined){
// If the entity is a deck
if(gameData.deck[key]){
if(key in gameData.deck){
drawDeck(key);
}
// If card in (player) hand
if(key in gameData.hand){
drawCardInHand(key);
}
}
}
@ -123,4 +162,71 @@ function drawDeck(entity){
printText(deckCount, textX, textY, 'center', 'bottom', 'normal', 'bold', '10', 'Arial', '#000');
}
function drawCardInHand(entity){
console.log('Draw card in hand');
console.log(gameData.position[entity]);
console.log(gameData.size[entity]);
// Draw the deck shape
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',
});
shape.draw();
}
// TEMP, or maybe not for opponent. Not 100% how to draw opponent hand without passing the data
// avoiding passing the data (for now) to prevent cheating by checking their cardIds etc. in the
// console. An issue that comes with making this in JS...
function drawFakeHand(){
console.log('Draw FAKE hand');
// itemList length is the count (/highest listPosition) in the hand in this case
// i is the listPosition of the entity (which since this isn't using the entities at the mo...)
// All jank temp kinda vars
// Needed as i substitute to track the fake hand drawn count
let opponentHandItem = 0;
let itemListLength = 0; // Believe value should just be the count of current cardCount.hand
let i = 0; // Believe value should just be the count of current cardCount.hand
// Loop each 'hand' not actual hand, but count of cards in hand
for (const [key, value] of Object.entries(gameData.cardCount.hand)) {
// key is the playerId here
switch(gameData.player[key]){
// Set position for opponents deck
case gameData.opponentId:
// Then loop the size of the hand
itemListLength = value; // Believe value should just be the count of current cardCount.hand
i = opponentHandItem; // Believe value should just be the count of current cardCount.hand
for(i; i < itemListLength; i++){
let shape = new Shape({
x: canvas.width/2 - (cardWidth * (itemListLength - (i+1)) - (cardMargin * (i+1))),
y: 20,
width: cardWidth,
height: cardHeight,
fillStyle: '#EEE',
strokeStyle: '#AAA',
});
shape.draw();
}
break;
}
}
}

@ -19,8 +19,11 @@ let gameData = {
// Real components from here?
listPosition : {},
cardData : {},
player : {},
deck : {},
hand : {},
// Local components, not done on serverside
// calculated, etc. by client

@ -11,7 +11,7 @@ function updateGameData(data){
updateTurn(data.component.turn, data.component.playerTurn);
updateItems(data.component.item, data.component.itemCount);
updatePlayerComponent(data.player);
updatePlayerComponent(data.component.player);
updateDecks(data.component.deck);
updateCardCount(data.component.cardCount);
@ -52,3 +52,15 @@ function updateCardCount(cardCount = null){
gameData.cardCount = cardCount;
}
// Cards in hand
function updatePlayerHand(data){
console.log('Update player hand');
// TODO: These will likely not be = as will overwrite.
// Likely to union all the data server-side and pass as one
// function such as updateEntities() or something
gameData.hand = data.handEntities;
gameData.listPosition = data.handPositions;
gameData.cardData = data.handCardData;
console.log(gameData);
}

@ -10,6 +10,10 @@ socket.on('responsePassTurn', function (data) {
updateTurn(data.turn, data.playerTurn);
drawGameBoard();
});
function requestDrawACard(){
console.log('>> drawACard');
socket.emit('drawACard', gameData.roomId, gameData.playerId);
}
// Functions like this would be elsewhere, do client-side
// validation THEN request stuff from the server?
@ -19,9 +23,19 @@ function passTurn(){
}
// Draw Card
// Both players get new hand + deck counts updated
socket.on('responseDrawCard', function (data) {
console.log('<< drawCard');
updateCardCount(data);
drawGameBoard();
});
// Player drew card
// Player that drew the card (atm) gets the cardData, listPosition
// TODO: related attack, cost, effects, etc.
socket.on('responsePlayerDrewCard', function (data) {
console.log('<< playerDrewCard');
updatePlayerHand(data);
drawGameBoard();
});

@ -20,3 +20,5 @@ const maxHandSize = 4;
const maxBoardSize = 3;
const maxShield = 2;
const cardMargin = 10;

@ -77,6 +77,7 @@ function roomGeneration(roomId){
// Add all the empty components to the room itemData
itemData.component = components.component;
itemData.component.player = itemData.player; // TODO: do this in setPlayers
// Generate the decks, and card within the deck cardLists
[itemData] = await Promise.all([ cardGen.requestDeck(itemData) ]);

@ -55,6 +55,16 @@ function onConnection(socket){
gameMod.passTurn(roomId, playerId);
});
socket.on('drawACard', function(roomId, playerId) {
gameMod.drawACard(roomId, playerId);
});
}
global.getPlayerSocketFromRoom = function(playerId, roomId){
return roomData[roomId].playerData[playerId].socketId;
}
// Globals for easier clientside alerts/logs, etc.
@ -64,3 +74,58 @@ global.socketAlert = function(socket, message, type = 'alert'){
);
}
// passTurn response for all clients in room
// TODO: include spectators when added
global.socketResponsePassTurn = function(roomId){
let clients = global.io.sockets.adapter.rooms.get(roomId);
for (const clientId of clients) {
const clientSocket = global.io.sockets.sockets.get(clientId);
console.log('>> '+clientSocket.playerId+' passed turn');
// Send the data back. Whose turn it is, and what turn
let turnData = {
'playerTurn': global.roomData[roomId].itemData.component.playerTurn,
'turn': global.roomData[roomId].itemData.component.turn,
};
global.io.to(clientSocket.id).emit('responsePassTurn', turnData);
}
}
// Then emit the deckSize and hand size to all the player's sockets
// TODO: spectators in future, won't comment about this from now on
global.socketResponseDrawCard = function(roomId, playerId){
let clients = global.io.sockets.adapter.rooms.get(roomId);
for (const clientId of clients) {
const clientSocket = global.io.sockets.sockets.get(clientId);
console.log('>> '+roomData[roomId].playerData[playerId].playerId+' drew card');
// Send the data back
global.io.to(clientSocket.id).emit(
'responseDrawCard'
,global.roomData[roomId].itemData.component.cardCount
);
}
}
global.socketResponsePlayerDrewCard = function(roomId, playerId){
// This function may be redundant fast, as hand, board, grave, void
// anywhere that's visible to one (or both) players will need all the data
// sending, so will likely be one function that returns it all?
// Could do each thing as their own, and union the data too?
global.io.to(global.getPlayerSocketFromRoom(playerId, roomId)).emit(
'responsePlayerDrewCard'
,gameMod.getPlayerHandData(roomId, playerId)
);
}

Loading…
Cancel
Save