Files
snex.io/server.js
T
2019-01-07 13:48:30 +01:00

184 lines
4.8 KiB
JavaScript

const app = require('express')();
const http = require('http').Server(app);
const io = require('socket.io')(http);
const convert = require('color-convert');
app.get('/', function (req, res) {
res.sendFile(__dirname + '/client.html');
});
function randomColor() {
return '#' + convert.hsl.hex([randInt(0, 256), randInt(50, 200), 256]);
}
function randInt(min, max) {
return Math.floor(min + Math.random() * (max - min));
}
function intersects(a1, a2, b1, b2) {
let det, gamma, lambda;
det = (a2.x - a1.x) * (b2.y - b1.y) - (b2.x - b1.x) * (a2.y - a1.y);
if (det === 0) {
return false;
} else {
lambda = ((b2.y - b1.y) * (b2.x - a1.x) + (b1.x - b2.x) * (b2.y - a1.y)) / det;
gamma = ((a1.y - a2.y) * (b2.x - a1.x) + (a2.x - a1.x) * (b2.y - a1.y)) / det;
return (0 < lambda && lambda < 1) && (0 < gamma && gamma < 1);
}
}
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)};
}
const HSIZE = 300;
const MAXX = 1600;
const MAXY = 900;
const SPD = 5;
const MAX_ANGLE_SPEED = Math.PI / 32;
const players = {};
const history = {};
let upc = 0;
let ic = 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;
}
if(p.starting <= 0){
const h = 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`);
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;
}
}
lastpoint = point;
} else {
break;
}
}
}
});
}
if(p.starting > 0)
p.starting -= 20;
}
});
io.emit('players', players);
upc++;
}, 20);
setInterval(function () {
process.stdout.write(`\rtick ${20 * upc * 20 / 1000}/20 ms (${ic} intersect/s)`);
upc = 0;
ic = 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
});
socket.on('disconnect', function () {
delete players[socket.name];
delete history[socket.name];
process.stdout.write(`\r${socket.name} disconnected\n`);
io.emit('players', players);
});
socket.on('update', function (newp) {
const p = players[newp.name];
if (!p) {
socket.disconnect();
return;
}
if (!p.alive)
return;
if (newp.color === 'new')
players[newp.name].color = randomColor();
if (newp.angleSpd > 0)
players[newp.name].angleSpd = MAX_ANGLE_SPEED;
else if (newp.angleSpd < 0)
players[newp.name].angleSpd = -MAX_ANGLE_SPEED;
else
players[newp.name].angleSpd = 0;
});
});
http.listen(3001, function () {
console.log('listening on *:3001\n');
});