diff --git a/client/index.css b/client/index.css index 9ab203e..b5eb064 100644 --- a/client/index.css +++ b/client/index.css @@ -68,7 +68,6 @@ canvas { height: 512px; background-color: #03A9F4; margin: 10px; - /*border: 5px solid #2196F3;*/ } .boxlayout { text-align: center; @@ -151,5 +150,47 @@ button#leave { width: 200px; } #game_canvas { - margin-left: 265px; + margin-left: 300px; +} +.endresult { + text-align: center; +} +.result { + width: 530px; + display: inline-block; +} +button#lobby { + display: inline-block; + vertical-align: middle; + margin-left: 15px; +} +.bigstat { + font-size: 200%; + font-weight: bold; + margin-bottom: 50px; + margin-top: 10px; +} +.message.t_event { + color: #b5b5b5; +} +.message .sender { + color: red; +} +.message.me .sender { + color: blue !important; +} +.chatbox { + margin-top: 50px; + padding: 5px; + background-color: #f9f9f9; + border: 1px solid #ddd; + border-radius: 5px; +} +#messages { + height: 250px; + background-color: #fff; + border-radius: 5px; + overflow-y: scroll; + word-wrap: break-word; + white-space: pre; } diff --git a/client/index.html b/client/index.html index 37c73bc..cf2bbf0 100644 --- a/client/index.html +++ b/client/index.html @@ -60,6 +60,24 @@ You have 0 ships left. Your opponent has 0 ships left. Your turn. +
+
+ +
+ + + diff --git a/client/index.js b/client/index.js index 01fc9fa..7b8d5a3 100644 --- a/client/index.js +++ b/client/index.js @@ -10,12 +10,9 @@ played: 0, Game: { gameId: null, - inGame: false, myTurn: true, opponentID: '', opponentName: '', - ships: 0, - oShips: 0, gridHome: {ships: [], strikes: []}, gridOpponent: [] } @@ -121,6 +118,52 @@ } }, + endResultCellRenderer(cells, ctx, ship) { + for (let i in cells) { + let cell = cells[i] + let destVar = (cell.destroyed != null ? cell.destroyed : cell.destroy) + let color = '#dddd00' + if (destVar || (ship != null && ship.sunken)) { + color = '#ff0000' + } else { + if (ship) { + color = '#dddddd' + } + } + ctx.fillStyle = color + ctx.fillRect(cell.x * GameDrawer.gridSize, cell.y * GameDrawer.gridSize, GameDrawer.gridSize, GameDrawer.gridSize) + } + }, + + resultScreen(myShips, enemyShips, myHits, enemyHits) { + let c1 = Battleship.DOM.resultScreen.querySelector('#opponent_result_canvas') + let c2 = Battleship.DOM.resultScreen.querySelector('#my_result_canvas') + let ctx1 = c1.getContext('2d') + let ctx2 = c2.getContext('2d') + + ctx1.clearRect(0, 0, Battleship.canvasW, Battleship.canvasH) + ctx2.clearRect(0, 0, Battleship.canvasW, Battleship.canvasH) + + ctx1.drawImage(GameDrawer.boardStaticState, 0, 0) + ctx2.drawImage(GameDrawer.boardStaticState, 0, 0) + + GameDrawer.endResultCellRenderer(myHits, ctx1, null) + + // Render my ship tiles + for (let i in myShips) { + let ship = myShips[i] + GameDrawer.endResultCellRenderer(ship.cells, ctx2, ship) + } + + // Render enemy ship tiles + for (let i in enemyShips) { + let ship = enemyShips[i] + GameDrawer.endResultCellRenderer(ship.cells, ctx1, ship) + } + + GameDrawer.endResultCellRenderer(enemyHits, ctx2, null) + }, + click: () => { if (GameDrawer.placingShips && GameDrawer.canPlace && GameDrawer.shipIndex != -1) { let shipData = Battleship.ships[GameDrawer.shipIndex] @@ -377,6 +420,8 @@ Battleship.Game.opponentName = game.opponentName Battleship.DOM.opponentName.innerHTML = game.opponentName + Battleship.DOM.chatbox.innerHTML = '' + io.emit('game_poll', {gameId: Battleship.Game.gameId}) logStatus('Place your ships onto the board.
Press `r` to rotate') @@ -386,6 +431,7 @@ Battleship.DOM.waitlistBtns.style.display = 'block' Battleship.DOM.waitlistQuit.style.display = 'none' GameDrawer.startGame() + addChatMessage('event', null, 'Game started!') } function attemptJoin (name) { @@ -446,8 +492,10 @@ if (reason === 1) { if (winner === true) { alert('You won!') + Battleship.DOM.winStatus.innerHTML = 'Won' } else { alert('You lost.') + Battleship.DOM.winStatus.innerHTML = 'Lost' } } @@ -458,8 +506,15 @@ Battleship.locked = false Battleship.Game.gameId = null io.emit('poll_games') + Battleship.DOM.gameScreen.style.display = 'none' - Battleship.DOM.selectionScreen.style.display = 'block' + if (reason === 1) { + Battleship.DOM.resultScreen.style.display = 'block' + } else { + Battleship.DOM.selectionScreen.style.display = 'block' + Battleship.DOM.resultScreen.style.display = 'none' + } + Battleship.DOM.waitlistBtns.style.display = 'block' Battleship.DOM.waitlistQuit.style.display = 'none' @@ -475,16 +530,37 @@ Battleship.DOM.gameScreen.style.display = 'none' Battleship.DOM.selectionScreen.style.display = 'none' Battleship.DOM.startScreen.style.display = 'block' + Battleship.DOM.resultScreen.style.display = 'none' Battleship.locked = false Battleship.playerName = '' Battleship.Game.gameId = null } + function escapeHtml(unsafe) { + return unsafe + .replace(/&/g, "&") + .replace(//g, ">") + .replace(/"/g, """) + .replace(/'/g, "'") + } + + function addChatMessage (type, senderName, message) { + let msgElem = '
' + if (senderName) { + msgElem += '' + senderName + ' ' + } + msgElem += '' + escapeHtml(message) + '' + + Battleship.DOM.chatbox.innerHTML += msgElem + } + window.onload = () => { const startScreen = Battleship.DOM.startScreen = $.querySelector('#start') const selectionScreen = Battleship.DOM.selectionScreen = $.querySelector('#selection') const gameScreen = Battleship.DOM.gameScreen = $.querySelector('#game') + const resultScreen = Battleship.DOM.resultScreen = $.querySelector('#endresult') const warning = Battleship.DOM.joinWarn = startScreen.querySelector('#warning_message') const playerName = startScreen.querySelector('#player_name') @@ -515,6 +591,12 @@ const dataMineDestroyed = Battleship.DOM.dataMineDestroyed = gameScreen.querySelector('#g_s_num') Battleship.DOM.statusCurrent = gameScreen.querySelector('#g_s_stat') + const doneBtn = resultScreen.querySelector('#lobby') + Battleship.DOM.winStatus = resultScreen.querySelector('#wonlost') + + const chatbox = Battleship.DOM.chatbox = gameScreen.querySelector('#messages') + const chatfield = Battleship.DOM.chatfield = gameScreen.querySelector('#message_send') + GameDrawer.initialize() let uname = getStored('name') @@ -528,6 +610,16 @@ } }, false) + chatfield.addEventListener('keydown', (e) => { + if (e.keyCode === 13 && Battleship.Game.gameId) { + if (chatfield.value != '') { + io.emit('chat_send', {message: chatfield.value, gameId: Battleship.Game.gameId}) + addChatMessage('chat me', Battleship.playerName, chatfield.value) + chatfield.value = '' + } + } + }) + startButton.addEventListener('click', (e) => { attemptJoin(playerName.value) }, false) @@ -544,6 +636,10 @@ io.emit('poll_games') }) + doneBtn.addEventListener('click', (e) => { + gameEnds(0, null) + }) + waitlistQuit.addEventListener('click', (e) => { io.emit('leave_game', {gameId: Battleship.Game.gameId}) }) @@ -568,6 +664,10 @@ } }) + io.on('chat', (data) => { + addChatMessage('chat', data.name, data.message) + }) + io.on('update_hits', (data) => { if (data.me) { Battleship.Game.gridHome.strikes = data.strikes @@ -576,7 +676,7 @@ } }) - io.on('updateShip', (dship) => { + io.on('update_ship', (dship) => { for (let i in Battleship.Game.gridHome.ships) { let ship = Battleship.Game.gridHome.ships[i] if (ship.name === dship.name) { @@ -623,6 +723,10 @@ forceRelogin() }) + io.on('display_result', (data) => { + GameDrawer.resultScreen(Battleship.Game.gridHome.ships, data.enemyShips, Battleship.Game.gridHome.strikes, Battleship.Game.gridOpponent) + }) + io.on('game_end', (data) => { gameEnds(data.result, data.win) }) diff --git a/server.js b/server.js index b67efcd..80d553a 100644 --- a/server.js +++ b/server.js @@ -4,17 +4,18 @@ const http = require('http') const path = require('path') // TODO LIST: -// * More ships // * Timer // * Chat box -// * Side-by-side board display const ships = [ - {name: 'biggest', tiles: 5, destCount: 4}, - {name: 'bigger', tiles: 4, destCount: 3}, - {name: 'medium', tiles: 3, destCount: 2}, - {name: 'smaller', tiles: 3, destCount: 2}, - {name: 'smallest', tiles: 2, destCount: 1} + {name: 'aircraft_carrier1', tiles: 5, destCount: 4}, + {name: 'aircraft_carrier2', tiles: 5, destCount: 4}, + {name: 'cruiser', tiles: 4, destCount: 3}, + {name: 'ferry', tiles: 3, destCount: 2}, + {name: 'fishing_ship', tiles: 3, destCount: 2}, + {name: 'destroyer', tiles: 2, destCount: 1}, + {name: 'submarine1', tiles: 1, destCount: 1}, + {name: 'submarine2', tiles: 1, destCount: 1} ] let app = express() @@ -202,6 +203,8 @@ function waitingGamesList (uid) { function determinePlayerById (gameId, uid) { let game = games[gameId] + if (!game) return null + if (game.player1 && game.player1.uid === uid) { return 'player1' } else if (game.player2 && game.player2.uid === uid) { @@ -476,7 +479,7 @@ io.on('connection', (socket) => { let me = game[playerInGame] if (result.ship) { - clients[opponentObj.uid].socket.emit('updateShip', result.ship) + clients[opponentObj.uid].socket.emit('update_ship', result.ship) } clients[me.uid].socket.emit('update_hits', {me: true, strikes: me.strikes}) @@ -499,6 +502,8 @@ io.on('connection', (socket) => { clients[me.uid].socket.emit('infmessage', 'You missed!') break case 6: + clients[opponentObj.uid].socket.emit('display_result', {enemyShips: me.ships, gameId: data.gameId}) + clients[me.uid].socket.emit('display_result', {enemyShips: opponentObj.ships, gameId: data.gameId}) endGame(data.gameId, client, opponentObj.uid) break } @@ -513,6 +518,35 @@ io.on('connection', (socket) => { }) }) + socket.on('chat_send', (data) => { + let client = clientsBySocketID(socket.conn.id) + + if (!client) { + socket.emit('game_error', {message: 'You are not logged in properly!'}) + socket.emit('force_relog') + return + } + + let game = games[data.gameId] + let playerInGame = determinePlayerById(data.gameId, client) + + if (!playerInGame) { + socket.emit('game_error', {message: 'unexpected error. code: 763'}) + return + } + + let opponent = 'player2' + + if (playerInGame === 'player2') { + opponent = 'player1' + } + + let opponentObj = game[opponent] + let me = game[playerInGame] + + clients[opponentObj.uid].socket.emit('chat', {name: clients[me.uid].name, message: data.message}) + }) + socket.on('disconnect', () => { let client = clientsBySocketID(socket.conn.id) if (!client) return