From 4cdabd0b6ec10b178c898f762cbfec722cf87af6 Mon Sep 17 00:00:00 2001 From: Klemek Date: Tue, 8 Jan 2019 09:21:49 +0100 Subject: [PATCH] Scores + game restart + fixes --- README.md | 1 + client/main.js | 63 ++++++++++++++++++++++++++++++++--------------- preview2.png | Bin 0 -> 31872 bytes server.js | 65 ++++++++++++++++++++++++++++++++++++++++++------- 4 files changed, 101 insertions(+), 28 deletions(-) create mode 100644 preview2.png diff --git a/README.md b/README.md index 267bde6..c7df7e2 100644 --- a/README.md +++ b/README.md @@ -15,3 +15,4 @@ npm start ``` it's now listening on *:3001 +![preview2](preview2.png) \ No newline at end of file diff --git a/client/main.js b/client/main.js index 17d2955..1b50cd3 100644 --- a/client/main.js +++ b/client/main.js @@ -5,6 +5,9 @@ let hsize = 300; let current; let players; let room; +let lastScores; +let leaderboard; +let lock; let history = {}; function ellipse(cx, cy, rx, ry) { @@ -26,14 +29,17 @@ function drawPlayer(ratio, p) { ellipse(p.pos.x, p.pos.y, ratio * 3, ratio * 3); if (p.starting > 0) return; - if (!history[p.name]) - history[p.name] = { - i0: 0, - list: new Array(hsize) - }; - else - history[p.name].i0 = (history[p.name].i0 + 1) % hsize; - history[p.name].list[history[p.name].i0] = p.pos; + + if (!lock) { + if (!history[p.name]) + history[p.name] = { + i0: 0, + list: new Array(hsize) + }; + else + history[p.name].i0 = (history[p.name].i0 + 1) % hsize; + history[p.name].list[history[p.name].i0] = p.pos; + } } if (history[p.name]) { @@ -70,30 +76,29 @@ function drawGame() { ctx.clearRect(0, 0, canvas.width, canvas.height); const ratio = canvas.height / window.innerHeight; - const writeTitleText = function (txt, x, y) { - ctx.font = `bold 120px Roboto`; - ctx.textAlign = 'center'; - + const writeText = function (txt, size, x, y, font) { + ctx.font = `${font} ${size}px Roboto`; const lines = txt.split('\n'); - lines.forEach(function (line, i) { ctx.fillStyle = '#4b4b4b'; - ctx.fillText(line, x - 3, y + 37 - (120 * lines.length) / 2 + 120 * i); + ctx.fillText(line, x - size / 40, y + size / 2 - (size * lines.length) / 2 + size * i - size / 40); ctx.fillStyle = '#545454'; - ctx.fillText(line, x, y + 40 - (120 * lines.length) / 2 + 120 * i); + ctx.fillText(line, x, y + size / 2 - (size * lines.length) / 2 + size * i); }); - - }; - writeTitleText(`snex.io\n#${room}`, canvas.width / 2, canvas.height / 2); + ctx.textAlign = 'center'; + writeText(`snex.io\n#${room}`, 120, canvas.width / 2, canvas.height / 2, 'bold'); + + ctx.textAlign = 'left'; + writeText(leaderboard, 30, canvas.width / 30, canvas.height / 15, 'normal'); ctx.lineCap = 'round'; ctx.lineJoin = 'round'; ctx.lineWidth = 3; ctx.textAlign = 'left'; - ctx.font = `normal ${ratio * 10}px Roboto`; + ctx.font = `normal ${ratio * 15}px Roboto`; const names = Object.keys(players); names.forEach(function (name) { drawPlayer(ratio, players[name]); @@ -104,6 +109,16 @@ function drawGame() { requestAnimationFrame(drawGame); } +function updateLeaderboard() { + const pl = Object.keys(players); + const scores = pl.map(p => `${players[p].score} - ${p}`).join('\n'); + if (!lastScores || scores !== lastScores) { + lastScores = scores; + pl.sort((p1, p2) => players[p2].score - players[p1].score); + leaderboard = pl.map(p => `${players[p].score} - ${p}` + (p === current.name ? ' *' : '')).join('\n'); + } +} + const socket = io({ 'reconnection': true, 'reconnectionDelay': 1000, @@ -128,6 +143,7 @@ socket.on('info', function (res) { players = res.players; room = res.room; window.location.hash = '#' + room; + updateLeaderboard(); drawGame(); $(window).focus(function () { socket.emit('history', current); @@ -138,8 +154,13 @@ socket.on('history', function (h) { history = h; }); +socket.on('lock', function (l) { + lock = l; +}); + socket.on('players', function (p) { players = p; + updateLeaderboard(); }); const keys = {}; @@ -167,6 +188,10 @@ $(document).on('keydown', function (e) { $(document).on('keyup', function (e) { switch (e.keyCode) { + case 32://space; + current.color = 'new'; + socket.emit('update', current); + return; case 37://left; if (keys[39]) changeAngle(1); diff --git a/preview2.png b/preview2.png new file mode 100644 index 0000000000000000000000000000000000000000..f4801637a968266d141b1083b98952602918f9a6 GIT binary patch literal 31872 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 OPfc|lwOkde;Qs}pM6eV9 literal 0 HcmV?d00001 diff --git a/server.js b/server.js index a1c2d4a..be03e69 100644 --- a/server.js +++ b/server.js @@ -55,9 +55,44 @@ let playerCount = 0; setInterval(function () { //main loop - Object.keys(rooms).forEach(function (room) { - Object.keys(rooms[room].players).forEach(function (name) { - const p = rooms[room].players[name]; + Object.keys(rooms).forEach(function (rname) { + const room = rooms[rname]; + const pl = Object.keys(room.players); + + if (room.waiting > 0) { + room.waiting -= 20; + if (room.waiting <= 0) { //restart + process.stdout.write(`\rroom #${rname} > restarting game \n`); + room.history = {}; + pl.forEach(function (name) { + const p = room.players[name]; + room.players[name] = { + pos: { + x: randInt(100, MAXX - 100), + y: randInt(100, MAXY - 100) + }, + angle: Math.random() * Math.PI, + angleSpd: 0, + color: p.color, + name: p.name, + alive: true, + starting: 2000, + score: p.score + }; + room.history[name] = { + i0: -1, + list: new Array(HSIZE) + } + }); + io.to(rname).emit('players', room.players); + io.to(rname).emit('history', room.history); + io.to(rname).emit('lock', false); + } + return; + } + + pl.forEach(function (name) { + const p = room.players[name]; if (p.alive) { const lastpos = clone(p.pos); p.pos.x += SPD * Math.cos(p.angle); @@ -82,7 +117,7 @@ setInterval(function () { } if (p.starting <= 0) { - const h = rooms[room].history[name]; + const h = room.history[name]; h.i0 = (h.i0 + 1) % HSIZE; h.list[h.i0] = clone(p.pos); } @@ -94,9 +129,9 @@ setInterval(function () { if (ds >= SPD * 1.1) process.stdout.write(`\r${name} moved too quickly : ${ds} [${lastpos.x},${lastpos.y}]->[${p.pos.x},${p.pos.y}]\n`); - Object.keys(rooms[room].history).forEach(function (name2) { + Object.keys(room.history).forEach(function (name2) { if (p.alive && name !== name2) { - const h2 = rooms[room].history[name2]; + const h2 = room.history[name2]; let lastpoint = h2.list[h2.i0]; if (!lastpoint) return; @@ -106,7 +141,7 @@ setInterval(function () { if (Math.abs(lastpoint.x - point.x) < 1600 * .9 && Math.abs(lastpoint.y - point.y) < 900 * .9) { intersectCount++; if (intersects(lastpos, p.pos, lastpoint, point)) { - process.stdout.write(`\r${name} collided with ${name2} \n`); + process.stdout.write(`\rroom #${rname} > ${name} collided with ${name2} \n`); p.alive = false; break; } @@ -125,7 +160,15 @@ setInterval(function () { } }); - io.to(room).emit('players', rooms[room].players); + const palive = pl.filter(p => room.players[p].alive); + + if (pl.length > 1 && palive.length === 1) { //end of game + room.players[palive[0]].score++; + room.waiting = 3000; + process.stdout.write(`\rroom #${rname} > ${palive[0]} won \n`); + io.to(rname).emit('lock', true); + } + io.to(rname).emit('players', room.players); }); updateCount++; }, 20); @@ -154,6 +197,7 @@ io.on('connection', function (socket) { if (!rooms[socket.room]) { rooms[socket.room] = { + waiting: 0, players: {}, history: {} } @@ -169,7 +213,8 @@ io.on('connection', function (socket) { color: randomColor(), name: socket.name, alive: true, - starting: 2000 + starting: 2000, + score: 0 }; rooms[socket.room].history[socket.name] = { i0: -1, @@ -215,6 +260,8 @@ io.on('connection', function (socket) { } if (!p.alive) return; + if (newp.color === 'new') + rooms[socket.room].players[newp.name].color = randomColor(); if (newp.angleSpd > 0) rooms[socket.room].players[newp.name].angleSpd = MAX_ANGLE_SPEED; else if (newp.angleSpd < 0)