From 216f88f2d572c926ddb4318d21e6b559e1bb1c64 Mon Sep 17 00:00:00 2001 From: JoeMattie Date: Fri, 5 Jun 2015 07:55:15 -0800 Subject: [PATCH 01/12] A whole mess of updates and fixes. Levels are fixed size, food filtering, etc --- client/index.html | 2 +- client/js/app.js | 142 ++++++++-------------- server/config.json | 16 +-- server/server.js | 287 ++++++++++++++++++++------------------------- 4 files changed, 182 insertions(+), 265 deletions(-) diff --git a/client/index.html b/client/index.html index 689e1f56c..fe36e460e 100644 --- a/client/index.html +++ b/client/index.html @@ -32,7 +32,7 @@

Gameplay

- + diff --git a/client/js/app.js b/client/js/app.js index 72e70f150..4b7940533 100644 --- a/client/js/app.js +++ b/client/js/app.js @@ -9,7 +9,7 @@ function startGame() { document.getElementById('gameAreaWrapper').style.display = 'block'; document.getElementById('startMenuWrapper').style.display = 'none'; socket = io(); - SetupSocket(socket); + setupSocket(socket); animloop(); } @@ -52,8 +52,8 @@ window.onload = function() { // Canvas var screenWidth = window.innerWidth; var screenHeight = window.innerHeight; -var gameWidth = screenWidth * 10; -var gameHeight = screenHeight * 10; +var gameWidth = 0; +var gameHeight = 0; var xoffset = -gameWidth; var yoffset = -gameHeight; @@ -71,11 +71,11 @@ var foodConfig = { border: 0, borderColor: '#f39c12', fillColor: '#f1c40f', - size: 10 + mass: 0.5 }; var playerConfig = { - border: 15, + border: 4, textColor: '#FFFFFF', textBorder: '#000000', textBorderSize: 3, @@ -83,7 +83,7 @@ var playerConfig = { }; var enemyConfig = { - border: 15, + border: 4, textColor: '#FFFFFF', textBorder: '#000000', textBorderSize: 3, @@ -92,13 +92,10 @@ var enemyConfig = { var player = { id: -1, - x: gameWidth / 2, y: gameHeight / 2, - mass: 0, speed: 20, - //TODO: exclude width and height out of player package + x: screenWidth / 2, + y: screenHeight / 2, screenWidth: screenWidth, - screenHeight: screenHeight, - gameWidth: gameWidth, - gameHeight: gameHeight + screenHeight: screenHeight }; var foods = []; @@ -115,8 +112,6 @@ function outOfBounds() { target = { x : screenWidth / 2, y : screenHeight / 2 }; } - - var graph = c.getContext('2d'); var chatInput = document.getElementById('chatInput'); @@ -222,7 +217,7 @@ function sendChat(key) { } } -function SetupSocket(socket) { +function setupSocket(socket) { // Handle ping socket.on('pong', function () { var latency = Date.now() - startPingTime; @@ -243,16 +238,25 @@ function SetupSocket(socket) { // Handle connection socket.on('welcome', function (playerSettings) { - player.name = playerName; - player.id = playerSettings.id; - player.hue = playerSettings.hue; + player = playerSettings; + player.name = playerName; + player.screenWidth = screenWidth; + player.screenHeight = screenHeight; socket.emit('gotit', player); + + // playerBall.fill = 'hsl(' + playerSettings.hue + ', 100%, 60%)'; + gameStart = true; console.log('Game is started: ' + gameStart); addSystemLine('Connected to the game!'); addSystemLine('Type -help for a list of commands'); }); + socket.on('gameSetup', function(data){ + gameWidth = data.gameWidth; + gameHeight = data.gameHeight; + }); + socket.on('playerDisconnect', function (data) { enemies = data.playersList; document.getElementById('status').innerHTML = 'Players: ' + enemies.length; @@ -282,19 +286,16 @@ function SetupSocket(socket) { }); // Handle movement - socket.on('serverTellPlayerMove', function (playerData, foodsList) { - xoffset += (player.x - playerData.x); - yoffset += (player.y - playerData.y); + socket.on('serverTellPlayerMove', function (playerData, userData, foodsList) { + var xoffset = player.x - playerData.x; + var yoffset = player.y - playerData.y; player = playerData; + player.xoffset = isNaN(xoffset) ? 0 : xoffset; + player.yoffset = isNaN(yoffset) ? 0 : yoffset; + // console.log(xoffset); + enemies = userData; if(foodsList !== 0){ - foods = foodsList; - } - }); - - socket.on('serverUpdateAll', function (players, foodsList) { - enemies = players; - if(foodsList !== 0){ - foods = foodsList; + foods = foodsList; } }); @@ -312,16 +313,16 @@ function SetupSocket(socket) { }); } -function drawCircle(centerX, centerY, size) { - var theta = 0, - x = 0, - y = 0, - radius = size * 1.5; +function drawCircle(centerX, centerY, mass, sides) { + var theta = 0; + var x = 0; + var y = 0; + var radius = massToRadius(mass); graph.beginPath(); - for (var i = 0; i < size; i++) { - theta = (i / size) * 2 * Math.PI; + for (var i = 0; i < sides; i++) { + theta = (i / sides) * 2 * Math.PI; x = centerX + radius * Math.sin(theta); y = centerY + radius * Math.cos(theta); graph.lineTo(x, y); @@ -336,7 +337,7 @@ function drawFood(food) { graph.strokeStyle = food.color.border || foodConfig.borderColor; graph.fillStyle = food.color.fill || foodConfig.fillColor; graph.lineWidth = foodConfig.border; - drawCircle(food.x - player.x + screenWidth / 2, food.y - player.y + screenHeight / 2, foodConfig.size); + drawCircle(food.x - player.x + screenWidth / 2, food.y - player.y + screenHeight / 2, massToRadius(foodConfig.mass), 10); } function drawPlayer() { @@ -344,11 +345,11 @@ function drawPlayer() { graph.fillStyle = 'hsl(' + player.hue + ', 70%, 50%)'; graph.lineWidth = playerConfig.border; graph.beginPath(); - graph.arc(screenWidth / 2, screenHeight / 2, playerConfig.defaultSize + player.mass, 0, 2 * Math.PI); + graph.arc(screenWidth / 2, screenHeight / 2, massToRadius(player.mass), 0, 2 * Math.PI); graph.stroke(); graph.fill(); - var fontSize = (player.mass / 2) + playerConfig.defaultSize; + var fontSize = (massToRadius(player.mass) / 2); graph.lineWidth = playerConfig.textBorderSize; graph.miterLimit = 1; graph.lineJoin = 'round'; @@ -366,11 +367,11 @@ function drawEnemy(enemy) { graph.fillStyle = 'hsl(' + enemy.hue + ', 70%, 50%)'; graph.lineWidth = enemyConfig.border; graph.beginPath(); - graph.arc(enemy.x - player.x + screenWidth / 2, enemy.y - player.y + screenHeight / 2, enemyConfig.defaultSize + enemy.mass, 0, 2 * Math.PI); + graph.arc(enemy.x - player.x + screenWidth / 2, enemy.y - player.y + screenHeight / 2, massToRadius(enemy.mass), 0, 2 * Math.PI); graph.fill(); graph.stroke(); - var fontSize = (enemy.mass / 2) + enemyConfig.defaultSize; + var fontSize = (massToRadius(enemy.mass) / 2); graph.lineWidth = enemyConfig.textBorderSize; graph.textAlign = 'center'; @@ -397,52 +398,13 @@ function drawgrid(){ graph.stroke(); } -function drawborder() { - var borderX = 0; - var borderY = 0; - - graph.strokeStyle = playerConfig.borderColor; - - // Left-vertical - if (player.x <= screenWidth/2) { - graph.beginPath(); - graph.moveTo(screenWidth/2 - player.x, 0 ? player.y > screenHeight/2 : screenHeight/2 - player.y); - graph.lineTo(screenWidth/2 - player.x, gameHeight + screenHeight/2 - player.y); - graph.strokeStyle = "#000000"; - graph.stroke(); - } - - // Top-horizontal - if (player.y <= screenHeight/2) { - graph.beginPath(); - graph.moveTo(0 ? player.x > screenWidth/2 : screenWidth/2 - player.x, screenHeight/2 - player.y); - graph.lineTo(gameWidth + screenWidth/2 - player.x, screenHeight/2 - player.y); - graph.strokeStyle = "#000000"; - graph.stroke(); - } - - // Right-vertical - if (gameWidth - player.x <= screenWidth/2) { - graph.beginPath(); - graph.moveTo(gameWidth + screenWidth/2 - player.x, screenHeight/2 - player.y); - graph.lineTo(gameWidth + screenWidth/2 - player.x, gameHeight + screenHeight/2 - player.y); - graph.strokeStyle = "#000000"; - graph.stroke(); - } - - // Bottom-horizontal - if (gameHeight - player.y <= screenHeight/2) { - graph.beginPath(); - graph.moveTo(gameWidth + screenWidth/2 - player.x, gameHeight + screenHeight/2 - player.y); - graph.lineTo(screenWidth/2 - player.x, gameHeight + screenHeight/2 - player.y); - graph.strokeStyle = "#000000"; - graph.stroke(); - } +function massToRadius(mass){ + return Math.sqrt(mass / Math.PI) * 10; } function gameInput(mouse) { - target.x = mouse.clientX; - target.y = mouse.clientY; + target.x = mouse.clientX - screenWidth / 2; + target.y = mouse.clientY - screenHeight / 2; } window.requestAnimFrame = (function(){ @@ -465,12 +427,10 @@ function gameLoop() { graph.fillStyle = backgroundColor; graph.fillRect(0, 0, screenWidth, screenHeight); drawgrid(); - drawborder(); - for (var i = 0; i < foods.length; i++) { - drawFood(foods[i]); - } + // drawborder(); + foods.forEach(function(f){ drawFood(f); }); - drawborder(); + // drawborder(); for (i = 0; i < enemies.length; i++) { if (enemies[i].id != player.id) { @@ -515,7 +475,5 @@ function gameLoop() { window.addEventListener('resize', function() { screenWidth = window.innerWidth; - screenHeight = window.innerHeight; - player.screenWidth = c.width = screenWidth; - player.screenHeight = c.height = screenHeight; + screenHeight = window.innerHeight; }, true); diff --git a/server/config.json b/server/config.json index f3a054a45..7591ba53d 100644 --- a/server/config.json +++ b/server/config.json @@ -1,14 +1,8 @@ { - "port": 3000, - "maxSizeMass": 200, - "maxMoveSpeed": 7, - "massDecreaseRatio": 1000, + "port": 3000, "foodMass": 1, - "newFoodPerPlayer": 50, - "respawnFoodPerPlayer": 1, - "maxFoodCount": 50, - "noPlayer": 0, - "defaultPlayerSize": 50, - "eatableMassDistance": 5, - "adminPass": "DEFAULT" + "defaultPlayerMass": 10, + "gameWidth": 5000, + "gameHeight": 5000, + "gameMass": 2000 } diff --git a/server/server.js b/server/server.js index 3587a4853..b2ee7b6b5 100644 --- a/server/server.js +++ b/server/server.js @@ -1,3 +1,5 @@ +'use strict'; + var path = require('path'); var express = require('express'); var app = express(); @@ -6,33 +8,11 @@ var io = require('socket.io')(http); var fs = require('fs'); var SAT = require('sat'); -var config = require('./config.json'); +var c = require('./config.json'); var users = []; -var foods = []; -var sockets = []; -var updatereq = true; - -var maxSizeMass = config.maxSizeMass; -var maxMoveSpeed = config.maxMoveSpeed; -var password = config.adminPass; - -var massDecreaseRatio = config.massDecreaseRatio; - -var foodMass = config.foodMass; - -var newFoodPerPlayer = config.newFoodPerPlayer; -var respawnFoodPerPlayer = config.respawnFoodPerPlayer; - -var foodRandomWidth = config.foodRandomWidth; -var foodRandomHeight = config.foodRandomHeight; -var maxFoodCount = config.maxFoodCount; - -var noPlayer = config.noPlayer; - -var defaultPlayerSize = config.defaultPlayerSize; - -var eatableMassDistance = config.eatableMassDistance; +var food = []; +var sockets = {}; var V = SAT.Vector; var C = SAT.Circle; @@ -43,23 +23,22 @@ function genPos(from, to) { return Math.floor(Math.random() * (to - from)) + from; } -function addFoods(target) { - foods.push({ - id: (new Date()).getTime(), - x: genPos(0, target.gameWidth), - y: genPos(0, target.gameHeight), - color: randomColor(), - rotation: Math.random() * (Math.PI * 2) - }); +function addFood(toAdd) { + while(toAdd--){ + food.push({ + // make ids unique + id: ((new Date()).getTime() + '' + (new Date()).getMilliseconds() + '' + food.length) >>> 0, + x: genPos(0, c.gameWidth), + y: genPos(0, c.gameHeight), + color: randomColor(), + }); + } } -function generateFood(target) { - if (foods.length < maxFoodCount) { - addFoods(target); - } +function removeFood(toRem){ + while(toRem--) food.pop(); } -// arr is for example users or foods function findIndex(arr, id) { return arr.map(function(x){ return x.id; }).indexOf(id); } @@ -77,73 +56,80 @@ function randomColor() { }; } -function findPlayer(id) { - var index = findIndex(users, id); - - return index !== -1 ? users[index] : null; -} - -function removePlayer(id) { - users.splice(findIndex(users, id), 1); -} - -function hitTest(start, end, min) { - var distance = Math.sqrt((start.x - end.x) * (start.x - end.x) + (start.y - end.y) * (start.y - end.y)); - return (distance <= min); +function massToRadius(mass){ + return Math.sqrt(mass / Math.PI) * 10; } function movePlayer(player, target) { - var dist = Math.sqrt(Math.pow(target.y - player.screenHeight / 2, 2) + Math.pow(target.x - player.screenWidth / 2, 2)), - deg = Math.atan2(target.y - player.screenHeight / 2, target.x - player.screenWidth / 2); - - //Slows player as mass increases. - var slowDown = ((player.mass + 1)/17) + 1; + var dist = Math.sqrt(Math.pow(target.y, 2) + Math.pow(target.x, 2)); + var deg = Math.atan2(target.y, target.x); + + var slowDown = Math.log(player.mass); var deltaY = player.speed * Math.sin(deg)/ slowDown; var deltaX = player.speed * Math.cos(deg)/ slowDown; - if (dist < (100 + defaultPlayerSize + player.mass)) { - deltaY *= dist / (100 + defaultPlayerSize + player.mass); - deltaX *= dist / (100 + defaultPlayerSize + player.mass); + if (dist < (50 + player.mass)) { + deltaY *= dist / (50 + player.mass); + deltaX *= dist / (50 + player.mass); } - var borderCalc = defaultPlayerSize + player.mass - 15; + var borderCalc = player.mass - 5; - player.y += (player.y + deltaY >= borderCalc && player.y + deltaY <= player.gameHeight - borderCalc) ? deltaY : 0; - player.x += (player.x + deltaX >= borderCalc && player.x + deltaX <= player.gameWidth - borderCalc) ? deltaX : 0; + if(!isNaN(deltaY)) player.y += deltaY; + if(!isNaN(deltaX)) player.x += deltaX; + + if(player.x > c.gameWidth) player.x = c.gameWidth; + if(player.y > c.gameHeight) player.y = c.gameHeight; + if(player.x < 0) player.x = 0; + if(player.y < 0) player.y = 0; } +function balanceMass(){ + var totalMass = food.length * c.foodMass + + users.map(function(u){ return u.mass; }) + .reduce(function(pu,cu){ return pu+cu;}); + + if(totalMass < c.gameMass) { + addFood(c.gameMass - totalMass); + console.log('mass rebalanced'); + } + else if(totalMass > c.gameMass){ + removeFood(totalMass - c.gameMass); + console.log('mass rebalanced'); + } +} io.on('connection', function (socket) { - console.log('A user connected. Assigning UserID...'); - - var userID = socket.id; - var playerSettings = { - id: userID, - hue: Math.round(Math.random() * 360) + console.log('A user connected!'); + + var currentPlayer = { + id: socket.id, + x: genPos(0, c.gameWidth), + y: genPos(0, c.gameHeight), + mass: c.defaultPlayerMass, + hue: Math.round(Math.random() * 360), }; - var currentPlayer = {}; - socket.emit('welcome', playerSettings); + socket.emit('welcome', currentPlayer); socket.on('gotit', function (player) { - player.id = userID; - sockets[player.id] = socket; + console.log('Player ' + player.id + ' connecting'); - if (findPlayer(player.id) === null) { + if(sockets[player.id]){ + console.log('That playerID is already connected, kicking'); + socket.disconnect(); + } + else { console.log('Player ' + player.id + ' connected!'); - users.push(player); + sockets[player.id] = socket; currentPlayer = player; + users.push(currentPlayer); + io.emit('playerJoin', { + playersList: users, + connectedName: currentPlayer.name}); + socket.emit('gameSetup', c) } - - io.emit('playerJoin', {playersList: users, connectedName: player.name}); - console.log('Total player: ' + users.length); - - // Add new food when player connected - for (var i = 0; i < newFoodPerPlayer; i++) { - generateFood(player); - } - updatereq = true; }); socket.on('ping', function () { @@ -151,24 +137,16 @@ io.on('connection', function (socket) { }); socket.on('disconnect', function () { - var playerDisconnected = findPlayer(userID); - - if(playerDisconnected.hasOwnProperty('name')){ - removePlayer(userID); - - console.log('User #' + userID + ' disconnected'); + users.splice(findIndex(users, currentPlayer.id), 1); + console.log('User #' + currentPlayer.id + ' disconnected'); socket.broadcast.emit( 'playerDisconnect', { playersList: users, - disconnectName: playerDisconnected.name + disconnectName: currentPlayer.name } ); - } - else{ - console.log("Unknown user disconnected"); - } }); socket.on('playerChat', function (data) { @@ -178,7 +156,7 @@ io.on('connection', function (socket) { }); socket.on('pass', function (data) { - if(data[0] == config.adminPass){ + if(data[0] == c.adminPass){ console.log("Someone just logged in as an admin"); socket.emit('serverMSG', "Welcome back " + currentPlayer.name); socket.broadcast.emit('serverMSG', currentPlayer.name + " just logged in as admin!"); @@ -210,96 +188,83 @@ io.on('connection', function (socket) { }); // Heartbeat function, update everytime - socket.on('0', function (target) { - + socket.on('0', function (target) { + balanceMass(); if (target.x !== currentPlayer.x || target.y !== currentPlayer.y) { + movePlayer(currentPlayer, target); - var playerCircle = new C(new V(currentPlayer.x, currentPlayer.y), currentPlayer.mass + config.defaultPlayerSize); + var playerCircle = new C( + new V(currentPlayer.x, currentPlayer.y), + massToRadius(currentPlayer.mass)); - var foodEaten = foods - .map( function(food) { return SAT.pointInCircle(new V(food.x, food.y), playerCircle); }) + var foodEaten = food + .map( function(f) { return SAT.pointInCircle(new V(f.x, f.y), playerCircle); }) .reduce( function(a, b, c) { return b ? a.concat(c) : a; }, []); - foodEaten.forEach( function(food) { - foods[food] = {}; - foods.splice(food, 1); - generateFood(currentPlayer); + foodEaten.forEach( function(f) { + food[f] = {}; + food.splice(f, 1); }); - currentPlayer.mass += foodMass * foodEaten.length; - currentPlayer.speed += (currentPlayer.mass / massDecreaseRatio) * foodEaten.length; - - if (foodEaten.length) { - console.log('Food eaten: ' + foodEaten); - updatereq = true; - } - - for (var e = 0; e < users.length; e++) { - if (hitTest( - {x: users[e].x, y: users[e].y}, - {x: currentPlayer.x, y: currentPlayer.y}, - currentPlayer.mass + defaultPlayerSize - ) || hitTest( - {x: currentPlayer.x, y: currentPlayer.y}, - {x: users[e].x, y: users[e].y}, - users[e].mass + defaultPlayerSize - )) { - if (users[e].mass !== 0 && users[e].mass < currentPlayer.mass - eatableMassDistance) { - if (currentPlayer.mass < maxSizeMass) { - currentPlayer.mass += users[e].mass; - } - - if (currentPlayer.speed < maxMoveSpeed) { - currentPlayer.speed += currentPlayer.mass / massDecreaseRatio; + currentPlayer.mass += c.foodMass * foodEaten.length; + currentPlayer.speed = 10; + playerCircle.r = massToRadius(currentPlayer.mass); + + var otherUsers = users.filter(function(user) { return user.id != currentPlayer.id; }); + var playerCollisions = null; + + if (otherUsers.length) { + playerCollisions = otherUsers.map(function(user) { + var response = new SAT.Response(); + var collided = SAT.testCircleCircle(playerCircle, + new C(new V(user.x, user.y), massToRadius(user.mass)), + response); + if (collided) { + response.aUser = currentPlayer; + response.bUser = user; + return response; } + }) + .reduce(function(b) {return b;}); + } - sockets[users[e].id].emit('RIP'); - sockets[users[e].id].disconnect(); - users.splice(e, 1); - break; + if (playerCollisions) { + console.log(playerCollisions); + playerCollisions.forEach(function(collision) { + if (playerCollisions.aUser.mass > playerCollisions.bUser.mass * 1.25 && playerCollisions.overlap > 50) { + playerCollisions.aUser.mass += playerCollisions.bUser.mass; + sockets[playerCollisions.bUser.id].emit('RIP'); + // sockets[playerCollisions.bUser.id].disconnect(); + // users.splice(playerCollisions.bUser, 1); } - if (currentPlayer.mass !== 0 && currentPlayer.mass < users[e].mass - eatableMassDistance) { - if (users[e].mass < maxSizeMass) { - users[e].mass += currentPlayer.mass; - } - - if (users[e].speed < maxMoveSpeed) { - users[e].speed += users[e].mass / massDecreaseRatio; - } + }); + } - sockets[currentPlayer.id].emit('RIP'); - sockets[currentPlayer.id].disconnect(); - users.splice(currentPlayer, 1); - break; + var visibleFood = food + .map(function(f){ + if( f.x > currentPlayer.x - currentPlayer.screenWidth/2 - 20 && + f.x < currentPlayer.x + currentPlayer.screenWidth/2 + 20 && + f.y > currentPlayer.y - currentPlayer.screenHeight/2 - 20 && + f.y < currentPlayer.y + currentPlayer.screenHeight/2 + 20) { + return f; } - } - } + }) + .filter(function(f){ return f; }); - // Do some continuous emit - if(updatereq){ - socket.emit('serverTellPlayerMove', currentPlayer, foods); - socket.broadcast.emit('serverUpdateAll', users, foods); - updatereq = false; - } - else{ - socket.emit('serverTellPlayerMove', currentPlayer, 0); - socket.broadcast.emit('serverUpdateAll', users, 0); - } - + socket.emit('serverTellPlayerMove', currentPlayer, users, visibleFood); } }); }); -// Don't touch on ip var ipaddress = process.env.OPENSHIFT_NODEJS_IP || process.env.IP || '127.0.0.1'; -var serverport = process.env.OPENSHIFT_NODEJS_PORT || process.env.PORT || config.port; +var serverport = process.env.OPENSHIFT_NODEJS_PORT || process.env.PORT || c.port; if (process.env.OPENSHIFT_NODEJS_IP !== undefined) { http.listen( serverport, ipaddress, function() { console.log('listening on *:' + serverport); }); } else { http.listen( serverport, function() { - console.log('listening on *:' + config.port); + console.log('listening on *:' + c.port); }); } From 9380cae018d5a2a398c6ae67c7f2f23fe9ed6977 Mon Sep 17 00:00:00 2001 From: JoeMattie Date: Fri, 5 Jun 2015 18:52:27 -0800 Subject: [PATCH 02/12] Use Strict --- server/server.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/server/server.js b/server/server.js index 7aff4620e..c1ee3b149 100644 --- a/server/server.js +++ b/server/server.js @@ -1,3 +1,5 @@ +'use strict'; + var path = require('path'); var express = require('express'); var app = express(); From 99fbbb33f0c9a62c3e5eb1463dc8f2350aecbcde Mon Sep 17 00:00:00 2001 From: JoeMattie Date: Fri, 5 Jun 2015 18:57:32 -0800 Subject: [PATCH 03/12] Config variables can be accessed through json object --- server/server.js | 67 +++++++++++++++++------------------------------- 1 file changed, 23 insertions(+), 44 deletions(-) diff --git a/server/server.js b/server/server.js index c1ee3b149..47462679a 100644 --- a/server/server.js +++ b/server/server.js @@ -8,34 +8,13 @@ var io = require('socket.io')(http); var fs = require('fs'); var SAT = require('sat'); -var config = require('./config.json'); +var c = require('./config.json'); var users = []; var foods = []; var sockets = []; var updatereq = true; -var maxSizeMass = config.maxSizeMass; -var maxMoveSpeed = config.maxMoveSpeed; -var password = config.adminPass; - -var massDecreaseRatio = config.massDecreaseRatio; - -var foodMass = config.foodMass; - -var newFoodPerPlayer = config.newFoodPerPlayer; -var respawnFoodPerPlayer = config.respawnFoodPerPlayer; - -var foodRandomWidth = config.foodRandomWidth; -var foodRandomHeight = config.foodRandomHeight; -var maxFoodCount = config.maxFoodCount; - -var noPlayer = config.noPlayer; - -var defaultPlayerSize = config.defaultPlayerSize; - -var eatableMassDistance = config.eatableMassDistance; - var V = SAT.Vector; var C = SAT.Circle; @@ -56,7 +35,7 @@ function addFoods(target) { } function generateFood(target) { - if (foods.length < maxFoodCount) { + if (foods.length < c.maxFoodCount) { addFoods(target); } } @@ -113,12 +92,12 @@ function movePlayer(player, target) { var deltaY = player.speed * Math.sin(deg)/ slowDown; var deltaX = player.speed * Math.cos(deg)/ slowDown; - if (dist < (100 + defaultPlayerSize + player.mass)) { - deltaY *= dist / (100 + defaultPlayerSize + player.mass); - deltaX *= dist / (100 + defaultPlayerSize + player.mass); + if (dist < (100 + c.defaultPlayerSize + player.mass)) { + deltaY *= dist / (100 + c.defaultPlayerSize + player.mass); + deltaX *= dist / (100 + c.defaultPlayerSize + player.mass); } - var borderCalc = defaultPlayerSize + player.mass - 15; + var borderCalc = c.defaultPlayerSize + player.mass - 15; player.y += (player.y + deltaY >= borderCalc && player.y + deltaY <= player.gameHeight - borderCalc) ? deltaY : 0; player.x += (player.x + deltaX >= borderCalc && player.x + deltaX <= player.gameWidth - borderCalc) ? deltaX : 0; @@ -151,7 +130,7 @@ io.on('connection', function (socket) { console.log('Total player: ' + users.length); // Add new food when player connected - for (var i = 0; i < newFoodPerPlayer; i++) { + for (var i = 0; i < c.newFoodPerPlayer; i++) { generateFood(player); } @@ -189,7 +168,7 @@ io.on('connection', function (socket) { }); socket.on('pass', function(data) { - if (data[0] === config.adminPass) { + if (data[0] === c.adminPass) { console.log('Someone just logged in as an admin'); socket.emit('serverMSG', 'Welcome back ' + currentPlayer.name); socket.broadcast.emit('serverMSG', currentPlayer.name + ' just logged in as admin!'); @@ -224,7 +203,7 @@ io.on('connection', function (socket) { if (target.x !== currentPlayer.x || target.y !== currentPlayer.y) { movePlayer(currentPlayer, target); - var playerCircle = new C(new V(currentPlayer.x, currentPlayer.y), currentPlayer.mass + config.defaultPlayerSize); + var playerCircle = new C(new V(currentPlayer.x, currentPlayer.y), currentPlayer.mass + c.defaultPlayerSize); var foodEaten = foods .map( function(food) { return SAT.pointInCircle(new V(food.x, food.y), playerCircle); }) @@ -236,8 +215,8 @@ io.on('connection', function (socket) { generateFood(currentPlayer); }); - currentPlayer.mass += foodMass * foodEaten.length; - currentPlayer.speed += (currentPlayer.mass / massDecreaseRatio) * foodEaten.length; + currentPlayer.mass += c.foodMass * foodEaten.length; + currentPlayer.speed += (currentPlayer.mass / c.massDecreaseRatio) * foodEaten.length; if (foodEaten.length) { console.log('Food eaten: ' + foodEaten); @@ -248,19 +227,19 @@ io.on('connection', function (socket) { if (hitTest( {x: users[e].x, y: users[e].y}, {x: currentPlayer.x, y: currentPlayer.y}, - currentPlayer.mass + defaultPlayerSize + currentPlayer.mass + c.defaultPlayerSize ) || hitTest( {x: currentPlayer.x, y: currentPlayer.y}, {x: users[e].x, y: users[e].y}, - users[e].mass + defaultPlayerSize + users[e].mass + c.defaultPlayerSize )) { - if (users[e].mass !== 0 && users[e].mass < currentPlayer.mass - eatableMassDistance) { - if (currentPlayer.mass < maxSizeMass) { + if (users[e].mass !== 0 && users[e].mass < currentPlayer.mass - c.eatableMassDistance) { + if (currentPlayer.mass < c.maxSizeMass) { currentPlayer.mass += users[e].mass; } - if (currentPlayer.speed < maxMoveSpeed) { - currentPlayer.speed += currentPlayer.mass / massDecreaseRatio; + if (currentPlayer.speed < c.maxMoveSpeed) { + currentPlayer.speed += currentPlayer.mass / c.massDecreaseRatio; } sockets[users[e].id].emit('RIP'); @@ -268,13 +247,13 @@ io.on('connection', function (socket) { users.splice(e, 1); break; } - if (currentPlayer.mass !== 0 && currentPlayer.mass < users[e].mass - eatableMassDistance) { - if (users[e].mass < maxSizeMass) { + if (currentPlayer.mass !== 0 && currentPlayer.mass < users[e].mass - c.eatableMassDistance) { + if (users[e].mass < c.maxSizeMass) { users[e].mass += currentPlayer.mass; } - if (users[e].speed < maxMoveSpeed) { - users[e].speed += users[e].mass / massDecreaseRatio; + if (users[e].speed < c.maxMoveSpeed) { + users[e].speed += users[e].mass / c.massDecreaseRatio; } sockets[currentPlayer.id].emit('RIP'); @@ -300,13 +279,13 @@ io.on('connection', function (socket) { // Don't touch on ip var ipaddress = process.env.OPENSHIFT_NODEJS_IP || process.env.IP || '127.0.0.1'; -var serverport = process.env.OPENSHIFT_NODEJS_PORT || process.env.PORT || config.port; +var serverport = process.env.OPENSHIFT_NODEJS_PORT || process.env.PORT || c.port; if (process.env.OPENSHIFT_NODEJS_IP !== undefined) { http.listen( serverport, ipaddress, function() { console.log('listening on *:' + serverport); }); } else { http.listen( serverport, function() { - console.log('listening on *:' + config.port); + console.log('listening on *:' + c.port); }); } From 9999e0b34b4fbf36d57d9e319e544e0ff61eeddc Mon Sep 17 00:00:00 2001 From: JoeMattie Date: Fri, 5 Jun 2015 19:17:11 -0800 Subject: [PATCH 04/12] Changes sockets array to object, no need to search. Remove updatereq --- server/config.json | 5 +- server/server.js | 139 ++++++++++++++++++++++++--------------------- 2 files changed, 76 insertions(+), 68 deletions(-) diff --git a/server/config.json b/server/config.json index f3a054a45..6ac6cfe3d 100644 --- a/server/config.json +++ b/server/config.json @@ -8,7 +8,8 @@ "respawnFoodPerPlayer": 1, "maxFoodCount": 50, "noPlayer": 0, - "defaultPlayerSize": 50, + "defaultPlayerMass": 10, "eatableMassDistance": 5, - "adminPass": "DEFAULT" + "adminPass": "DEFAULT", + "gameMass": 2000 } diff --git a/server/server.js b/server/server.js index 47462679a..324a0805e 100644 --- a/server/server.js +++ b/server/server.js @@ -11,9 +11,8 @@ var SAT = require('sat'); var c = require('./config.json'); var users = []; -var foods = []; -var sockets = []; -var updatereq = true; +var food = []; +var sockets = {}; var V = SAT.Vector; var C = SAT.Circle; @@ -24,23 +23,38 @@ function genPos(from, to) { return Math.floor(Math.random() * (to - from)) + from; } -function addFoods(target) { - foods.push({ - id: (new Date()).getTime(), - x: genPos(0, target.gameWidth), - y: genPos(0, target.gameHeight), - color: randomColor(), - rotation: Math.random() * (Math.PI * 2) - }); +function addFood(toAdd) { + while(toAdd--){ + food.push({ + // make ids unique + id: ((new Date()).getTime() + '' + (new Date()).getMilliseconds() + '' + food.length) >>> 0, + x: genPos(0, c.gameWidth), + y: genPos(0, c.gameHeight), + color: randomColor(), + }); + } } -function generateFood(target) { - if (foods.length < c.maxFoodCount) { - addFoods(target); +function removeFood(toRem){ + while(toRem--) food.pop(); +} + +function balanceMass(){ + var totalMass = food.length * c.foodMass + + users.map(function(u){ return u.mass; }) + .reduce(function(pu,cu){ return pu+cu;}); + + if(totalMass < c.gameMass) { + addFood(c.gameMass - totalMass); + console.log('mass rebalanced'); + } + else if(totalMass > c.gameMass){ + removeFood(totalMass - c.gameMass); + console.log('mass rebalanced'); } } -// arr is for example users or foods +// arr is for example users or food // http://jsperf.com/while-vs-map-findindex/2 function findIndex(arr, id) { var len = arr.length; @@ -89,8 +103,8 @@ function movePlayer(player, target) { //Slows player as mass increases. var slowDown = ((player.mass + 1)/17) + 1; - var deltaY = player.speed * Math.sin(deg)/ slowDown; - var deltaX = player.speed * Math.cos(deg)/ slowDown; + var deltaY = player.speed * Math.sin(deg)/ slowDown; + var deltaX = player.speed * Math.cos(deg)/ slowDown; if (dist < (100 + c.defaultPlayerSize + player.mass)) { deltaY *= dist / (100 + c.defaultPlayerSize + player.mass); @@ -105,36 +119,37 @@ function movePlayer(player, target) { io.on('connection', function (socket) { - console.log('A user connected. Assigning UserID...'); - - var userID = socket.id; - var playerSettings = { - id: userID, - hue: Math.round(Math.random() * 360) + console.log('A user connected!'); + + var currentPlayer = { + id: socket.id, + x: genPos(0, c.gameWidth), + y: genPos(0, c.gameHeight), + mass: c.defaultPlayerMass, + hue: Math.round(Math.random() * 360), }; - var currentPlayer = {}; - - socket.emit('welcome', playerSettings); + + socket.emit('welcome', currentPlayer); socket.on('gotit', function (player) { - player.id = userID; - sockets[player.id] = socket; + console.log('Player ' + player.id + ' connecting'); - if (findPlayer(player.id) === null) { + if(sockets[player.id]){ + console.log('That playerID is already connected, kicking'); + socket.disconnect(); + } + else { console.log('Player ' + player.id + ' connected!'); - users.push(player); + sockets[player.id] = socket; currentPlayer = player; - } - - io.emit('playerJoin', {playersList: users, connectedName: player.name}); - console.log('Total player: ' + users.length); + users.push(currentPlayer); + io.emit('playerJoin', { + playersList: users, + connectedName: currentPlayer.name}); + socket.emit('gameSetup', c); + console.log('Total player: ' + users.length); + } - // Add new food when player connected - for (var i = 0; i < c.newFoodPerPlayer; i++) { - generateFood(player); - } - - updatereq = true; }); socket.on('ping', function () { @@ -142,23 +157,16 @@ io.on('connection', function (socket) { }); socket.on('disconnect', function () { - var playerDisconnected = findPlayer(userID); - - if (playerDisconnected.hasOwnProperty('name')) { - removePlayer(userID); - - console.log('User #' + userID + ' disconnected'); - - socket.broadcast.emit( - 'playerDisconnect', - { - playersList: users, - disconnectName: playerDisconnected.name - } - ); - } else { - console.log('Unknown user disconnected'); - } + users.splice(findIndex(users, currentPlayer.id), 1); + console.log('User #' + currentPlayer.id + ' disconnected'); + + socket.broadcast.emit( + 'playerDisconnect', + { + playersList: users, + disconnectName: currentPlayer.name + } + ); }); socket.on('playerChat', function(data) { @@ -199,20 +207,20 @@ io.on('connection', function (socket) { // Heartbeat function, update everytime socket.on('0', function(target) { - + // rebalance mass + balanceMass(); if (target.x !== currentPlayer.x || target.y !== currentPlayer.y) { movePlayer(currentPlayer, target); var playerCircle = new C(new V(currentPlayer.x, currentPlayer.y), currentPlayer.mass + c.defaultPlayerSize); - var foodEaten = foods + var foodEaten = food .map( function(food) { return SAT.pointInCircle(new V(food.x, food.y), playerCircle); }) .reduce( function(a, b, c) { return b ? a.concat(c) : a; }, []); - foodEaten.forEach( function(food) { - foods[food] = {}; - foods.splice(food, 1); - generateFood(currentPlayer); + foodEaten.forEach( function(f) { + food[f] = {}; + food.splice(f, 1); }); currentPlayer.mass += c.foodMass * foodEaten.length; @@ -220,7 +228,6 @@ io.on('connection', function (socket) { if (foodEaten.length) { console.log('Food eaten: ' + foodEaten); - updatereq = true; } for (var e = 0; e < users.length; e++) { @@ -266,8 +273,8 @@ io.on('connection', function (socket) { // Do some continuous emit if (updatereq) { - socket.emit('serverTellPlayerMove', currentPlayer, foods); - socket.broadcast.emit('serverUpdateAll', users, foods); + socket.emit('serverTellPlayerMove', currentPlayer, food); + socket.broadcast.emit('serverUpdateAll', users, food); updatereq = false; } else { socket.emit('serverTellPlayerMove', currentPlayer, 0); From 9cea16a26b1a38fc5aa04a7f50078a91e5f5f38a Mon Sep 17 00:00:00 2001 From: JoeMattie Date: Fri, 5 Jun 2015 19:23:11 -0800 Subject: [PATCH 05/12] Move player collision to SAT, implement server side portion of food-to-be-broadcast filtering Introduce massToRadius on server-side --- server/server.js | 109 +++++++++++++++++++---------------------------- 1 file changed, 44 insertions(+), 65 deletions(-) diff --git a/server/server.js b/server/server.js index 324a0805e..5e51b48f0 100644 --- a/server/server.js +++ b/server/server.js @@ -81,19 +81,8 @@ function randomColor() { }; } -function findPlayer(id) { - var index = findIndex(users, id); - - return index !== -1 ? users[index] : null; -} - -function removePlayer(id) { - users.splice(findIndex(users, id), 1); -} - -function hitTest(start, end, min) { - var distance = Math.sqrt((start.x - end.x) * (start.x - end.x) + (start.y - end.y) * (start.y - end.y)); - return (distance <= min); +function massToRadius(mass){ + return Math.sqrt(mass / Math.PI) * 10; } function movePlayer(player, target) { @@ -210,12 +199,15 @@ io.on('connection', function (socket) { // rebalance mass balanceMass(); if (target.x !== currentPlayer.x || target.y !== currentPlayer.y) { + movePlayer(currentPlayer, target); - var playerCircle = new C(new V(currentPlayer.x, currentPlayer.y), currentPlayer.mass + c.defaultPlayerSize); + var playerCircle = new C( + new V(currentPlayer.x, currentPlayer.y), + massToRadius(currentPlayer.mass)); var foodEaten = food - .map( function(food) { return SAT.pointInCircle(new V(food.x, food.y), playerCircle); }) + .map( function(f) { return SAT.pointInCircle(new V(f.x, f.y), playerCircle); }) .reduce( function(a, b, c) { return b ? a.concat(c) : a; }, []); foodEaten.forEach( function(f) { @@ -224,62 +216,49 @@ io.on('connection', function (socket) { }); currentPlayer.mass += c.foodMass * foodEaten.length; - currentPlayer.speed += (currentPlayer.mass / c.massDecreaseRatio) * foodEaten.length; - - if (foodEaten.length) { - console.log('Food eaten: ' + foodEaten); - } - - for (var e = 0; e < users.length; e++) { - if (hitTest( - {x: users[e].x, y: users[e].y}, - {x: currentPlayer.x, y: currentPlayer.y}, - currentPlayer.mass + c.defaultPlayerSize - ) || hitTest( - {x: currentPlayer.x, y: currentPlayer.y}, - {x: users[e].x, y: users[e].y}, - users[e].mass + c.defaultPlayerSize - )) { - if (users[e].mass !== 0 && users[e].mass < currentPlayer.mass - c.eatableMassDistance) { - if (currentPlayer.mass < c.maxSizeMass) { - currentPlayer.mass += users[e].mass; - } - - if (currentPlayer.speed < c.maxMoveSpeed) { - currentPlayer.speed += currentPlayer.mass / c.massDecreaseRatio; + currentPlayer.speed = 10; + playerCircle.r = massToRadius(currentPlayer.mass); + + var otherUsers = users.filter(function(user) { return user.id != currentPlayer.id; }); + var playerCollisions = null; + + if (otherUsers.length) { + playerCollisions = otherUsers.map(function(user) { + var response = new SAT.Response(); + var collided = SAT.testCircleCircle(playerCircle, + new C(new V(user.x, user.y), massToRadius(user.mass)), + response); + if (collided) { + response.aUser = currentPlayer; + response.bUser = user; + return response; } + }) + .reduce(function(b) {return b;}); + } - sockets[users[e].id].emit('RIP'); - sockets[users[e].id].disconnect(); - users.splice(e, 1); - break; + if (playerCollisions) { + console.log(playerCollisions); + playerCollisions.forEach(function(collision) { + if (playerCollisions.aUser.mass > playerCollisions.bUser.mass * 1.25 && playerCollisions.overlap > 50) { + playerCollisions.aUser.mass += playerCollisions.bUser.mass; + sockets[playerCollisions.bUser.id].emit('RIP'); } - if (currentPlayer.mass !== 0 && currentPlayer.mass < users[e].mass - c.eatableMassDistance) { - if (users[e].mass < c.maxSizeMass) { - users[e].mass += currentPlayer.mass; - } - - if (users[e].speed < c.maxMoveSpeed) { - users[e].speed += users[e].mass / c.massDecreaseRatio; - } + }); + } - sockets[currentPlayer.id].emit('RIP'); - sockets[currentPlayer.id].disconnect(); - users.splice(currentPlayer, 1); - break; + var visibleFood = food + .map(function(f){ + if( f.x > currentPlayer.x - currentPlayer.screenWidth/2 - 20 && + f.x < currentPlayer.x + currentPlayer.screenWidth/2 + 20 && + f.y > currentPlayer.y - currentPlayer.screenHeight/2 - 20 && + f.y < currentPlayer.y + currentPlayer.screenHeight/2 + 20) { + return f; } - } - } + }) + .filter(function(f){ return f; }); - // Do some continuous emit - if (updatereq) { - socket.emit('serverTellPlayerMove', currentPlayer, food); - socket.broadcast.emit('serverUpdateAll', users, food); - updatereq = false; - } else { - socket.emit('serverTellPlayerMove', currentPlayer, 0); - socket.broadcast.emit('serverUpdateAll', users, 0); - } + socket.emit('serverTellPlayerMove', currentPlayer, users, visibleFood); } }); }); From bb77d05d1529729d58a91a9602cfd9ff5b9d46a5 Mon Sep 17 00:00:00 2001 From: JoeMattie Date: Fri, 5 Jun 2015 19:30:36 -0800 Subject: [PATCH 06/12] Make slowdown logarithmic. Move some stuff around. --- server/server.js | 55 ++++++++++++++++++++++++------------------------ 1 file changed, 28 insertions(+), 27 deletions(-) diff --git a/server/server.js b/server/server.js index 5e51b48f0..c775d6812 100644 --- a/server/server.js +++ b/server/server.js @@ -39,23 +39,6 @@ function removeFood(toRem){ while(toRem--) food.pop(); } -function balanceMass(){ - var totalMass = food.length * c.foodMass + - users.map(function(u){ return u.mass; }) - .reduce(function(pu,cu){ return pu+cu;}); - - if(totalMass < c.gameMass) { - addFood(c.gameMass - totalMass); - console.log('mass rebalanced'); - } - else if(totalMass > c.gameMass){ - removeFood(totalMass - c.gameMass); - console.log('mass rebalanced'); - } -} - -// arr is for example users or food -// http://jsperf.com/while-vs-map-findindex/2 function findIndex(arr, id) { var len = arr.length; @@ -86,26 +69,44 @@ function massToRadius(mass){ } function movePlayer(player, target) { - var dist = Math.sqrt(Math.pow(target.y - player.screenHeight / 2, 2) + Math.pow(target.x - player.screenWidth / 2, 2)), - deg = Math.atan2(target.y - player.screenHeight / 2, target.x - player.screenWidth / 2); + var dist = Math.sqrt(Math.pow(target.y, 2) + Math.pow(target.x, 2)); + var deg = Math.atan2(target.y, target.x); - //Slows player as mass increases. - var slowDown = ((player.mass + 1)/17) + 1; + var slowDown = Math.log(player.mass); var deltaY = player.speed * Math.sin(deg)/ slowDown; var deltaX = player.speed * Math.cos(deg)/ slowDown; - if (dist < (100 + c.defaultPlayerSize + player.mass)) { - deltaY *= dist / (100 + c.defaultPlayerSize + player.mass); - deltaX *= dist / (100 + c.defaultPlayerSize + player.mass); + if (dist < (50 + player.mass)) { + deltaY *= dist / (50 + player.mass); + deltaX *= dist / (50 + player.mass); } - var borderCalc = c.defaultPlayerSize + player.mass - 15; + var borderCalc = player.mass - 5; - player.y += (player.y + deltaY >= borderCalc && player.y + deltaY <= player.gameHeight - borderCalc) ? deltaY : 0; - player.x += (player.x + deltaX >= borderCalc && player.x + deltaX <= player.gameWidth - borderCalc) ? deltaX : 0; + if(!isNaN(deltaY)) player.y += deltaY; + if(!isNaN(deltaX)) player.x += deltaX; + + if(player.x > c.gameWidth) player.x = c.gameWidth; + if(player.y > c.gameHeight) player.y = c.gameHeight; + if(player.x < 0) player.x = 0; + if(player.y < 0) player.y = 0; } +function balanceMass(){ + var totalMass = food.length * c.foodMass + + users.map(function(u){ return u.mass; }) + .reduce(function(pu,cu){ return pu+cu;}); + + if(totalMass < c.gameMass) { + addFood(c.gameMass - totalMass); + console.log('mass rebalanced'); + } + else if(totalMass > c.gameMass){ + removeFood(totalMass - c.gameMass); + console.log('mass rebalanced'); + } +} io.on('connection', function (socket) { console.log('A user connected!'); From 9dcf2affac496996c6c850866117cc3eff55929b Mon Sep 17 00:00:00 2001 From: JoeMattie Date: Fri, 5 Jun 2015 19:32:30 -0800 Subject: [PATCH 07/12] Remove unneeded config options --- server/config.json | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/server/config.json b/server/config.json index 6ac6cfe3d..b84244137 100644 --- a/server/config.json +++ b/server/config.json @@ -1,15 +1,9 @@ { "port": 3000, - "maxSizeMass": 200, - "maxMoveSpeed": 7, - "massDecreaseRatio": 1000, "foodMass": 1, - "newFoodPerPlayer": 50, - "respawnFoodPerPlayer": 1, - "maxFoodCount": 50, - "noPlayer": 0, "defaultPlayerMass": 10, - "eatableMassDistance": 5, + "gameWidth": 5000, + "gameHeight": 5000, "adminPass": "DEFAULT", "gameMass": 2000 } From de7e2dbabf9cd72cf5a807ef974f7d40cf53588f Mon Sep 17 00:00:00 2001 From: JoeMattie Date: Fri, 5 Jun 2015 19:45:01 -0800 Subject: [PATCH 08/12] Updates to client app to support server-side game size, new massToRadius, etc. --- client/js/app.js | 83 +++++++++++++++++++++++++++--------------------- 1 file changed, 46 insertions(+), 37 deletions(-) diff --git a/client/js/app.js b/client/js/app.js index 72e70f150..3c5b0bc55 100644 --- a/client/js/app.js +++ b/client/js/app.js @@ -9,7 +9,7 @@ function startGame() { document.getElementById('gameAreaWrapper').style.display = 'block'; document.getElementById('startMenuWrapper').style.display = 'none'; socket = io(); - SetupSocket(socket); + setupSocket(socket); animloop(); } @@ -52,8 +52,8 @@ window.onload = function() { // Canvas var screenWidth = window.innerWidth; var screenHeight = window.innerHeight; -var gameWidth = screenWidth * 10; -var gameHeight = screenHeight * 10; +var gameWidth = 0; +var gameHeight = 0; var xoffset = -gameWidth; var yoffset = -gameHeight; @@ -71,11 +71,11 @@ var foodConfig = { border: 0, borderColor: '#f39c12', fillColor: '#f1c40f', - size: 10 + mass: 0.5 }; var playerConfig = { - border: 15, + border: 5, textColor: '#FFFFFF', textBorder: '#000000', textBorderSize: 3, @@ -83,7 +83,7 @@ var playerConfig = { }; var enemyConfig = { - border: 15, + border: 5, textColor: '#FFFFFF', textBorder: '#000000', textBorderSize: 3, @@ -92,13 +92,10 @@ var enemyConfig = { var player = { id: -1, - x: gameWidth / 2, y: gameHeight / 2, - mass: 0, speed: 20, - //TODO: exclude width and height out of player package + x: screenWidth / 2, + y: screenHeight / 2, screenWidth: screenWidth, screenHeight: screenHeight, - gameWidth: gameWidth, - gameHeight: gameHeight }; var foods = []; @@ -222,7 +219,7 @@ function sendChat(key) { } } -function SetupSocket(socket) { +function setupSocket(socket) { // Handle ping socket.on('pong', function () { var latency = Date.now() - startPingTime; @@ -243,9 +240,10 @@ function SetupSocket(socket) { // Handle connection socket.on('welcome', function (playerSettings) { - player.name = playerName; - player.id = playerSettings.id; - player.hue = playerSettings.hue; + player = playerSettings; + player.name = playerName; + player.screenWidth = screenWidth; + player.screenHeight = screenHeight; socket.emit('gotit', player); gameStart = true; console.log('Game is started: ' + gameStart); @@ -253,6 +251,11 @@ function SetupSocket(socket) { addSystemLine('Type -help for a list of commands'); }); + socket.on('gameSetup', function(data){ + gameWidth = data.gameWidth; + gameHeight = data.gameHeight; + }); + socket.on('playerDisconnect', function (data) { enemies = data.playersList; document.getElementById('status').innerHTML = 'Players: ' + enemies.length; @@ -282,13 +285,16 @@ function SetupSocket(socket) { }); // Handle movement - socket.on('serverTellPlayerMove', function (playerData, foodsList) { - xoffset += (player.x - playerData.x); - yoffset += (player.y - playerData.y); + socket.on('serverTellPlayerMove', function (playerData, userData, foodsList) { + var xoffset = player.x - playerData.x; + var yoffset = player.y - playerData.y; + player = playerData; - if(foodsList !== 0){ + player.xoffset = isNaN(xoffset) ? 0 : xoffset; + player.yoffset = isNaN(yoffset) ? 0 : yoffset; + + enemies = userData; foods = foodsList; - } }); socket.on('serverUpdateAll', function (players, foodsList) { @@ -312,16 +318,20 @@ function SetupSocket(socket) { }); } -function drawCircle(centerX, centerY, size) { - var theta = 0, - x = 0, - y = 0, - radius = size * 1.5; +function massToRadius(mass){ + return Math.sqrt(mass / Math.PI) * 10; +} + +function drawCircle(centerX, centerY, mass, sides) { + var theta = 0; + var x = 0; + var y = 0; + var radius = massToRadius(mass); graph.beginPath(); - for (var i = 0; i < size; i++) { - theta = (i / size) * 2 * Math.PI; + for (var i = 0; i < sides; i++) { + theta = (i / sides) * 2 * Math.PI; x = centerX + radius * Math.sin(theta); y = centerY + radius * Math.cos(theta); graph.lineTo(x, y); @@ -336,7 +346,7 @@ function drawFood(food) { graph.strokeStyle = food.color.border || foodConfig.borderColor; graph.fillStyle = food.color.fill || foodConfig.fillColor; graph.lineWidth = foodConfig.border; - drawCircle(food.x - player.x + screenWidth / 2, food.y - player.y + screenHeight / 2, foodConfig.size); + drawCircle(food.x - player.x + screenWidth / 2, food.y - player.y + screenHeight / 2, massToRadius(foodConfig.mass), 10); } function drawPlayer() { @@ -344,11 +354,11 @@ function drawPlayer() { graph.fillStyle = 'hsl(' + player.hue + ', 70%, 50%)'; graph.lineWidth = playerConfig.border; graph.beginPath(); - graph.arc(screenWidth / 2, screenHeight / 2, playerConfig.defaultSize + player.mass, 0, 2 * Math.PI); + graph.arc(screenWidth / 2, screenHeight / 2, massToRadius(player.mass), 0, 2 * Math.PI); graph.stroke(); graph.fill(); - var fontSize = (player.mass / 2) + playerConfig.defaultSize; + var fontSize = (massToRadius(player.mass) / 2); graph.lineWidth = playerConfig.textBorderSize; graph.miterLimit = 1; graph.lineJoin = 'round'; @@ -366,11 +376,11 @@ function drawEnemy(enemy) { graph.fillStyle = 'hsl(' + enemy.hue + ', 70%, 50%)'; graph.lineWidth = enemyConfig.border; graph.beginPath(); - graph.arc(enemy.x - player.x + screenWidth / 2, enemy.y - player.y + screenHeight / 2, enemyConfig.defaultSize + enemy.mass, 0, 2 * Math.PI); + graph.arc(enemy.x - player.x + screenWidth / 2, enemy.y - player.y + screenHeight / 2, massToRadius(enemy.mass), 0, 2 * Math.PI); graph.fill(); graph.stroke(); - var fontSize = (enemy.mass / 2) + enemyConfig.defaultSize; + var fontSize = (massToRadius(enemy.mass) / 2); graph.lineWidth = enemyConfig.textBorderSize; graph.textAlign = 'center'; @@ -441,8 +451,8 @@ function drawborder() { } function gameInput(mouse) { - target.x = mouse.clientX; - target.y = mouse.clientY; + target.x = mouse.clientX - screenWidth / 2; + target.y = mouse.clientY - screenHeight / 2; } window.requestAnimFrame = (function(){ @@ -466,9 +476,8 @@ function gameLoop() { graph.fillRect(0, 0, screenWidth, screenHeight); drawgrid(); drawborder(); - for (var i = 0; i < foods.length; i++) { - drawFood(foods[i]); - } + + foods.forEach(function(f){ drawFood(f); }); drawborder(); From 284d18258b88df586dd30136480b82d1fbf0d610 Mon Sep 17 00:00:00 2001 From: JoeMattie Date: Fri, 5 Jun 2015 19:54:09 -0800 Subject: [PATCH 09/12] Removed Strict --- server/server.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/server/server.js b/server/server.js index c775d6812..2b0f669e1 100644 --- a/server/server.js +++ b/server/server.js @@ -1,5 +1,3 @@ -'use strict'; - var path = require('path'); var express = require('express'); var app = express(); From fb3db10773207c0a25cd67bdc94ab1d694d0bca2 Mon Sep 17 00:00:00 2001 From: Joe Mattie Date: Sat, 6 Jun 2015 06:40:00 -0800 Subject: [PATCH 10/12] Fixed server disconnect bug. Small other bugfixes. --- client/js/app.js | 6 +++--- server/server.js | 55 +++++++++++++++++++++++++----------------------- 2 files changed, 32 insertions(+), 29 deletions(-) diff --git a/client/js/app.js b/client/js/app.js index 3c5b0bc55..41a31a7e2 100644 --- a/client/js/app.js +++ b/client/js/app.js @@ -108,8 +108,8 @@ c.width = screenWidth; c.height = screenHeight; c.addEventListener('mouseout', outOfBounds, false); // register when the mouse goes off the canvas -function outOfBounds() { - target = { x : screenWidth / 2, y : screenHeight / 2 }; +function outOfBounds() { + target = { x : 0, y: 0 }; } @@ -308,7 +308,7 @@ function setupSocket(socket) { socket.on('RIP', function () { gameStart = false; died = true; - socket.close(); + // socket.close(); }); socket.on('kick', function () { diff --git a/server/server.js b/server/server.js index 2b0f669e1..4e6e61142 100644 --- a/server/server.js +++ b/server/server.js @@ -97,10 +97,12 @@ function balanceMass(){ .reduce(function(pu,cu){ return pu+cu;}); if(totalMass < c.gameMass) { + console.log('adding ' + (c.gameMass - totalMass) + ' mass to level'); addFood(c.gameMass - totalMass); console.log('mass rebalanced'); } else if(totalMass > c.gameMass){ + console.log('removing ' + (totalMass - c.gameMass) + ' mass from level'); removeFood(totalMass - c.gameMass); console.log('mass rebalanced'); } @@ -219,32 +221,33 @@ io.on('connection', function (socket) { playerCircle.r = massToRadius(currentPlayer.mass); var otherUsers = users.filter(function(user) { return user.id != currentPlayer.id; }); - var playerCollisions = null; - - if (otherUsers.length) { - playerCollisions = otherUsers.map(function(user) { - var response = new SAT.Response(); - var collided = SAT.testCircleCircle(playerCircle, - new C(new V(user.x, user.y), massToRadius(user.mass)), - response); - if (collided) { - response.aUser = currentPlayer; - response.bUser = user; - return response; - } - }) - .reduce(function(b) {return b;}); - } - - if (playerCollisions) { - console.log(playerCollisions); - playerCollisions.forEach(function(collision) { - if (playerCollisions.aUser.mass > playerCollisions.bUser.mass * 1.25 && playerCollisions.overlap > 50) { - playerCollisions.aUser.mass += playerCollisions.bUser.mass; - sockets[playerCollisions.bUser.id].emit('RIP'); - } - }); - } + var playerCollisions = []; + + otherUsers.forEach(function(user) { + var response = new SAT.Response(); + var collided = SAT.testCircleCircle(playerCircle, + new C(new V(user.x, user.y), massToRadius(user.mass)), + response); + + if (collided) { + response.aUser = currentPlayer; + response.bUser = user; + playerCollisions.push(response); + } + }); + + playerCollisions.forEach(function(collision) { + //TODO: make overlap area-based + if (collision.aUser.mass > collision.bUser.mass * 1.25 && collision.overlap > 50) { + console.log('KILLING USER: ' + collision.bUser.id); + console.log('collision info:'); + console.log(collision); + + collision.aUser.mass += collision.bUser.mass; + sockets[collision.bUser.id].emit('RIP'); + sockets[collision.bUser.id].disconnect(); + } + }); var visibleFood = food .map(function(f){ From 4352e74fa122fdb1fd33015d0a0b4ff34749f02f Mon Sep 17 00:00:00 2001 From: JoeMattie Date: Sun, 7 Jun 2015 22:44:49 -0800 Subject: [PATCH 11/12] fixed conflict --- client/js/app.js | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/client/js/app.js b/client/js/app.js index bc27a4a69..37fbe17c5 100644 --- a/client/js/app.js +++ b/client/js/app.js @@ -494,28 +494,17 @@ function gameLoop() { graph.fillStyle = backgroundColor; graph.fillRect(0, 0, screenWidth, screenHeight); drawgrid(); -<<<<<<< HEAD if(borderDraw){ drawborder(); } - for (var i = 0; i < foods.length; i++) { - drawFood(foods[i]); - } + foods.forEach(function(f){ drawFood(f); }); if(borderDraw){ drawborder(); } -======= - drawborder(); - - foods.forEach(function(f){ drawFood(f); }); - - drawborder(); - ->>>>>>> origin/refactor_fixes for (i = 0; i < enemies.length; i++) { if (enemies[i].id != player.id) { drawEnemy(enemies[i]); From 2c395a63542b6827e04e4aa48e7d5caf433bcd5a Mon Sep 17 00:00:00 2001 From: Joe Mattie Date: Mon, 8 Jun 2015 00:32:43 -0800 Subject: [PATCH 12/12] make grid static --- client/js/app.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/js/app.js b/client/js/app.js index cd264f322..b29ce6c2b 100644 --- a/client/js/app.js +++ b/client/js/app.js @@ -412,12 +412,12 @@ function drawEnemy(enemy) { } function drawgrid(){ - for (var x = xoffset; x < screenWidth; x += screenHeight / 20) { + for (var x = xoffset - player.x; x < screenWidth; x += screenHeight / 20) { graph.moveTo(x, 0); graph.lineTo(x, screenHeight); } - for (var y = yoffset ; y < screenHeight; y += screenHeight / 20) { + for (var y = yoffset - player.y ; y < screenHeight; y += screenHeight / 20) { graph.moveTo(0, y); graph.lineTo(screenWidth, y); }