diff --git a/public/game.html b/public/game.html index 397b0c88bce90770e96d1bb4df76d5b3caf1df45..80e94909daa1c6ed8265db5c03645fb382ff4436 100644 --- a/public/game.html +++ b/public/game.html @@ -80,6 +80,16 @@ ); ctx.fillStyle = "white"; } + if (board[i][j].type === 4) { + ctx.fillStyle = "yellow"; + ctx.fillRect( + j * widthStep + 1, + i * heightStep + 1, + widthStep - 2, + heightStep - 2, + ); + ctx.fillStyle = "white"; + } } } }; diff --git a/src/game/game.js b/src/game/game.js index 4210b6efa7cff5c325eabbee82393e995ebd94e5..1087a46df079a33437644b2fbccf65e4c9ce60ce 100644 --- a/src/game/game.js +++ b/src/game/game.js @@ -3,6 +3,7 @@ const cellTypes = { PLAYERHEAD: 1, PLAYERBODY: 2, FOOD: 3, + BANANA: 4 }; function createCell(x, y, type) { @@ -31,12 +32,19 @@ function addFood(gameBoard) { } } + let bananaExists = gameBoard.some(row => row.some(cell => cell.type === cellTypes.BANANA)); + //Create food cells randomly if (emptySpaces.length > 0) { let randomCell = emptySpaces[getRandomInt(emptySpaces.length)]; randomCell.type = cellTypes.FOOD; } + if (!bananaExists && emptySpaces.length > 0) { + let randomCell = emptySpaces[getRandomInt(emptySpaces.length)]; + randomCell.type = cellTypes.BANANA; + } + return gameBoard; } @@ -90,7 +98,10 @@ module.exports = { }, moveOneStep: (gameBoard) => { - //Loop through board until we find a PLAYERHEAD + // Save board state to allow multiple snake movements + let updatedBoard = gameBoard.map(row => row.map(cell => ({ ...cell }))); + + // Loop through board until we find a PLAYERHEAD for (var i = 0; i < gameBoard.length; i++) { for (var j = 0; j < gameBoard[i].length; j++) { let cell = gameBoard[i][j]; @@ -99,10 +110,10 @@ module.exports = { let oldY = cell.y; let newX = oldX; let newY = oldY; - - let tempVar = cell.direction; - //New position based on direction + let tempVar = cell.direction; + + // New position based on direction if (cell.direction === 0) { // Up newY -= 1; @@ -117,52 +128,80 @@ module.exports = { newX -= 1; } - //Continue if within bounds + // Check for collisions with walls if ( - newX >= 0 && - newX < gameBoard[0].length && - newY >= 0 && - newY < gameBoard.length + newX < 0 || + newX >= gameBoard[0].length || + newY < 0 || + newY >= gameBoard.length ) { - //Snake head to new position by updating cell object - let newHeadCell = createCell(newX, newY, cellTypes.PLAYERHEAD); - newHeadCell.pid = cell.pid; - gameBoard[newY][newX] = newHeadCell; - - newHeadCell.direction = tempVar; - gameBoard[newY][newX] = newHeadCell; - - //Remove previous head position - gameBoard[oldY][oldX] = createCell(oldX, oldY, cellTypes.EMPTY); - - //Snake body to previous locations - let currentBody = gameBoard[newY][newX].next; - while (currentBody) { - let bodyOldX = currentBody.x; - let bodyOldY = currentBody.y; - currentBody.x = oldX; - currentBody.y = oldY; - - //Update cell body position - gameBoard[oldY][oldX] = { - ...currentBody, - type: cellTypes.PLAYERBODY, - }; - oldX = bodyOldX; - oldY = bodyOldY; - currentBody = currentBody.next; - } - - //Remove previous body position - gameBoard[oldY][oldX] = createCell(oldX, oldY, cellTypes.EMPTY); - - console.log(gameBoard); - return gameBoard; + console.log(`Player ${cell.pid} has collided with the wall!`); + // Remove the player from the game (indicating death) + updatedBoard = updatedBoard.map(row => + row.map(c => (c.pid === cell.pid ? createCell(c.x, c.y, cellTypes.EMPTY) : c)) + ); + continue; + } + + // Handle collision with food + if (gameBoard[newY][newX].type === cellTypes.FOOD) { + console.log(`Player ${cell.pid} has eaten the food!`); + // Add new body segment at the current head's position + let newBodySegment = createCell(oldX, oldY, cellTypes.PLAYERBODY); + newBodySegment.pid = cell.pid; + newBodySegment.next = cell.next; + cell.next = newBodySegment; + // Place new food somewhere else + updatedBoard = addFood(updatedBoard); + } + + // Handle collision with banana + if (gameBoard[newY][newX].type == cellTypes.BANANA) { + console.log('Slip'); + updatedBoard[newY][newX] = createCell(newX, newY, cellTypes.EMPTY); + updatedBoard = updatedBoard.map(row => + row.map(c => (c.pid === cell.pid ? createCell(c.x, c.y, cellTypes.EMPTY) : c)) + ); + updatedBoard = addFood(updatedBoard); + continue; + } + + // Snake head to new position by updating cell object + let newHeadCell = createCell(newX, newY, cellTypes.PLAYERHEAD); + newHeadCell.pid = cell.pid; + newHeadCell.direction = tempVar; + newHeadCell.next = cell.next; + updatedBoard[newY][newX] = newHeadCell; + + // Remove previous head position + updatedBoard[oldY][oldX] = createCell(oldX, oldY, cellTypes.EMPTY); + + // Move the body segments + let currentBody = newHeadCell.next; + while (currentBody) { + let bodyOldX = currentBody.x; + let bodyOldY = currentBody.y; + currentBody.x = oldX; + currentBody.y = oldY; + + // Update cell body position + updatedBoard[oldY][oldX] = { + ...currentBody, + type: cellTypes.PLAYERBODY, + }; + oldX = bodyOldX; + oldY = bodyOldY; + currentBody = currentBody.next; + } + + // Remove previous body position if it's no longer part of the snake + if (oldX !== newHeadCell.x || oldY !== newHeadCell.y) { + updatedBoard[oldY][oldX] = createCell(oldX, oldY, cellTypes.EMPTY); } } } } - return gameBoard; + return updatedBoard; }, checkCollisions: (gameBoard) => {