From b7589fff99155ccdcc632d1965f8758e869dc2e6 Mon Sep 17 00:00:00 2001 From: Klemek Date: Tue, 8 Jan 2019 08:39:05 +0100 Subject: [PATCH] Game rooms with page hash --- client/main.js | 39 +++++--- server.js | 245 ++++++++++++++++++++++++++++--------------------- 2 files changed, 169 insertions(+), 115 deletions(-) diff --git a/client/main.js b/client/main.js index 7facaf9..17d2955 100644 --- a/client/main.js +++ b/client/main.js @@ -4,7 +4,7 @@ const ctx = canvas.getContext('2d'); let hsize = 300; let current; let players; - +let room; let history = {}; function ellipse(cx, cy, rx, ry) { @@ -70,13 +70,23 @@ function drawGame() { ctx.clearRect(0, 0, canvas.width, canvas.height); const ratio = canvas.height / window.innerHeight; - ctx.font = `bold ${ratio * 120}px Roboto`; - ctx.textAlign = 'center'; + const writeTitleText = function (txt, x, y) { + ctx.font = `bold 120px Roboto`; + ctx.textAlign = 'center'; - ctx.fillStyle = '#4b4b4b'; - ctx.fillText('snex.io', canvas.width / 2 - ratio * 3, canvas.height / 2 + ratio * 37); - ctx.fillStyle = '#545454'; - ctx.fillText('snex.io', canvas.width / 2, canvas.height / 2 + ratio * 40); + 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.fillStyle = '#545454'; + ctx.fillText(line, x, y + 40 - (120 * lines.length) / 2 + 120 * i); + }); + + + }; + + writeTitleText(`snex.io\n#${room}`, canvas.width / 2, canvas.height / 2); ctx.lineCap = 'round'; ctx.lineJoin = 'round'; @@ -101,9 +111,11 @@ const socket = io({ }); socket.on('connect', function () { console.log('connected'); - $(window).focus(function () { - socket.emit('history', current); - }); + if (window.location.hash) { + socket.emit('room', window.location.hash.slice(1)); + } else { + socket.emit('room', undefined); + } }); socket.on('disconnect', function () { console.log('disconnected'); @@ -114,7 +126,12 @@ socket.on('info', function (res) { history = res.history; hsize = res.hsize; players = res.players; - drawGame() + room = res.room; + window.location.hash = '#' + room; + drawGame(); + $(window).focus(function () { + socket.emit('history', current); + }); }); socket.on('history', function (h) { diff --git a/server.js b/server.js index bf243b6..a1c2d4a 100644 --- a/server.js +++ b/server.js @@ -5,7 +5,7 @@ const convert = require('color-convert'); const fs = require('fs'); app.get('*', function (req, res) { - if(req.originalUrl === '/') + if (req.originalUrl === '/') res.sendFile(`${__dirname}/client/index.html`); else if (fs.existsSync(`${__dirname}/client${req.originalUrl}`)) res.sendFile(`${__dirname}/client${req.originalUrl}`); @@ -33,12 +33,12 @@ function intersects(a1, a2, b1, b2) { } } -function dist(a1,a2){ - return Math.sqrt(Math.pow(a1.x-a2.x,2)+Math.pow(a1.y-a2.y,2)); +function dist(a1, a2) { + return Math.sqrt(Math.pow(a1.x - a2.x, 2) + Math.pow(a1.y - a2.y, 2)); } -function clone(a){ - return {x:parseFloat(a.x),y:parseFloat(a.y)}; +function clone(a) { + return {x: parseFloat(a.x), y: parseFloat(a.y)}; } const HSIZE = 300; @@ -47,131 +47,168 @@ const MAXY = 900; const SPD = 5; const MAX_ANGLE_SPEED = Math.PI / 32; -const players = {}; -const history = {}; +const rooms = {}; -let upc = 0; -let ic = 0; +let updateCount = 0; +let intersectCount = 0; +let playerCount = 0; setInterval(function () { //main loop - Object.keys(players).forEach(function (name) { - const p = players[name]; - if (p.alive) { - const lastpos = clone(p.pos); - p.pos.x += SPD * Math.cos(p.angle); - p.pos.y += SPD * Math.sin(p.angle); - p.angle += p.angleSpd; - let exempt = false; - if (p.pos.x > MAXX){ - p.pos.x = 0; - exempt = true; - } - if (p.pos.x < 0){ - p.pos.x = MAXX; - exempt = true; - } - if (p.pos.y > MAXY){ - p.pos.y = 0; - exempt = true; - } - if (p.pos.y < 0){ - p.pos.y = MAXY; - exempt = true; - } + Object.keys(rooms).forEach(function (room) { + Object.keys(rooms[room].players).forEach(function (name) { + const p = rooms[room].players[name]; + if (p.alive) { + const lastpos = clone(p.pos); + p.pos.x += SPD * Math.cos(p.angle); + p.pos.y += SPD * Math.sin(p.angle); + p.angle += p.angleSpd; + let exempt = false; + if (p.pos.x > MAXX) { + p.pos.x = 0; + exempt = true; + } + if (p.pos.x < 0) { + p.pos.x = MAXX; + exempt = true; + } + if (p.pos.y > MAXY) { + p.pos.y = 0; + exempt = true; + } + if (p.pos.y < 0) { + p.pos.y = MAXY; + exempt = true; + } - if(p.starting <= 0){ - const h = history[name]; - h.i0 = (h.i0 + 1) % HSIZE; - h.list[h.i0] = clone(p.pos); - } + if (p.starting <= 0) { + const h = rooms[room].history[name]; + h.i0 = (h.i0 + 1) % HSIZE; + h.list[h.i0] = clone(p.pos); + } - if(!exempt && p.starting <= 0){ - const ds = dist(lastpos,p.pos); - if(ds <= SPD*0.9) - process.stdout.write(`\r${name} moved too slowly : ${ds} [${lastpos.x},${lastpos.y}]->[${p.pos.x},${p.pos.y}]\n`); - 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`); + if (!exempt && p.starting <= 0) { + const ds = dist(lastpos, p.pos); + if (ds <= SPD * 0.9) + process.stdout.write(`\r${name} moved too slowly : ${ds} [${lastpos.x},${lastpos.y}]->[${p.pos.x},${p.pos.y}]\n`); + 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(history).forEach(function (name2) { - if (p.alive && name !== name2) { - const h2 = history[name2]; - let lastpoint = h2.list[h2.i0]; - if(!lastpoint) - return; - for (let di = 1; di < HSIZE; di++) { - const point = h2.list[(h2.i0 - di + HSIZE) % HSIZE]; - if (point !== undefined) { - if(Math.abs(lastpoint.x - point.x) < 1600 * .9 && Math.abs(lastpoint.y - point.y) < 900 * .9){ - ic++; - if (intersects(lastpos, p.pos, lastpoint, point)) { - process.stdout.write(`\r${name} collided with ${name2} \n`); - p.alive = false; - break; + Object.keys(rooms[room].history).forEach(function (name2) { + if (p.alive && name !== name2) { + const h2 = rooms[room].history[name2]; + let lastpoint = h2.list[h2.i0]; + if (!lastpoint) + return; + for (let di = 1; di < HSIZE; di++) { + const point = h2.list[(h2.i0 - di + HSIZE) % HSIZE]; + if (point !== undefined) { + 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`); + p.alive = false; + break; + } } + lastpoint = point; + } else { + break; } - lastpoint = point; - } else { - break; } } - } - }); + }); + } + + if (p.starting > 0) + p.starting -= 20; + } - - if(p.starting > 0) - p.starting -= 20; - - } + }); + io.to(room).emit('players', rooms[room].players); }); - io.emit('players', players); - upc++; + updateCount++; }, 20); setInterval(function () { - process.stdout.write(`\rtick ${20 * upc * 20 / 1000}/20 ms (${Object.keys(players).length} connected) (${ic} intersect/s) `); - upc = 0; - ic = 0; + process.stdout.write(`\rtick ${20 * updateCount * 20 / 1000}/20 ms (${Object.keys(rooms).length} rooms) (${playerCount} players) (${intersectCount} intersect/s) `); + updateCount = 0; + intersectCount = 0; }, 1000); io.on('connection', function (socket) { socket.name = '#' + ('0000' + randInt(0, 10000)).slice(-4); process.stdout.write(`\r${socket.name} connected \n`); - players[socket.name] = { - pos: { - x: randInt(100, MAXX - 100), - y: randInt(100, MAXY - 100) - }, - angle: Math.random() * Math.PI, - angleSpd: 0, - color: randomColor(), - name: socket.name, - alive: true, - starting: 2000 - }; - history[socket.name] = { - i0: -1, - list: new Array(HSIZE) - }; - socket.emit('info', { - self:players[socket.name], - players:players, - history:history, - hsize:HSIZE + playerCount++; + + socket.on('room', function (name) { + if (socket.room) + return; + if (name) { + socket.room = name; + } else { + socket.room = ('000000' + randInt(0, 1000000)).slice(-4); + } + + socket.join(socket.room); + + if (!rooms[socket.room]) { + rooms[socket.room] = { + players: {}, + history: {} + } + } + + rooms[socket.room].players[socket.name] = { + pos: { + x: randInt(100, MAXX - 100), + y: randInt(100, MAXY - 100) + }, + angle: Math.random() * Math.PI, + angleSpd: 0, + color: randomColor(), + name: socket.name, + alive: true, + starting: 2000 + }; + rooms[socket.room].history[socket.name] = { + i0: -1, + list: new Array(HSIZE) + }; + + socket.emit('info', { + room: socket.room, + self: rooms[socket.room].players[socket.name], + players: rooms[socket.room].players, + history: rooms[socket.room].history, + hsize: HSIZE + }); + + process.stdout.write(`\rroom #${socket.room} > ${socket.name} connected \n`); }); socket.on('history', function () { - socket.emit('history', history); + if (socket.room) + socket.emit('history', rooms[socket.room].history); }); socket.on('disconnect', function () { - delete players[socket.name]; - delete history[socket.name]; - process.stdout.write(`\r${socket.name} disconnected \n`); - io.emit('players', players); + playerCount--; + if (!socket.room) + return; + delete rooms[socket.room].players[socket.name]; + delete rooms[socket.room].history[socket.name]; + process.stdout.write(`\rroom #${socket.room} > ${socket.name} disconnected \n`); + if (Object.keys(rooms[socket.room].players).length === 0) { + delete rooms[socket.room]; + process.stdout.write(`\rroom #${socket.room} deleted \n`); + } }); + socket.on('update', function (newp) { - const p = players[newp.name]; + if (!socket.room) + return; + const p = rooms[socket.room].players[newp.name]; if (!p) { socket.disconnect(); return; @@ -179,11 +216,11 @@ io.on('connection', function (socket) { if (!p.alive) return; if (newp.angleSpd > 0) - players[newp.name].angleSpd = MAX_ANGLE_SPEED; + rooms[socket.room].players[newp.name].angleSpd = MAX_ANGLE_SPEED; else if (newp.angleSpd < 0) - players[newp.name].angleSpd = -MAX_ANGLE_SPEED; + rooms[socket.room].players[newp.name].angleSpd = -MAX_ANGLE_SPEED; else - players[newp.name].angleSpd = 0; + rooms[socket.room].players[newp.name].angleSpd = 0; }); });