123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146 |
- /*jslint bitwise: true, node: true */
- 'use strict';
- var express = require('express');
- var app = express();
- var http = require('http').Server(app);
- var io = require('socket.io')(http);
- var SAT = require('sat');
- var sql = require ("mysql");
- // Import game settings.
- var c = require('../../config.json');
- // Import utilities.
- var util = require('./lib/util');
- // Import quadtree.
- var quadtree = require('simple-quadtree');
- //call sqlinfo
- var s = c.sqlinfo;
- var tree = quadtree(0, 0, c.gameWidth, c.gameHeight);
- var users = [];
- var massFood = [];
- var food = [];
- var virus = [];
- var mothercell = [];
- var mothercellFood = [];
- var foodStructSpiral = [];
- var foodStructSpiralFood = [];
- var foodStructDotCircle = [];
- var foodStructDotCircleFood = [];
- var sockets = {};
- var leaderboard = [];
- var leaderboardChanged = false;
- var V = SAT.Vector;
- var C = SAT.Circle;
- if(s.host !== "DEFAULT") {
- var pool = sql.createConnection({
- host: s.host,
- user: s.user,
- password: s.password,
- database: s.database
- });
- //log sql errors
- pool.connect(function(err){
- if (err){
- console.log (err);
- }
- });
- }
- var initMassLog = util.log(c.defaultPlayerMass, c.slowBase);
- app.use(express.static(__dirname + '/../client'));
- function addFood(toAdd) {
- while (toAdd--) {
- var mass = util.randomInRange(c.foodMass.from,c.foodMass.to);
- var radius = util.massToRadius(mass);
- var position = c.foodUniformDisposition ? util.uniformPosition(food, radius) : util.randomPosition(radius);
- food.push({
- // Make IDs unique.
- id: ((new Date()).getTime() + '' + food.length) >>> 0,
- x: position.x,
- y: position.y,
- radius: radius,
- mass: mass,
- hue: Math.round(Math.random() * 360)
- });
- }
- }
- function addVirus(toAdd) {
- while (toAdd--) {
- var mass = util.randomInRange(c.virus.defaultMass.from, c.virus.defaultMass.to, true);
- var radius = util.massToRadius(mass);
- var position = c.virusUniformDisposition ? util.uniformPosition(virus, radius) : util.randomPosition(radius);
- virus.push({
- id: ((new Date()).getTime() + '' + virus.length) >>> 0,
- x: position.x,
- y: position.y,
- radius: radius,
- mass: mass,
- });
- }
- }
- function addMothercell(toAdd) {
- while (toAdd--) {
- var mass = util.randomInRange(c.mothercell.defaultMass.from, c.mothercell.defaultMass.to, true);
- var radius = util.massToRadius(mass);
- var position = c.mothercellUniformDisposition ? util.uniformPosition(mothercell, radius) : util.randomPosition(radius);
- mothercell.push({
- id: ((new Date()).getTime() + '' + mothercell.length) >>> 0,
- x: position.x,
- y: position.y,
- radius: radius,
- mass: mass,
- });
- }
- }
- function mothercellAddFood(mCell,toAdd,limit=true) {
- var currentCells = mothercellFood.map(function(thisFood) {
- return thisFood.for == this.id;
- },mCell).length;
- if(!limit || currentCells+toAdd <= c.mothercell.foodLimit) {
- var radius = util.massToRadius(1);
- var distance = util.randomInRange(mCell.radius+25,mCell.radius+25+(c.mothercell.foodLimit/5));
- var position = util.relativePosition({x:mCell.x,y:mCell.y},distance);
- mothercellFood.push({
- // Make IDs unique.
- id: ((new Date()).getTime() + '' + mothercellFood.length) >>> 0,
- x: position.x,
- y: position.y,
- radius: radius,
- mass: 1,
- hue: Math.round(Math.random() * 360),
- for: mCell.id
- });
- if(toAdd > 1) setTimeout(function() {mothercellAddFood(mCell,toAdd-1,limit);},100);
- }
- }
- function addFoodStructSpiral(toAdd) {
- var radius = util.massToRadius(c.foodStruct.spiral.centerMass);
- var foodRadius = util.massToRadius(c.foodStruct.spiral.borderMass);
- while (toAdd--) {
- var position = c.foodUniformDisposition ? util.uniformPosition(foodStructSpiral, radius) : util.randomPosition(radius);
- var hue = Math.round(Math.random() * 360);
- foodStructSpiral.push({
- // Make IDs unique.
- id: ((new Date()).getTime() + '' + foodStructSpiral.length) >>> 0,
- x: position.x,
- y: position.y,
- radius: radius,
- mass: c.foodStruct.spiral.centerMass,
- hue: hue
- });
- var addSpiralDots = 20;
- for(var i=0;i<addSpiralDots/2;i++) {
- var aFoodPosition = util.relativePosition(position,radius+15+(i*3),foodRadius*1.7*i-90);
- foodStructSpiralFood.push({
- // Make IDs unique.
- id: ((new Date()).getTime() + '' + foodStructSpiralFood.length) >>> 0,
- x: aFoodPosition.x,
- y: aFoodPosition.y,
- radius: foodRadius,
- mass: c.foodStruct.spiral.borderMass,
- hue: hue+(i*3)
- });
- }
- for(i=0;i<addSpiralDots/2;i++) {
- var bFoodPosition = util.relativePosition(position,radius+15+(i*3),foodRadius*1.7*i+90);
- foodStructSpiralFood.push({
- // Make IDs unique.
- id: ((new Date()).getTime() + '' + foodStructSpiralFood.length) >>> 0,
- x: bFoodPosition.x,
- y: bFoodPosition.y,
- radius: foodRadius,
- mass: c.foodStruct.spiral.borderMass,
- hue: hue-(i*3)
- });
- }
- }
- }
- function addFoodStructDotCircle(toAdd) {
- var radius = util.massToRadius(c.foodStruct.dotCircle.centerMass);
- var dotRadius = util.massToRadius(c.foodStruct.dotCircle.borderDotMass);
- var foodRadius = util.massToRadius(c.foodStruct.dotCircle.borderMass);
- while (toAdd--) {
- var position = c.foodUniformDisposition ? util.uniformPosition(foodStructDotCircle, radius) : util.randomPosition(radius);
- var dotHue = Math.round(Math.random() * 360);
- var foodHue = Math.round(Math.random() * 360);
- foodStructDotCircle.push({
- // Make IDs unique.
- id: ((new Date()).getTime() + '' + foodStructDotCircle.length) >>> 0,
- x: position.x,
- y: position.y,
- radius: radius,
- mass: c.foodStruct.dotCircle.centerMass,
- hue: Math.round(Math.random() * 360)
- });
- var addBorderDots = 25;
- var addBorderFood = 5;
- for(var i=0;i<addBorderDots;i++) {
- var dotPosition = util.relativePosition(position,radius+15,(360/addBorderDots*i)-90);
- foodStructDotCircleFood.push({
- // Make IDs unique.
- id: ((new Date()).getTime() + '' + foodStructDotCircleFood.length) >>> 0,
- x: dotPosition.x,
- y: dotPosition.y,
- radius: dotRadius,
- mass: c.foodStruct.dotCircle.borderDotMass,
- hue: dotHue
- });
- }
- for(i=0;i<addBorderFood;i++) {
- var foodPosition = util.relativePosition(position,radius+15,(360/addBorderFood*i)-90);
- foodStructDotCircleFood.push({
- // Make IDs unique.
- id: ((new Date()).getTime() + '' + foodStructDotCircleFood.length) >>> 0,
- x: foodPosition.x,
- y: foodPosition.y,
- radius: foodRadius,
- mass: c.foodStruct.dotCircle.borderMass,
- hue: foodHue
- });
- }
- }
- }
- function removeFood(toRem) {
- while (toRem--) {
- food.pop();
- }
- }
- function movePlayer(player) {
- var x =0,y =0;
- for(var i=0; i<player.cells.length; i++)
- {
- var target = {
- x: player.x - player.cells[i].x + player.target.x,
- y: player.y - player.cells[i].y + player.target.y
- };
- var dist = Math.sqrt(Math.pow(target.y, 2) + Math.pow(target.x, 2));
- var deg = Math.atan2(target.y, target.x);
- var slowDown = 1;
- if(player.cells[i].speed <= 6.25) {
- slowDown = util.log(player.cells[i].mass, c.slowBase) - initMassLog + 1;
- }
- var deltaY = player.cells[i].speed * Math.sin(deg)/ slowDown;
- var deltaX = player.cells[i].speed * Math.cos(deg)/ slowDown;
- if(player.cells[i].speed > 6.25) {
- player.cells[i].speed -= 0.5;
- }
- if (dist < (50 + player.cells[i].radius)) {
- deltaY *= dist / (50 + player.cells[i].radius);
- deltaX *= dist / (50 + player.cells[i].radius);
- }
- if (!isNaN(deltaY)) {
- player.cells[i].y += deltaY;
- }
- if (!isNaN(deltaX)) {
- player.cells[i].x += deltaX;
- }
- // Find best solution.
- for(var j=0; j<player.cells.length; j++) {
- if(j != i && player.cells[i] !== undefined) {
- var distance = Math.sqrt(Math.pow(player.cells[j].y-player.cells[i].y,2) + Math.pow(player.cells[j].x-player.cells[i].x,2));
- var radiusTotal = (player.cells[i].radius + player.cells[j].radius);
- if(distance < radiusTotal) {
- if(player.lastSplit > new Date().getTime() - 1000 * c.mergeTimer) {
- if(player.cells[i].x < player.cells[j].x) {
- player.cells[i].x--;
- } else if(player.cells[i].x > player.cells[j].x) {
- player.cells[i].x++;
- }
- if(player.cells[i].y < player.cells[j].y) {
- player.cells[i].y--;
- } else if((player.cells[i].y > player.cells[j].y)) {
- player.cells[i].y++;
- }
- }
- else if(distance < radiusTotal / 1.75) {
- player.cells[i].mass += player.cells[j].mass;
- player.cells[i].radius = util.massToRadius(player.cells[i].mass);
- player.cells.splice(j, 1);
- }
- }
- }
- }
- if(player.cells.length > i) {
- var borderCalc = player.cells[i].radius / 3;
- if (player.cells[i].x > c.gameWidth - borderCalc) {
- player.cells[i].x = c.gameWidth - borderCalc;
- }
- if (player.cells[i].y > c.gameHeight - borderCalc) {
- player.cells[i].y = c.gameHeight - borderCalc;
- }
- if (player.cells[i].x < borderCalc) {
- player.cells[i].x = borderCalc;
- }
- if (player.cells[i].y < borderCalc) {
- player.cells[i].y = borderCalc;
- }
- x += player.cells[i].x;
- y += player.cells[i].y;
- }
- }
- player.x = x/player.cells.length;
- player.y = y/player.cells.length;
- }
- function moveMass(mass) {
- var deg = Math.atan2(mass.target.y, mass.target.x);
- var deltaY = mass.speed * Math.sin(deg);
- var deltaX = mass.speed * Math.cos(deg);
- mass.speed -= 0.5;
- if(mass.speed < 0) {
- mass.speed = 0;
- }
- if (!isNaN(deltaY)) {
- mass.y += deltaY;
- }
- if (!isNaN(deltaX)) {
- mass.x += deltaX;
- }
- var borderCalc = mass.radius + 5;
- if (mass.x > c.gameWidth - borderCalc) {
- mass.x = c.gameWidth - borderCalc;
- }
- if (mass.y > c.gameHeight - borderCalc) {
- mass.y = c.gameHeight - borderCalc;
- }
- if (mass.x < borderCalc) {
- mass.x = borderCalc;
- }
- if (mass.y < borderCalc) {
- mass.y = borderCalc;
- }
- }
- function balanceMass() {
- var totalMass = food.length * (c.foodMass.from+c.foodMass.to)/2 +
- users
- .map(function(u) {return u.massTotal; })
- .reduce(function(pu,cu) { return pu+cu;}, 0);
- var massDiff = c.gameMass - totalMass;
- var maxFoodDiff = c.maxFood - food.length;
- var foodDiff = parseInt(massDiff / (c.foodMass.from+c.foodMass.to)/2) - maxFoodDiff;
- var foodToAdd = Math.min(foodDiff, maxFoodDiff);
- var foodToRemove = -Math.max(foodDiff, maxFoodDiff);
- if (foodToAdd > 0) {
- //console.log('[DEBUG] Adding ' + foodToAdd + ' food to level!');
- addFood(foodToAdd);
- //console.log('[DEBUG] Mass rebalanced!');
- }
- else if (foodToRemove > 0) {
- //console.log('[DEBUG] Removing ' + foodToRemove + ' food from level!');
- removeFood(foodToRemove);
- //console.log('[DEBUG] Mass rebalanced!');
- }
- var virusToAdd = c.maxVirus - virus.length;
- if (virusToAdd > 0) {
- addVirus(virusToAdd);
- }
- var mothercellToAdd = c.maxMothercell - mothercell.length;
- if (mothercellToAdd > 0) {
- addMothercell(mothercellToAdd);
- }
- var foodStructSpiralToAdd = c.foodStruct.spiral.limit - foodStructSpiral.length;
- if (foodStructSpiralToAdd > 0) {
- addFoodStructSpiral(foodStructSpiralToAdd);
- }
- var foodStructDotCircleToAdd = c.foodStruct.dotCircle.limit - foodStructDotCircle.length;
- if (foodStructDotCircleToAdd > 0) {
- addFoodStructDotCircle(foodStructDotCircleToAdd);
- }
- }
- io.on('connection', function (socket) {
- console.log('A user connected!', socket.handshake.query.type);
- var type = socket.handshake.query.type;
- var radius = util.massToRadius(c.defaultPlayerMass);
- var position = c.newPlayerInitialPosition == 'farthest' ? util.uniformPosition(users, radius) : util.randomPosition(radius);
- var cells = [];
- var massTotal = 0;
- if(type === 'player') {
- cells = [{
- mass: c.defaultPlayerMass,
- x: position.x,
- y: position.y,
- radius: radius
- }];
- massTotal = c.defaultPlayerMass;
- }
- var currentPlayer = {
- id: socket.id,
- x: position.x,
- y: position.y,
- w: c.defaultPlayerMass,
- h: c.defaultPlayerMass,
- cells: cells,
- massTotal: massTotal,
- hue: Math.round(Math.random() * 360),
- type: type,
- lastHeartbeat: new Date().getTime(),
- target: {
- x: 0,
- y: 0
- }
- };
- socket.on('gotit', function (player) {
- player.name = player.name.substr(0,25);
- console.log('[INFO] Player ' + player.name + ' connecting!');
- if (util.findIndex(users, player.id) > -1) {
- console.log('[INFO] Player ID is already connected, kicking.');
- socket.disconnect();
- } else if (!util.validNick(player.name)) {
- socket.emit('kick', 'Invalid username.');
- socket.disconnect();
- } else {
- console.log('[INFO] Player ' + player.name + ' connected!');
- sockets[player.id] = socket;
- var radius = util.massToRadius(c.defaultPlayerMass);
- var position = c.newPlayerInitialPosition == 'farthest' ? util.uniformPosition(users, radius) : util.randomPosition(radius);
- player.x = position.x;
- player.y = position.y;
- player.target.x = 0;
- player.target.y = 0;
- if(type === 'player') {
- player.cells = [{
- mass: c.defaultPlayerMass,
- x: position.x,
- y: position.y,
- radius: radius
- }];
- player.massTotal = c.defaultPlayerMass;
- }
- else {
- player.cells = [];
- player.massTotal = 0;
- }
- player.hue = Math.round(Math.random() * 360);
- currentPlayer = player;
- currentPlayer.lastHeartbeat = new Date().getTime();
- users.push(currentPlayer);
- io.emit('playerJoin', { name: currentPlayer.name });
- socket.emit('gameSetup', {
- gameWidth: c.gameWidth,
- gameHeight: c.gameHeight,
- virus:{
- fill: c.virus.fill,
- stroke: c.virus.stroke,
- strokeWidth: c.virus.strokeWidth
- },
- mothercell:{
- fill: c.mothercell.fill,
- stroke: c.mothercell.stroke,
- strokeWidth: c.mothercell.strokeWidth
- }
- });
- console.log('Total players: ' + users.length);
- }
- });
- socket.on('pingcheck', function () {
- socket.emit('pongcheck');
- });
- socket.on('windowResized', function (data) {
- currentPlayer.screenWidth = data.screenWidth;
- currentPlayer.screenHeight = data.screenHeight;
- });
- socket.on('respawn', function () {
- if (util.findIndex(users, currentPlayer.id) > -1)
- users.splice(util.findIndex(users, currentPlayer.id), 1);
- socket.emit('welcome', currentPlayer);
- console.log('[INFO] User ' + currentPlayer.name + ' respawned!');
- });
- socket.on('disconnect', function () {
- if (util.findIndex(users, currentPlayer.id) > -1)
- users.splice(util.findIndex(users, currentPlayer.id), 1);
- console.log('[INFO] User ' + currentPlayer.name + ' disconnected!');
- socket.broadcast.emit('playerDisconnect', { name: currentPlayer.name });
- });
- socket.on('playerChat', function(data) {
- if (c.logChat === 1) {
- console.log('[CHAT] [' + (new Date()).getHours() + ':' + (new Date()).getMinutes() + '] ' + currentPlayer.name + ': ' + data);
- }
- socket.broadcast.emit('serverSendPlayerChat', {sender: currentPlayer.name, hue: currentPlayer.hue, message: data});
- });
- socket.on('pass', function(data) {
- if (data[0] === c.adminPass) {
- console.log('[ADMIN] ' + currentPlayer.name + ' just logged in as an admin!');
- socket.emit('serverMSG', 'Welcome back ' + currentPlayer.name);
- socket.broadcast.emit('serverMSG', currentPlayer.name + ' just logged in as admin!');
- currentPlayer.admin = true;
- } else {
-
- // TODO: Actually log incorrect passwords.
- console.log('[ADMIN] ' + currentPlayer.name + ' attempted to log in with incorrect password.');
- socket.emit('serverMSG', 'Password incorrect, attempt logged.');
- //pool.query('INSERT INTO logging SET name=' + currentPlayer.name + ', reason="Invalid login attempt as admin"');
- }
- });
- socket.on('whisper', function(data) {
- var userFound = false;
- if(data.length > 1) {
- for(var e = 0; e < users.length; e++) {
- if(currentPlayer.name === data[0]) {
- socket.emit('serverMSG', 'You cannot whisper to yourself.');
- return;
- }
- if(users[e].name === data[0]) {
- userFound = true;
- var message = "";
- for(var f = 1; f < data.length; f++)
- message = message + data[f] + " ";
- sockets[users[e].id].emit('serverSendPlayerChat', {sender: currentPlayer.name, hue: currentPlayer.hue, message: message, prefix: 'WHISPER <-'});
- socket.emit('serverSendPlayerChat', {sender: currentPlayer.name, hue: currentPlayer.hue, message: message, prefix: 'WHISPER ->'});
- }
- }
- if(!userFound) {
- socket.emit('serverMSG', 'This user is not online.');
- }
- } else {
- socket.emit('serverMSG', 'Please enter a name and a message.');
- }
- });
- socket.on('kick', function(data) {
- if (currentPlayer.admin) {
- var reason = '';
- var worked = false;
- for (var e = 0; e < users.length; e++) {
- if (users[e].name === data[0] && !users[e].admin && !worked) {
- if (data.length > 1) {
- for (var f = 1; f < data.length; f++) {
- if (f === data.length) {
- reason = reason + data[f];
- }
- else {
- reason = reason + data[f] + ' ';
- }
- }
- }
- if (reason !== '') {
- console.log('[ADMIN] User ' + users[e].name + ' kicked successfully by ' + currentPlayer.name + ' for reason ' + reason);
- }
- else {
- console.log('[ADMIN] User ' + users[e].name + ' kicked successfully by ' + currentPlayer.name);
- }
- socket.emit('serverMSG', 'User ' + users[e].name + ' was kicked by ' + currentPlayer.name);
- sockets[users[e].id].emit('kick', reason);
- sockets[users[e].id].disconnect();
- users.splice(e, 1);
- worked = true;
- }
- }
- if (!worked) {
- socket.emit('serverMSG', 'Could not locate user or user is an admin.');
- }
- } else {
- console.log('[ADMIN] ' + currentPlayer.name + ' is trying to use -kick but isn\'t an admin.');
- socket.emit('serverMSG', 'You are not permitted to use this command.');
- }
- });
- // Heartbeat function, update everytime.
- socket.on('0', function(target) {
- currentPlayer.lastHeartbeat = new Date().getTime();
- if (target.x !== currentPlayer.x || target.y !== currentPlayer.y) {
- currentPlayer.target = target;
- }
- });
- socket.on('1', function() {
- // Fire food.
- for(var i=0; i<currentPlayer.cells.length; i++)
- {
- if(((currentPlayer.cells[i].mass >= c.defaultPlayerMass + c.fireFood) && c.fireFood > 0) || (currentPlayer.cells[i].mass >= 20 && c.fireFood === 0)){
- var masa = 1;
- if(c.fireFood > 0)
- masa = c.fireFood;
- else
- masa = currentPlayer.cells[i].mass*0.1;
- currentPlayer.cells[i].mass -= masa;
- currentPlayer.massTotal -=masa;
- massFood.push({
- id: currentPlayer.id,
- num: i,
- masa: masa,
- hue: currentPlayer.hue,
- target: {
- x: currentPlayer.x - currentPlayer.cells[i].x + currentPlayer.target.x,
- y: currentPlayer.y - currentPlayer.cells[i].y + currentPlayer.target.y
- },
- x: currentPlayer.cells[i].x,
- y: currentPlayer.cells[i].y,
- radius: util.massToRadius(masa),
- speed: 25
- });
- }
- }
- });
- socket.on('2', function() {
- function splitCell(cell) {
- if(cell && cell.mass && cell.mass >= c.defaultPlayerMass*2) {
- cell.mass = cell.mass/2;
- cell.radius = util.massToRadius(cell.mass);
- currentPlayer.cells.push({
- mass: cell.mass,
- x: cell.x,
- y: cell.y,
- radius: cell.radius,
- speed: 25
- });
- }
- }
- if(currentPlayer.cells.length < c.limitSplit && currentPlayer.massTotal >= c.defaultPlayerMass*2) {
- //Split all cells
- if(currentPlayer.cells.length < c.limitSplit && currentPlayer.massTotal >= c.defaultPlayerMass*2) {
- var numMax = currentPlayer.cells.length;
- for(var d=0; d<numMax; d++) {
- splitCell(currentPlayer.cells[d]);
- }
- }
- currentPlayer.lastSplit = new Date().getTime();
- }
- });
- });
- function tickPlayer(currentPlayer) {
- if(currentPlayer.lastHeartbeat < new Date().getTime() - c.maxHeartbeatInterval) {
- sockets[currentPlayer.id].emit('kick', 'Last heartbeat received over ' + c.maxHeartbeatInterval + ' ago.');
- sockets[currentPlayer.id].disconnect();
- }
- movePlayer(currentPlayer);
- function funcFood(f) {
- return SAT.pointInCircle(new V(f.x, f.y), playerCircle);
- }
- function deleteFood(f) {
- if(currentCell.mass > food[f].mass) {
- currentCell.mass += food[f].mass;
- currentPlayer.massTotal += food[f].mass;
- food.splice(f, 1);
- }
- }
- function deleteMothercellFood(f) {
- if(currentCell.mass > mothercellFood[f].mass) {
- currentCell.mass += mothercellFood[f].mass;
- currentPlayer.massTotal += mothercellFood[f].mass;
- mothercellFood.splice(f, 1);
- }
- }
- function deleteFoodStructSpiral(f) {
- if(currentCell.mass > foodStructSpiral[f].mass) {
- currentCell.mass += foodStructSpiral[f].mass;
- currentPlayer.massTotal += foodStructSpiral[f].mass;
- foodStructSpiral.splice(f, 1);
- }
- }
- function deleteFoodStructSpiralFood(f) {
- if(currentCell.mass > foodStructSpiralFood[f].mass) {
- currentCell.mass += foodStructSpiralFood[f].mass;
- currentPlayer.massTotal += foodStructSpiralFood[f].mass;
- foodStructSpiralFood.splice(f, 1);
- }
- }
- function deleteFoodStructDotCircle(f) {
- if(currentCell.mass > foodStructDotCircle[f].mass) {
- currentCell.mass += foodStructDotCircle[f].mass;
- currentPlayer.massTotal += foodStructDotCircle[f].mass;
- foodStructDotCircle.splice(f, 1);
- }
- }
- function deleteFoodStructDotCircleFood(f) {
- if(currentCell.mass > foodStructDotCircleFood[f].mass) {
- currentCell.mass += foodStructDotCircleFood[f].mass;
- currentPlayer.massTotal += foodStructDotCircleFood[f].mass;
- foodStructDotCircleFood.splice(f, 1);
- }
- }
- function eatMass(m) {
- if(SAT.pointInCircle(new V(m.x, m.y), playerCircle)){
- if(m.id == currentPlayer.id && m.speed > 0 && z == m.num)
- return false;
- if(currentCell.mass > m.masa * 1.1)
- return true;
- }
- return false;
- }
- function check(user) {
- for(var i=0; i<user.cells.length; i++) {
- if(user.cells[i].mass > 10 && user.id !== currentPlayer.id) {
- var response = new SAT.Response();
- var collided = SAT.testCircleCircle(playerCircle,
- new C(new V(user.cells[i].x, user.cells[i].y), user.cells[i].radius),
- response);
- if (collided) {
- response.aUser = currentCell;
- response.bUser = {
- id: user.id,
- name: user.name,
- x: user.cells[i].x,
- y: user.cells[i].y,
- num: i,
- mass: user.cells[i].mass
- };
- playerCollisions.push(response);
- }
- }
- }
- return true;
- }
-
- function checkMothercell(mCell) {
- var response = new SAT.Response();
- var collided = SAT.testCircleCircle(playerCircle,
- new C(new V(mCell.x, mCell.y), mCell.radius),
- response);
- if (collided) {
- response.bUser = {
- id: currentPlayer.id,
- name: currentPlayer.name,
- x: currentCell.x,
- y: currentCell.y,
- mass: currentCell.mass,
- num: currentPlayer.cells.indexOf(currentCell)
- };
- response.aUser = {
- id: mCell.id,
- x: mCell.x,
- y: mCell.y,
- mass: mCell.mass,
- radius: mCell.radius
- };
- return response;
- }
- return false;
- }
- function collisionCheck(collision) {
- if (collision.aUser.mass > collision.bUser.mass * 1.1 && collision.aUser.radius > Math.sqrt(Math.pow(collision.aUser.x - collision.bUser.x, 2) + Math.pow(collision.aUser.y - collision.bUser.y, 2))*1.75) {
- console.log('[DEBUG] Killing user: ' + collision.bUser.name);
- console.log('[DEBUG] Collision info:');
- console.log(collision);
- var numUser = util.findIndex(users, collision.bUser.id);
- if (numUser > -1) {
- if(users[numUser].cells.length > 1) {
- users[numUser].massTotal -= collision.bUser.mass;
- users[numUser].cells.splice(collision.bUser.num, 1);
- } else {
- users.splice(numUser, 1);
- io.emit('playerDied', { name: collision.bUser.name });
- sockets[collision.bUser.id].emit('RIP');
- }
- }
- currentPlayer.massTotal += collision.bUser.mass;
- collision.aUser.mass += collision.bUser.mass;
- }
- }
- function mothercellCollisionCheck(collision) {
- if (collision.aUser.mass > collision.bUser.mass * 1.1 && collision.aUser.radius > Math.sqrt(Math.pow(collision.aUser.x - collision.bUser.x, 2) + Math.pow(collision.aUser.y - collision.bUser.y, 2))*1.75) {
- console.log('[DEBUG] Killing user: ' + collision.bUser.name);
- console.log('[DEBUG] Collision info:');
- console.log(collision);
- var numUser = util.findIndex(users, collision.bUser.id);
- if (numUser > -1) {
- if(users[numUser].cells.length > 1) {
- users[numUser].massTotal -= collision.bUser.mass;
- users[numUser].cells.splice(collision.bUser.num, 1);
- } else {
- users.splice(numUser, 1);
- io.emit('playerSuicide', { name: collision.bUser.name });
- sockets[collision.bUser.id].emit('RIP');
- }
- }
- mothercellAddFood(collision.aUser,Math.round(collision.bUser.mass),false);
- }
- }
- function splitCell(cell) {
- if(cell && cell.mass) {
- var thisUser = util.findIndex(users,currentPlayer.id);
- var parts = c.virus.splitParts-1;
- for(var i=0;i<c.virus.splitParts-1;i++) {
- if(cell.mass < c.defaultPlayerMass * parts || currentPlayer.cells.length + parts > c.limitSplit) parts--;
- }
- if(parts > 1) {
- cell.mass = cell.mass/parts;
- cell.radius = util.massToRadius(cell.mass);
- for(var a=0;a<parts;a++) {
- currentPlayer.cells.push({
- mass: cell.mass,
- x: cell.x,
- y: cell.y,
- radius: cell.radius,
- speed: 25
- });
- }
- }
- }
- }
- for(var z=0; z<currentPlayer.cells.length; z++) {
- var currentCell = currentPlayer.cells[z];
- var playerCircle = new C(
- new V(currentCell.x, currentCell.y),
- currentCell.radius
- );
- var foodEaten = food.map(funcFood)
- .reduce( function(a, b, c) { return b ? a.concat(c) : a; }, []);
- foodEaten.forEach(deleteFood);
- var mothercellFoodEaten = mothercellFood.map(funcFood)
- .reduce( function(a, b, c) { return b ? a.concat(c) : a; }, []);
- mothercellFoodEaten.forEach(deleteMothercellFood);
- var foodStructSpiralEaten = foodStructSpiral.map(funcFood)
- .reduce( function(a, b, c) { return b ? a.concat(c) : a; }, []);
- foodStructSpiralEaten.forEach(deleteFoodStructSpiral);
- var foodStructSpiralFoodEaten = foodStructSpiralFood.map(funcFood)
- .reduce( function(a, b, c) { return b ? a.concat(c) : a; }, []);
- foodStructSpiralFoodEaten.forEach(deleteFoodStructSpiralFood);
- var foodStructDotCircleEaten = foodStructDotCircle.map(funcFood)
- .reduce( function(a, b, c) { return b ? a.concat(c) : a; }, []);
- foodStructDotCircleEaten.forEach(deleteFoodStructDotCircle);
- var foodStructDotCircleFoodEaten = foodStructDotCircleFood.map(funcFood)
- .reduce( function(a, b, c) { return b ? a.concat(c) : a; }, []);
- foodStructDotCircleFoodEaten.forEach(deleteFoodStructDotCircleFood);
- var massEaten = massFood.map(eatMass)
- .reduce(function(a, b, c) {return b ? a.concat(c) : a; }, []);
- var virusCollision = virus.map(funcFood)
- .reduce( function(a, b, c) { return b ? a.concat(c) : a; }, []);
- if(virusCollision > 0 && currentCell.mass > virus[virusCollision].mass) {
- currentCell.mass += virus[virusCollision].mass;
- currentPlayer.massTotal += virus[virusCollision].mass;
- virus.splice(virusCollision, 1);
- splitCell(currentPlayer.cells[z]);
- currentPlayer.lastSplit = new Date().getTime();
- }
- var mothercellCollision = mothercell.map(funcFood)
- .reduce( function(a, b, c) { return b ? a.concat(c) : a; }, []);
- if(mothercellCollision > 0 && currentCell.mass > mothercell[mothercellCollision].mass) {
- currentCell.mass += mothercell[mothercellCollision].mass;
- currentPlayer.massTotal += mothercell[mothercellCollision].mass;
- mothercell.splice(mothercellCollision, 1);
- splitCell(currentPlayer.cells[z]);
- currentPlayer.lastSplit = new Date().getTime();
- }
- var masaGanada = 0;
- for(var m=0; m<massEaten.length; m++) {
- masaGanada += massFood[massEaten[m]].masa;
- massFood[massEaten[m]] = {};
- massFood.splice(massEaten[m],1);
- for(var n=0; n<massEaten.length; n++) {
- if(massEaten[m] < massEaten[n]) {
- massEaten[n]--;
- }
- }
- }
- if(typeof(currentCell.speed) == "undefined")
- currentCell.speed = 6.25;
- currentCell.mass += masaGanada;
- currentPlayer.massTotal += masaGanada;
- currentCell.radius = util.massToRadius(currentCell.mass);
- playerCircle.r = currentCell.radius;
- tree.clear();
- users.forEach(tree.put);
- var playerCollisions = [];
- var otherUsers = tree.get({x:currentCell.x, y: currentCell.y, w: currentCell.radius * 2, h: currentCell.radius * 2}, check);
- playerCollisions.forEach(collisionCheck);
- if(mothercellCollision > 0 && currentCell.mass < mothercell[mothercellCollision].mass) {
- var mCellCheck = checkMothercell(mothercell[mothercellCollision]);
- if(mCellCheck) mothercellCollisionCheck(mCellCheck);
- }
- }
- }
- function moveloop() {
- for (var i = 0; i < users.length; i++) {
- tickPlayer(users[i]);
- }
- for (i=0; i < massFood.length; i++) {
- if(massFood[i].speed > 0) moveMass(massFood[i]);
- }
- }
- function gameloop() {
- if (users.length > 0) {
- users.sort( function(a, b) { return b.massTotal - a.massTotal; });
- var topUsers = [];
- for (var i = 0; i < Math.min(10, users.length); i++) {
- if(users[i].type == 'player') {
- topUsers.push({
- id: users[i].id,
- hue: users[i].hue,
- name: users[i].name,
- mass: Math.round(users[i].massTotal)
- });
- }
- }
- if (isNaN(leaderboard) || leaderboard.length !== topUsers.length) {
- leaderboard = topUsers;
- leaderboardChanged = true;
- }
- else {
- for (i = 0; i < leaderboard.length; i++) {
- if (leaderboard[i].id !== topUsers[i].id) {
- leaderboard = topUsers;
- leaderboardChanged = true;
- break;
- }
- }
- }
- for (i = 0; i < users.length; i++) {
- for(var z=0; z < users[i].cells.length; z++) {
- if (users[i].cells[z].mass * (1 - (c.massLossRate / 1000)) > c.defaultPlayerMass && users[i].massTotal > c.minMassLoss) {
- var massLoss = users[i].cells[z].mass * (1 - (c.massLossRate / 1000));
- users[i].massTotal -= users[i].cells[z].mass - massLoss;
- users[i].cells[z].mass = massLoss;
- }
- }
- }
- }
- balanceMass();
- }
- function sendUpdates() {
- users.forEach( function(u) {
- // center the view if x/y is undefined, this will happen for spectators
- u.x = u.x || c.gameWidth / 2;
- u.y = u.y || c.gameHeight / 2;
- var visibleFood = food
- .concat(mothercellFood)
- .concat(foodStructSpiral)
- .concat(foodStructSpiralFood)
- .concat(foodStructDotCircle)
- .concat(foodStructDotCircleFood)
- .map(function(f) {
- if ( f.x > u.x - u.screenWidth/2 - 20 &&
- f.x < u.x + u.screenWidth/2 + 20 &&
- f.y > u.y - u.screenHeight/2 - 20 &&
- f.y < u.y + u.screenHeight/2 + 20) {
- return {
- i: f.id,
- x: util.round(f.x,1),
- y: util.round(f.y,1),
- r: util.round(f.radius,2),
- m: util.round(f.mass,2),
- h: f.hue
- };
- }
- })
- .filter(function(f) { return f; });
- var visibleVirus = virus
- .map(function(f) {
- if ( f.x > u.x - u.screenWidth/2 - f.radius &&
- f.x < u.x + u.screenWidth/2 + f.radius &&
- f.y > u.y - u.screenHeight/2 - f.radius &&
- f.y < u.y + u.screenHeight/2 + f.radius) {
- return {
- i: f.id,
- x: util.round(f.x,1),
- y: util.round(f.y,1),
- r: util.round(f.radius,2),
- m: util.round(f.mass,2)
- };
- }
- })
- .filter(function(f) { return f; });
- var visibleMothercell = mothercell
- .map(function(f) {
- if ( f.x > u.x - u.screenWidth/2 - f.radius &&
- f.x < u.x + u.screenWidth/2 + f.radius &&
- f.y > u.y - u.screenHeight/2 - f.radius &&
- f.y < u.y + u.screenHeight/2 + f.radius) {
- return {
- i: f.id,
- x: util.round(f.x,1),
- y: util.round(f.y,1),
- r: util.round(f.radius,2),
- m: util.round(f.mass,2)
- };
- }
- })
- .filter(function(f) { return f; });
- var visibleMass = massFood
- .map(function(f) {
- if ( f.x+f.radius > u.x - u.screenWidth/2 - 20 &&
- f.x-f.radius < u.x + u.screenWidth/2 + 20 &&
- f.y+f.radius > u.y - u.screenHeight/2 - 20 &&
- f.y-f.radius < u.y + u.screenHeight/2 + 20) {
- return {
- i: f.id,
- n: f.num,
- m: f.masa,
- h: f.hue,
- t: {
- x:util.round(f.target.x,1),
- y:util.round(f.target.y,1)
- },
- x: util.round(f.x,1),
- y: util.round(f.y,1),
- r: util.round(f.radius,2),
- s: f.speed
- };
- }
- })
- .filter(function(f) { return f; });
- var visibleCells = users
- .map(function(f) {
- var rcells = f.cells.map(function(c) {
- return {
- m: Math.round(c.mass),
- x: util.round(c.x,1),
- y: util.round(c.y,1),
- r: util.round(c.radius,2),
- s: c.speed
- };
- });
- for(var z=0; z<f.cells.length; z++)
- {
- if ( f.cells[z].x+f.cells[z].radius > u.x - u.screenWidth/2 - 20 &&
- f.cells[z].x-f.cells[z].radius < u.x + u.screenWidth/2 + 20 &&
- f.cells[z].y+f.cells[z].radius > u.y - u.screenHeight/2 - 20 &&
- f.cells[z].y-f.cells[z].radius < u.y + u.screenHeight/2 + 20) {
- z = f.cells.lenth;
- if(f.id !== u.id) {
- return {
- i: f.id,
- x: util.round(f.x,1),
- y: util.round(f.y,1),
- c: rcells,
- m: Math.round(f.massTotal),
- h: f.hue,
- n: f.name
- };
- } else {
- //console.log("Nombre: " + f.name + " Es Usuario");
- return {
- x: util.round(f.x,1),
- y: util.round(f.y,1),
- c: rcells,
- m: Math.round(f.massTotal),
- h: f.hue,
- };
- }
- }
- }
- })
- .filter(function(f) { return f; });
- sockets[u.id].emit('m', visibleCells, visibleFood, visibleMass, visibleVirus, visibleMothercell);
- if (leaderboardChanged) {
- sockets[u.id].emit('leaderboard', {
- players: users.length,
- leaderboard: leaderboard
- });
- }
- });
- leaderboardChanged = false;
- }
- function mothercellFeed() {
- for(var i=0;i<mothercell.length;i++) {
- mothercellAddFood(mothercell[i],1);
- }
- }
- setInterval(moveloop, 1000 / 60);
- setInterval(gameloop, 1000);
- setInterval(sendUpdates, 1000 / c.networkUpdateFactor);
- setInterval(mothercellFeed, 60000 / c.mothercell.foodSpeed);
- // Don't touch, IP configurations.
- var ipaddress = process.env.OPENSHIFT_NODEJS_IP || process.env.IP || c.host;
- var serverport = process.env.OPENSHIFT_NODEJS_PORT || process.env.PORT || c.port;
- http.listen( serverport, ipaddress, function() {
- console.log('[DEBUG] Listening on ' + ipaddress + ':' + serverport);
- });
|