From f9a5fcbaeff213535ac75c54dbb6a532e561f9c8 Mon Sep 17 00:00:00 2001 From: Jake Dreher <jdreherschool@gmail.com> Date: Wed, 4 Sep 2024 17:06:03 -0400 Subject: [PATCH] Rebase working changes into new branch --- src/game/game.js | 144 ++++++++++++++++++----------------- src/models/WebSocketModel.js | 77 +++++++++++-------- 2 files changed, 121 insertions(+), 100 deletions(-) diff --git a/src/game/game.js b/src/game/game.js index fc6b118..801a4c2 100644 --- a/src/game/game.js +++ b/src/game/game.js @@ -7,6 +7,14 @@ const cellTypes = { BORDER: 5, }; +const COLLISIONTYPES = { + NONE: 0, + FOOD: 1, + BANANA: 2, + BORDER: 3, + SNAKE: 4, +}; + function createCell(x, y, type) { return { x: x, @@ -51,8 +59,39 @@ function addFood(gameBoard) { return gameBoard; } +function checkCollisions(newY, newX, gameBoard) { + // returns a list of players that have collided, + // and a new gameBoard with the players removed + if ( + newX < 0 || + newX >= gameBoard[0].length || + newY < 0 || + newY >= gameBoard.length + ) { + console.log(`Player has collided with the wall!`); + return COLLISIONTYPES.BORDER; + } + //Handle collision with food + if (gameBoard[newY][newX].type === cellTypes.FOOD) { + console.log(`Player has eaten the food!`); + return COLLISIONTYPES.FOOD; + } + //Handle collision with banana + if (gameBoard[newY][newX].type == cellTypes.BANANA) { + console.log("Slip"); + return COLLISIONTYPES.BANANA; + } + //Handle collision with border + if (gameBoard[newY][newX].type == cellTypes.BORDER) { + console.log("Void"); + return COLLISIONTYPES.BORDER; + } + return COLLISIONTYPES.NONE; +} + module.exports = { cellTypes, + COLLISIONTYPES, createGameBoard: (width, height) => { let gameBoard = []; @@ -103,6 +142,7 @@ module.exports = { moveOneStep: (gameBoard) => { //Save board state to allow multiple snake movements let updatedBoard = gameBoard.map((row) => row.map((cell) => ({ ...cell }))); + let deadPlayers = []; //Loop through board until we find a PLAYERHEAD for (var i = 0; i < gameBoard.length; i++) { @@ -131,57 +171,28 @@ module.exports = { newX -= 1; } - //Check for collisions with walls + let collision = checkCollisions(newY, newX, gameBoard); + if ( - newX < 0 || - newX >= gameBoard[0].length || - newY < 0 || - newY >= gameBoard.length + collision === COLLISIONTYPES.BANANA || + collision === COLLISIONTYPES.FOOD ) { - console.log(`Player ${cell.pid} has collided with the wall!`); - //Remove the player from the game (indicating death) + updatedBoard = addFood(updatedBoard); + } + if (collision > COLLISIONTYPES.FOOD) { updatedBoard = updatedBoard.map((row) => row.map((c) => c.pid === cell.pid ? createCell(c.x, c.y, cellTypes.EMPTY) : c, ), ); + deadPlayers.push(cell.pid); 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 + if (collision === COLLISIONTYPES.FOOD) { 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; - } - - //Handle collision with border - if (gameBoard[newY][newX].type == cellTypes.BORDER) { - console.log("Void"); - updatedBoard = updatedBoard.map((row) => - row.map((c) => - c.pid === cell.pid ? createCell(c.x, c.y, cellTypes.EMPTY) : c, - ), - ); - continue; } //Snake head to new position by updating cell object @@ -219,63 +230,58 @@ module.exports = { } } } - return updatedBoard; + return [updatedBoard, deadPlayers]; }, applyBorders: (gameBoard, borderCounter) => { let height = gameBoard.length; - let width = gameBoard[0].length; - - //console.log(borderCounter); + let width = gameBoard[0].length; + + //console.log(borderCounter); //Return gameBoard when it is 2x2 - if (borderCounter * 2 >= (Math.min(height, width)) - 2) { + if (borderCounter * 2 >= Math.min(height, width) - 2) { return gameBoard; } //Top - for (let x = 0; x < width; x++) { + for (let x = 0; x < width; x++) { gameBoard[borderCounter][x].type = cellTypes.BORDER; - gameBoard[borderCounter][x].pid = 0; - gameBoard[borderCounter][x].direction = 0; - gameBoard[borderCounter][x].next = null; + gameBoard[borderCounter][x].pid = 0; + gameBoard[borderCounter][x].direction = 0; + gameBoard[borderCounter][x].next = null; } //Bottom - for (let x = 0; x < width; x++) { + for (let x = 0; x < width; x++) { gameBoard[height - borderCounter - 1][x].type = cellTypes.BORDER; - gameBoard[height - borderCounter - 1][x].pid = 0; - gameBoard[height - borderCounter - 1][x].direction = 0; - gameBoard[height - borderCounter - 1][x].next = null; + gameBoard[height - borderCounter - 1][x].pid = 0; + gameBoard[height - borderCounter - 1][x].direction = 0; + gameBoard[height - borderCounter - 1][x].next = null; } //Left - for (let y = 0; y < height; y++) { + for (let y = 0; y < height; y++) { gameBoard[y][borderCounter].type = cellTypes.BORDER; - gameBoard[y][borderCounter].pid = 0; - gameBoard[y][borderCounter].direction = 0; - gameBoard[y][borderCounter].next = null; + gameBoard[y][borderCounter].pid = 0; + gameBoard[y][borderCounter].direction = 0; + gameBoard[y][borderCounter].next = null; } //Right - for (let y = 0; y < height; y++) { + for (let y = 0; y < height; y++) { gameBoard[y][width - borderCounter - 1].type = cellTypes.BORDER; - gameBoard[y][width - borderCounter - 1].pid = 0; - gameBoard[y][width - borderCounter - 1].direction = 0; - gameBoard[y][width - borderCounter - 1].next = null; + gameBoard[y][width - borderCounter - 1].pid = 0; + gameBoard[y][width - borderCounter - 1].direction = 0; + gameBoard[y][width - borderCounter - 1].next = null; } - - return gameBoard; + + return gameBoard; }, - getPlayerView: (gameBoard, pid) => { + getPlayerView: (gameBoard, pid) => { let updatedBoard = gameBoard.map((row) => row.map((cell) => ({ ...cell }))); - // YANG: Find head with pid = pid - // return [x][y] around head - }, - - checkCollisions: (gameBoard) => { - // returns a list of players that have collided, - // and a new gameBoard with the players removed + // YANG: Find head with pid = pid + // return [x][y] around head }, }; diff --git a/src/models/WebSocketModel.js b/src/models/WebSocketModel.js index 43336e4..7114a60 100644 --- a/src/models/WebSocketModel.js +++ b/src/models/WebSocketModel.js @@ -2,6 +2,50 @@ const { WebSocketServer } = require("ws"); const gameModule = require("../game/game.js"); class WebSocketModel { + createInterval(game) { + setInterval(() => { + if (!this.games[game].started) return; + let deadPlayers = []; + + [this.games[game].gameBoard, deadPlayers] = gameModule.moveOneStep( + this.games[game].gameBoard, + ); + + if (!this.games[game].elapsedTime) { + this.games[game].elapsedTime = 0; + } + this.games[game].elapsedTime++; + + //Every 10 seconds, generate borders + if (this.games[game].elapsedTime % 10 === 0) { + this.games[game].gameBoard = gameModule.applyBorders( + this.games[game].gameBoard, + this.games[game].borderCounter, + ); + this.games[game].borderCounter++; + } + + if (deadPlayers.length > 0) { + for (let conn of this.games[game].players) { + conn.send( + JSON.stringify({ + type: "deadPlayers", + data: deadPlayers, + }), + ); + } + } + + for (let conn of this.games[game].players) { + conn.send( + JSON.stringify({ + type: "gameBoard", + data: this.games[game].gameBoard, // YANG: gameModule.getPlayerView()... + }), + ); + } + }, 1000); + } constructor() { this.connections = []; this.games = {}; @@ -34,37 +78,7 @@ class WebSocketModel { this.onConnection(); for (let game in this.games) { - setInterval(() => { - if (!this.games[game].started) return; - - this.games[game].gameBoard = gameModule.moveOneStep( - this.games[game].gameBoard, - ); - - if (!this.games[game].elapsedTime) { - this.games[game].elapsedTime = 0; - } - - this.games[game].elapsedTime++; - - //Every 10 seconds, generate borders - if (this.games[game].elapsedTime % 10 === 0) { - this.games[game].gameBoard = gameModule.applyBorders( - this.games[game].gameBoard, - this.games[game].borderCounter - ); - this.games[game].borderCounter++; - } - - for (let conn of this.games[game].players) { - conn.send( - JSON.stringify({ - type: "gameBoard", - data: this.games[game].gameBoard, // YANG: gameModule.getPlayerView()... - }), - ); - } - }, 1000); + this.createInterval(game); } } @@ -89,6 +103,7 @@ class WebSocketModel { readyPlayers: 0, borderCounter: 0, }; + this.createInterval(gameId); } moveHandler(connection, message) { -- GitLab