diff --git a/.gitignore b/.gitignore index 3b66d27..17935ea 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1 @@ -*node_modules/* +*node_modules/* diff --git a/TODO.md b/TODO.md index f22a8c0..40a0640 100644 --- a/TODO.md +++ b/TODO.md @@ -1,42 +1,42 @@ -# Project To Do list - -## Short Term - - [] Kill socket when browser closes/inactive. - - [] Make client get textures from single sprite sheet - -## Mid Term - - [] Implement Rooms with different games on server - - [] Add room selection menu on client - - [] Implement Players - - [] Player Names - - [] Player Colors - - [] Prevent Duplicate player info -## Long Term - - [] Power and money system for players - - [] Add land ownership - - [] Land Claiming - - [] Difficulty to claim hills and seas - - [] Create bouy flag sprite - - [] Make differentiation between land owned by different players - - [] System to have animated widgets overtop of the canvas. - - [] Explosion - - [] Selection cursor - - [] Color for different land status (claimed/open/unclaimable) - - [] Create spites for classes of buildings for economy. - - [x] Factory - - [x] Farmland/town - - [] Fishing area - - [] Building selection menu -## Longer Term - - - [] Add tests to ensure features act as they should - - [] Handle player death/leaving - - [] Dead player's resources go to killer with some tax. - - [] Leaving player's resources go to player -## Finishing Touches - - [] Sounds - - [] Graphics Redo - - [] Fancy webpage decorations - -## Maybe - - [] Chat +# Project To Do list + +## Short Term + - [] Kill socket when browser closes/inactive. + - [] Make client get textures from single sprite sheet + +## Mid Term + - [] Implement Rooms with different games on server + - [] Add room selection menu on client + - [] Implement Players + - [] Player Names + - [] Player Colors + - [] Prevent Duplicate player info +## Long Term + - [] Power and money system for players + - [] Add land ownership + - [] Land Claiming + - [] Difficulty to claim hills and seas + - [] Create bouy flag sprite + - [] Make differentiation between land owned by different players + - [] System to have animated widgets overtop of the canvas. + - [] Explosion + - [] Selection cursor + - [] Color for different land status (claimed/open/unclaimable) + - [] Create spites for classes of buildings for economy. + - [x] Factory + - [x] Farmland/town + - [] Fishing area + - [] Building selection menu +## Longer Term + + - [] Add tests to ensure features act as they should + - [] Handle player death/leaving + - [] Dead player's resources go to killer with some tax. + - [] Leaving player's resources go to player +## Finishing Touches + - [] Sounds + - [] Graphics Redo + - [] Fancy webpage decorations + +## Maybe + - [] Chat diff --git a/index.js b/index.js index 7ce20ab..ab4e15e 100644 --- a/index.js +++ b/index.js @@ -1,121 +1,166 @@ -const worldgen = require("./worldgen.js") -const util = require("./util.js") -const log = require("./log.js") -const gridSize = [18, 18]; -const perlinScale = 3; - -var express = require('express'); - -process.title = "Server" -setInterval(function(){ updateInfo()},5000) - -function updateInfo() { - const players = game.players; - - log.setInfo(players) -} - -class Player { - constructor(id, name, color) { - this.id = id; - this.name = name; - this.color = color; - } -} - -class Game { - constructor() { - this.players = [{id: "adfhad", name: "bobbert"}]; - this.world = worldgen.generateWorld(gridSize, perlinScale); - } - - addPlayer(id, name) { - if (this.getAllNames().includes(name)) return false - var color = "blue" - const player = new Player(id, name, color); - this.players.push(player); - return true - } - - removePlayer(id) { - this.players = this.players.filter(obj => obj.id != id); - log.log("removed player - " + id) - } - - getPlayerByID(id) { - const player = this.players.filter(obj => obj.id == id)[0] - return player - } - - getAllIDs() { - let ids = [] - for (i = 0; i < this.players.length; i++) { - ids.push(this.players[i].id) - } - return ids - } - getAllNames() { - let names = [] - for (i = 0; i < this.players.length; i++) { - names.push(this.players[i].name) - } - return names - } -} -var game = new Game(); - - -var app = express() //Static resources server -app.use(express.static(__dirname + '/www/'));var server = app.listen(8082, function () { - var port = server.address().port; - log.log(`Server running at port ${port}`, "bright"); -}); - -var io = require('socket.io')(server);/* Connection events */ -io.on('connection', function(client) { - - client.illegalAction = function(action) { - client.emit('illegalAction', action) - } - - log.log('User connected', 'FgGreen'); - - client.on('disconnect', function(){ - log.log(client.id + ' disconnected.', 'FgCyan') - game.removePlayer(client.id) - client.broadcast.emit('playerList', game.players) - }) - - client.on('joinGame', function(data){ - if (game.addPlayer(client.id, data.name) == false) return client.illegalAction(20) - sendMap(client) - log.log(`${client.id} joined the game as ${data.name} requesting to join room: ${data.room}`, 'FgMagenta'); - client.broadcast.emit('playerList', game.players) - client.emit('playerList', game.players) - }) - client.on('leaveGame', function(tank){ - log.log(client.id + ' disconnected.') - game.removePlayer(client.id) - client.broadcast.emit('playerList', game.players) - }) - - - client.on('clickCanvas', function(data){ - if (!game.getAllIDs().includes(client.id)) return client.illegalAction(1) - const xu = data.tilePosition[0] - const yu = data.tilePosition[1] - game.world[xu][yu].structure = data.structure - game.world[xu][yu].owner = game.getPlayerByID(client.id).color; - // log.log(world[xu][yu].owner = game.getPlayerbyID(client.id)) - - client.broadcast.emit('sync',{world: game.world}) - client.emit('sync',{world: game.world}) - }) - - - }); - - function sendMap(client) { - client.broadcast.emit('sync',{world: game.world.map}) - client.emit('sync',{world: game.world.map}) - } +const worldgen = require("./worldgen.js") +const util = require("./util.js") +const log = require("./log.js") +const gridSize = [18, 18]; +const perlinScale = 3; +var express = require('express'); +log.setMode(0) +process.title = "Server" +setInterval(function(){ updateInfo()},5000) + +function updateInfo() { + log.setInfo(server.games) +} + +class Player { + constructor(id, name, color) { + this.id = id; + this.name = name; + this.color = color; + } +} + +class Server { + constructor(){ + this.games = []; + } + getGameByName(name, create) { + const game = this.games.filter(obj => obj.name == name)[0] + if (game === undefined && create) { + this.addGame(name); + // Oh no.... This cant be good code. + return this.getGameByName(name); + } + return game + } + + addGame(name) { + const game = new Game(name); + this.games.push(game); + return game + } + removeGame(name) { + this.games = this.games.filter(obj => obj.name != name); + log.log("removed game - " + name) + } + + getAllIDs() { + let ids = [] + for (let i = 0; i < this.games.length; i++) { + for (let j = 0; j < this.games[i].players.length; j++) { + ids.push(this.games[i].players[j].id) + } + } + return ids + } + + joinClientToGame(room, nick, id, client) { + const game = this.getGameByName(room, true); + if (game.addPlayer(id, nick) == false) { + this.removeGame(game) + return client.illegalAction(20) + } + client.join(game.name) + client.game = game; + return true + } + + +} + +class Game { + constructor(name) { + this.name = name; + this.players = []; + this.world = worldgen.generateWorld(gridSize, perlinScale); + } + + addPlayer(id, name) { + if (this.getAllNames().includes(name)) return false + var color = "blue" + const player = new Player(id, name, color); + this.players.push(player); + return true + } + + removePlayer(id) { + this.players = this.players.filter(obj => obj.id != id); + log.log("removed player - " + id) + if (this.players.length < 1) { + server.removeGame(this.name); + } + } + + getPlayerByID(id) { + const player = this.players.filter(obj => obj.id == id)[0] + return player + } + + getAllIDs() { + let ids = [] + for (i = 0; i < this.players.length; i++) { + ids.push(this.players[i].id) + } + return ids + } + getAllNames() { + let names = [] + for (i = 0; i < this.players.length; i++) { + names.push(this.players[i].name) + } + return names + } +} +var server = new Server(); + + +var app = express() //Static resources server +app.use(express.static(__dirname + '/www/')); +var webServer = app.listen(8082, function () { + var port = webServer.address().port; + log.log(`Server running at port ${port}`, "bright"); +}); + +var io = require('socket.io')(webServer);/* Connection events */ +io.on('connection', function(client) { + + client.illegalAction = function(action) { + client.emit('illegalAction', action) + } + + log.log('User connected', 'FgGreen'); + + client.on('disconnect', function(){ + if (!server.getAllIDs().includes(client.id)) return client.illegalAction(22) + log.log(client.id + ' disconnected.', 'FgCyan') + client.game.removePlayer(client.id) + }) + + client.on('joinGame', function(data){ + if(!server.joinClientToGame(data.room, data.name, client.id, client)) return + io.to(client.game.name).emit('sync',{world: client.game.world}) + log.log(`${client.id} joined the game as ${data.name} requesting to join room: ${data.room}`, 'FgMagenta'); + client.emit('inGame', true) + }) + client.on('leaveGame', function(tank){ + log.log(celient.id + ' disconnected.') + client.game.removePlayer(client.id) + io.to(client.game.name).emit('playerList', client.game.players) + }) + + + client.on('clickCanvas', function(data){ + if (!server.getAllIDs().includes(client.id)) return client.illegalAction(1) + const room = client.game.name + const xu = util.clamp(data.tilePosition[0], 0, gridSize[0]) + const yu = util.clamp(data.tilePosition[1], 0, gridSize[1]) + if (!Number.isInteger(xu) || !Number.isInteger(yu)) return client.illegalAction(23) + + client.game.world[xu][yu].structure = data.structure + client.game.world[xu][yu].owner = client.game.getPlayerByID(client.id).color; + io.to(client.game.name).emit('sync',{world: client.game.world}) + // client.emit('sync',{world: client.game.world}) + }) + + + }); diff --git a/log.js b/log.js index 5844f22..87c536b 100644 --- a/log.js +++ b/log.js @@ -1,101 +1,123 @@ -const os = require("os") - -var logs = [] -var info = [[],[]] - -function updateLog() { -console.clear() -const columns = process.stdout.columns; -const rows = process.stdout.rows; -const vertSplit = Math.round(rows/4) - -for (var i = 0; i < vertSplit; i++) { - process.stdout.cursorTo(Math.round(columns/2),i); - process.stdout.clearLine(); - process.stdout.write(`|`) -} -for (var i = 0; i < columns; i++) { - process.stdout.cursorTo(i, vertSplit) - process.stdout.write(`=`) -} - -process.stdout.cursorTo(0,0) -process.stdout.write("Players:") -const players = info[0] -for (var i = 0; i < players.length; i++) { -process.stdout.cursorTo(0,i+1) -process.stdout.write(`Name: \x1b[1m${players[i].name}\x1b[0m -\x1b[1m ID:${players[i].id}\x1b[0m`) -} -for (var i = 0; i < logs.length; i++ ) { - process.stdout.cursorTo(0,vertSplit+1+i) - process.stdout.write(`${logs[i]}${os.EOL}` ) -} - -} -function log(string, color) { - if (string == undefined) return; - var prefix = ''; - switch (color) { - case "reset": - prefix = "\x1b[0m" - break; - case "bright": - prefix = "\x1b[1m" - break; - case "dim": - prefix = "\x1b[2m" - break; - case "underscore": - prefix = "\x1b[4m" - break; - case "reverse": - prefix = "\x1b[7m" - break; - case "FgBlack": - prefix = "\x1b[30m" - break; - case "FgRed": - prefix = "\x1b[31m" - break; - case "FgGreen": - prefix = "\x1b[32m" - break; - case "FgYellow": - prefix = "\x1b[33m" - break; - case "FgBlue": - prefix = "\x1b[34m" - break; - case "FgMagenta": - prefix = "\x1b[35m" - break; - case "FgCyan": - prefix = "\x1b[36m" - break; - case "FgWhite": - prefix = "\x1b[37m" - break; - } - - // BgBlack = "\x1b[40m" - // BgRed = "\x1b[41m" - // BgGreen = "\x1b[42m" - // BgYellow = "\x1b[43m" - // BgBlue = "\x1b[44m" - // BgMagenta = "\x1b[45m" - // BgCyan = "\x1b[46m" - // BgWhite = "\x1b[47m" - const newString = prefix + string + "\x1b[0m" -logs.push(newString) -updateLog(); -} - -function setInfo (players){ -if (players != undefined) { - info[0] = players; - updateLog() -} - -} - -module.exports = {log, updateLog, setInfo} +const os = require("os") +var mode = 0 +var logs = [] +var info = [[],[]] + +function setMode(type) { + mode = type +} + +function updateLog() { +if (mode) return +let templogs = logs; + +console.clear() +const columns = process.stdout.columns; +const rows = process.stdout.rows; +const vertSplit = Math.round(rows/4) + +for (var i = 0; i < vertSplit; i++) { + process.stdout.cursorTo(Math.round(columns/2),i); + process.stdout.clearLine(); + process.stdout.write(`|`) +} +for (var i = 0; i < columns; i++) { + process.stdout.cursorTo(i, vertSplit) + process.stdout.write(`=`) +} + +process.stdout.cursorTo(0,0) +process.stdout.write("Players:") +const games = info[0] +var pointer = 0 +for (i = 0; i < games.length; i++) { + process.stdout.cursorTo(0,pointer+1) + + process.stdout.write(`\x1b[46mGameName: \x1b[1m${games[i].name}\x1b[0m`) + const players = games[i].players; + for (var j = 0; j < players.length; j++) { + process.stdout.cursorTo(0,pointer+2) + process.stdout.write(`--Name: \x1b[1m${players[j].name}\x1b[0m -\x1b[1m ID:${players[j].id}\x1b[0m`) + pointer++; + } + pointer++; +} +if (templogs.length > Math.round(3*rows/4)-3) { +templogs.splice(0, logs.length-Math.round(3*rows/4)+2); +} +for (var i = 0; i < templogs.length; i++ ) { + process.stdout.cursorTo(0,vertSplit+1+i) + process.stdout.write(`${templogs[i]}${os.EOL}` ) +} + +} +function log(string, color) { + if (mode) return console.log(string) + if (string == undefined) return; + var prefix = ''; + switch (color) { + case "reset": + prefix = "\x1b[0m" + break; + case "bright": + prefix = "\x1b[1m" + break; + case "dim": + prefix = "\x1b[2m" + break; + case "underscore": + prefix = "\x1b[4m" + break; + case "reverse": + prefix = "\x1b[7m" + break; + case "FgBlack": + prefix = "\x1b[30m" + break; + case "FgRed": + prefix = "\x1b[31m" + break; + case "FgGreen": + prefix = "\x1b[32m" + break; + case "FgYellow": + prefix = "\x1b[33m" + break; + case "FgBlue": + prefix = "\x1b[34m" + break; + case "FgMagenta": + prefix = "\x1b[35m" + break; + case "FgCyan": + prefix = "\x1b[36m" + break; + case "FgWhite": + prefix = "\x1b[37m" + break; + } + + // BgBlack = "\x1b[40m" + // BgRed = "\x1b[41m" + // BgGreen = "\x1b[42m" + // BgYellow = "\x1b[43m" + // BgBlue = "\x1b[44m" + // BgMagenta = "\x1b[45m" + // BgCyan = "\x1b[46m" + // BgWhite = "\x1b[47m" + const newString = prefix + string + "\x1b[0m" +logs.push(newString) + +updateLog(); +} + +function setInfo (players){ + if (mode) return false +if (players != undefined) { + info[0] = players; + updateLog() +} + +} + +module.exports = {log, updateLog, setInfo, setMode} diff --git a/perlin.js b/perlin.js index 9c5f948..a3d5dd4 100644 --- a/perlin.js +++ b/perlin.js @@ -1,311 +1,311 @@ -/* - * A speed-improved perlin and simplex noise algorithms for 2D. - * - * Based on example code by Stefan Gustavson (stegu@itn.liu.se). - * Optimisations by Peter Eastman (peastman@drizzle.stanford.edu). - * Better rank ordering method by Stefan Gustavson in 2012. - * Converted to Javascript by Joseph Gentle. - * Converted to NPM Package by Jacob Schneider - * - * Version 2012-03-09 - * - * This code was placed in the public domain by its original author, - * Stefan Gustavson. You may use it as you see fit, but - * attribution is appreciated. - * - */ - -module.exports = (function(global){ - var functions = global.noise = {}; - - function Grad(x, y, z) { - this.x = x; this.y = y; this.z = z; - } - - Grad.prototype.dot2 = function(x, y) { - return this.x*x + this.y*y; - }; - - Grad.prototype.dot3 = function(x, y, z) { - return this.x*x + this.y*y + this.z*z; - }; - - var grad3 = [new Grad(1,1,0),new Grad(-1,1,0),new Grad(1,-1,0),new Grad(-1,-1,0), - new Grad(1,0,1),new Grad(-1,0,1),new Grad(1,0,-1),new Grad(-1,0,-1), - new Grad(0,1,1),new Grad(0,-1,1),new Grad(0,1,-1),new Grad(0,-1,-1)]; - - var p = [151,160,137,91,90,15, - 131,13,201,95,96,53,194,233,7,225,140,36,103,30,69,142,8,99,37,240,21,10,23, - 190, 6,148,247,120,234,75,0,26,197,62,94,252,219,203,117,35,11,32,57,177,33, - 88,237,149,56,87,174,20,125,136,171,168, 68,175,74,165,71,134,139,48,27,166, - 77,146,158,231,83,111,229,122,60,211,133,230,220,105,92,41,55,46,245,40,244, - 102,143,54, 65,25,63,161, 1,216,80,73,209,76,132,187,208, 89,18,169,200,196, - 135,130,116,188,159,86,164,100,109,198,173,186, 3,64,52,217,226,250,124,123, - 5,202,38,147,118,126,255,82,85,212,207,206,59,227,47,16,58,17,182,189,28,42, - 223,183,170,213,119,248,152, 2,44,154,163, 70,221,153,101,155,167, 43,172,9, - 129,22,39,253, 19,98,108,110,79,113,224,232,178,185, 112,104,218,246,97,228, - 251,34,242,193,238,210,144,12,191,179,162,241, 81,51,145,235,249,14,239,107, - 49,192,214, 31,181,199,106,157,184, 84,204,176,115,121,50,45,127, 4,150,254, - 138,236,205,93,222,114,67,29,24,72,243,141,128,195,78,66,215,61,156,180]; - // To remove the need for index wrapping, double the permutation table length - var perm = new Array(512); - var gradP = new Array(512); - - // This isn't a very good seeding function, but it works ok. It supports 2^16 - // different seed values. Write something better if you need more seeds. - functions.seed = function(seed) { - if(seed > 0 && seed < 1) { - // Scale the seed out - seed *= 65536; - } - - seed = Math.floor(seed); - if(seed < 256) { - seed |= seed << 8; - } - - for(var i = 0; i < 256; i++) { - var v; - if (i & 1) { - v = p[i] ^ (seed & 255); - } else { - v = p[i] ^ ((seed>>8) & 255); - } - - perm[i] = perm[i + 256] = v; - gradP[i] = gradP[i + 256] = grad3[v % 12]; - } - }; - - functions.seed(0); - - /* - for(var i=0; i<256; i++) { - perm[i] = perm[i + 256] = p[i]; - gradP[i] = gradP[i + 256] = grad3[perm[i] % 12]; - }*/ - - // Skewing and unskewing factors for 2, 3, and 4 dimensions - var F2 = 0.5*(Math.sqrt(3)-1); - var G2 = (3-Math.sqrt(3))/6; - - var F3 = 1/3; - var G3 = 1/6; - - // 2D simplex noise - functions.simplex2 = function(xin, yin) { - var n0, n1, n2; // Noise contributions from the three corners - // Skew the input space to determine which simplex cell we're in - var s = (xin+yin)*F2; // Hairy factor for 2D - var i = Math.floor(xin+s); - var j = Math.floor(yin+s); - var t = (i+j)*G2; - var x0 = xin-i+t; // The x,y distances from the cell origin, unskewed. - var y0 = yin-j+t; - // For the 2D case, the simplex shape is an equilateral triangle. - // Determine which simplex we are in. - var i1, j1; // Offsets for second (middle) corner of simplex in (i,j) coords - if(x0>y0) { // lower triangle, XY order: (0,0)->(1,0)->(1,1) - i1=1; j1=0; - } else { // upper triangle, YX order: (0,0)->(0,1)->(1,1) - i1=0; j1=1; - } - // A step of (1,0) in (i,j) means a step of (1-c,-c) in (x,y), and - // a step of (0,1) in (i,j) means a step of (-c,1-c) in (x,y), where - // c = (3-sqrt(3))/6 - var x1 = x0 - i1 + G2; // Offsets for middle corner in (x,y) unskewed coords - var y1 = y0 - j1 + G2; - var x2 = x0 - 1 + 2 * G2; // Offsets for last corner in (x,y) unskewed coords - var y2 = y0 - 1 + 2 * G2; - // Work out the hashed gradient indices of the three simplex corners - i &= 255; - j &= 255; - var gi0 = gradP[i+perm[j]]; - var gi1 = gradP[i+i1+perm[j+j1]]; - var gi2 = gradP[i+1+perm[j+1]]; - // Calculate the contribution from the three corners - var t0 = 0.5 - x0*x0-y0*y0; - if(t0<0) { - n0 = 0; - } else { - t0 *= t0; - n0 = t0 * t0 * gi0.dot2(x0, y0); // (x,y) of grad3 used for 2D gradient - } - var t1 = 0.5 - x1*x1-y1*y1; - if(t1<0) { - n1 = 0; - } else { - t1 *= t1; - n1 = t1 * t1 * gi1.dot2(x1, y1); - } - var t2 = 0.5 - x2*x2-y2*y2; - if(t2<0) { - n2 = 0; - } else { - t2 *= t2; - n2 = t2 * t2 * gi2.dot2(x2, y2); - } - // Add contributions from each corner to get the final noise value. - // The result is scaled to return values in the interval [-1,1]. - return 70 * (n0 + n1 + n2); - }; - - // 3D simplex noise - functions.simplex3 = function(xin, yin, zin) { - var n0, n1, n2, n3; // Noise contributions from the four corners - - // Skew the input space to determine which simplex cell we're in - var s = (xin+yin+zin)*F3; // Hairy factor for 2D - var i = Math.floor(xin+s); - var j = Math.floor(yin+s); - var k = Math.floor(zin+s); - - var t = (i+j+k)*G3; - var x0 = xin-i+t; // The x,y distances from the cell origin, unskewed. - var y0 = yin-j+t; - var z0 = zin-k+t; - - // For the 3D case, the simplex shape is a slightly irregular tetrahedron. - // Determine which simplex we are in. - var i1, j1, k1; // Offsets for second corner of simplex in (i,j,k) coords - var i2, j2, k2; // Offsets for third corner of simplex in (i,j,k) coords - if(x0 >= y0) { - if(y0 >= z0) { i1=1; j1=0; k1=0; i2=1; j2=1; k2=0; } - else if(x0 >= z0) { i1=1; j1=0; k1=0; i2=1; j2=0; k2=1; } - else { i1=0; j1=0; k1=1; i2=1; j2=0; k2=1; } - } else { - if(y0 < z0) { i1=0; j1=0; k1=1; i2=0; j2=1; k2=1; } - else if(x0 < z0) { i1=0; j1=1; k1=0; i2=0; j2=1; k2=1; } - else { i1=0; j1=1; k1=0; i2=1; j2=1; k2=0; } - } - // A step of (1,0,0) in (i,j,k) means a step of (1-c,-c,-c) in (x,y,z), - // a step of (0,1,0) in (i,j,k) means a step of (-c,1-c,-c) in (x,y,z), and - // a step of (0,0,1) in (i,j,k) means a step of (-c,-c,1-c) in (x,y,z), where - // c = 1/6. - var x1 = x0 - i1 + G3; // Offsets for second corner - var y1 = y0 - j1 + G3; - var z1 = z0 - k1 + G3; - - var x2 = x0 - i2 + 2 * G3; // Offsets for third corner - var y2 = y0 - j2 + 2 * G3; - var z2 = z0 - k2 + 2 * G3; - - var x3 = x0 - 1 + 3 * G3; // Offsets for fourth corner - var y3 = y0 - 1 + 3 * G3; - var z3 = z0 - 1 + 3 * G3; - - // Work out the hashed gradient indices of the four simplex corners - i &= 255; - j &= 255; - k &= 255; - var gi0 = gradP[i+ perm[j+ perm[k ]]]; - var gi1 = gradP[i+i1+perm[j+j1+perm[k+k1]]]; - var gi2 = gradP[i+i2+perm[j+j2+perm[k+k2]]]; - var gi3 = gradP[i+ 1+perm[j+ 1+perm[k+ 1]]]; - - // Calculate the contribution from the four corners - var t0 = 0.6 - x0*x0 - y0*y0 - z0*z0; - if(t0<0) { - n0 = 0; - } else { - t0 *= t0; - n0 = t0 * t0 * gi0.dot3(x0, y0, z0); // (x,y) of grad3 used for 2D gradient - } - var t1 = 0.6 - x1*x1 - y1*y1 - z1*z1; - if(t1<0) { - n1 = 0; - } else { - t1 *= t1; - n1 = t1 * t1 * gi1.dot3(x1, y1, z1); - } - var t2 = 0.6 - x2*x2 - y2*y2 - z2*z2; - if(t2<0) { - n2 = 0; - } else { - t2 *= t2; - n2 = t2 * t2 * gi2.dot3(x2, y2, z2); - } - var t3 = 0.6 - x3*x3 - y3*y3 - z3*z3; - if(t3<0) { - n3 = 0; - } else { - t3 *= t3; - n3 = t3 * t3 * gi3.dot3(x3, y3, z3); - } - // Add contributions from each corner to get the final noise value. - // The result is scaled to return values in the interval [-1,1]. - return 32 * (n0 + n1 + n2 + n3); - - }; - - // ##### Perlin noise stuff - - function fade(t) { - return t*t*t*(t*(t*6-15)+10); - } - - function lerp(a, b, t) { - return (1-t)*a + t*b; - } - - // 2D Perlin Noise - functions.perlin2 = function(x, y) { - // Find unit grid cell containing point - var X = Math.floor(x), Y = Math.floor(y); - // Get relative xy coordinates of point within that cell - x = x - X; y = y - Y; - // Wrap the integer cells at 255 (smaller integer period can be introduced here) - X = X & 255; Y = Y & 255; - - // Calculate noise contributions from each of the four corners - var n00 = gradP[X+perm[Y]].dot2(x, y); - var n01 = gradP[X+perm[Y+1]].dot2(x, y-1); - var n10 = gradP[X+1+perm[Y]].dot2(x-1, y); - var n11 = gradP[X+1+perm[Y+1]].dot2(x-1, y-1); - - // Compute the fade curve value for x - var u = fade(x); - - // Interpolate the four results - return lerp( - lerp(n00, n10, u), - lerp(n01, n11, u), - fade(y)); - }; - - // 3D Perlin Noise - functions.perlin3 = function(x, y, z) { - // Find unit grid cell containing point - var X = Math.floor(x), Y = Math.floor(y), Z = Math.floor(z); - // Get relative xyz coordinates of point within that cell - x = x - X; y = y - Y; z = z - Z; - // Wrap the integer cells at 255 (smaller integer period can be introduced here) - X = X & 255; Y = Y & 255; Z = Z & 255; - - // Calculate noise contributions from each of the eight corners - var n000 = gradP[X+ perm[Y+ perm[Z ]]].dot3(x, y, z); - var n001 = gradP[X+ perm[Y+ perm[Z+1]]].dot3(x, y, z-1); - var n010 = gradP[X+ perm[Y+1+perm[Z ]]].dot3(x, y-1, z); - var n011 = gradP[X+ perm[Y+1+perm[Z+1]]].dot3(x, y-1, z-1); - var n100 = gradP[X+1+perm[Y+ perm[Z ]]].dot3(x-1, y, z); - var n101 = gradP[X+1+perm[Y+ perm[Z+1]]].dot3(x-1, y, z-1); - var n110 = gradP[X+1+perm[Y+1+perm[Z ]]].dot3(x-1, y-1, z); - var n111 = gradP[X+1+perm[Y+1+perm[Z+1]]].dot3(x-1, y-1, z-1); - - // Compute the fade curve value for x, y, z - var u = fade(x); - var v = fade(y); - var w = fade(z); - - // Interpolate - return lerp( - lerp( - lerp(n000, n100, u), - lerp(n001, n101, u), w), - lerp( - lerp(n010, n110, u), - lerp(n011, n111, u), w), - v); - }; - return functions; -})(this); +/* + * A speed-improved perlin and simplex noise algorithms for 2D. + * + * Based on example code by Stefan Gustavson (stegu@itn.liu.se). + * Optimisations by Peter Eastman (peastman@drizzle.stanford.edu). + * Better rank ordering method by Stefan Gustavson in 2012. + * Converted to Javascript by Joseph Gentle. + * Converted to NPM Package by Jacob Schneider + * + * Version 2012-03-09 + * + * This code was placed in the public domain by its original author, + * Stefan Gustavson. You may use it as you see fit, but + * attribution is appreciated. + * + */ + +module.exports = (function(global){ + var functions = global.noise = {}; + + function Grad(x, y, z) { + this.x = x; this.y = y; this.z = z; + } + + Grad.prototype.dot2 = function(x, y) { + return this.x*x + this.y*y; + }; + + Grad.prototype.dot3 = function(x, y, z) { + return this.x*x + this.y*y + this.z*z; + }; + + var grad3 = [new Grad(1,1,0),new Grad(-1,1,0),new Grad(1,-1,0),new Grad(-1,-1,0), + new Grad(1,0,1),new Grad(-1,0,1),new Grad(1,0,-1),new Grad(-1,0,-1), + new Grad(0,1,1),new Grad(0,-1,1),new Grad(0,1,-1),new Grad(0,-1,-1)]; + + var p = [151,160,137,91,90,15, + 131,13,201,95,96,53,194,233,7,225,140,36,103,30,69,142,8,99,37,240,21,10,23, + 190, 6,148,247,120,234,75,0,26,197,62,94,252,219,203,117,35,11,32,57,177,33, + 88,237,149,56,87,174,20,125,136,171,168, 68,175,74,165,71,134,139,48,27,166, + 77,146,158,231,83,111,229,122,60,211,133,230,220,105,92,41,55,46,245,40,244, + 102,143,54, 65,25,63,161, 1,216,80,73,209,76,132,187,208, 89,18,169,200,196, + 135,130,116,188,159,86,164,100,109,198,173,186, 3,64,52,217,226,250,124,123, + 5,202,38,147,118,126,255,82,85,212,207,206,59,227,47,16,58,17,182,189,28,42, + 223,183,170,213,119,248,152, 2,44,154,163, 70,221,153,101,155,167, 43,172,9, + 129,22,39,253, 19,98,108,110,79,113,224,232,178,185, 112,104,218,246,97,228, + 251,34,242,193,238,210,144,12,191,179,162,241, 81,51,145,235,249,14,239,107, + 49,192,214, 31,181,199,106,157,184, 84,204,176,115,121,50,45,127, 4,150,254, + 138,236,205,93,222,114,67,29,24,72,243,141,128,195,78,66,215,61,156,180]; + // To remove the need for index wrapping, double the permutation table length + var perm = new Array(512); + var gradP = new Array(512); + + // This isn't a very good seeding function, but it works ok. It supports 2^16 + // different seed values. Write something better if you need more seeds. + functions.seed = function(seed) { + if(seed > 0 && seed < 1) { + // Scale the seed out + seed *= 65536; + } + + seed = Math.floor(seed); + if(seed < 256) { + seed |= seed << 8; + } + + for(var i = 0; i < 256; i++) { + var v; + if (i & 1) { + v = p[i] ^ (seed & 255); + } else { + v = p[i] ^ ((seed>>8) & 255); + } + + perm[i] = perm[i + 256] = v; + gradP[i] = gradP[i + 256] = grad3[v % 12]; + } + }; + + functions.seed(0); + + /* + for(var i=0; i<256; i++) { + perm[i] = perm[i + 256] = p[i]; + gradP[i] = gradP[i + 256] = grad3[perm[i] % 12]; + }*/ + + // Skewing and unskewing factors for 2, 3, and 4 dimensions + var F2 = 0.5*(Math.sqrt(3)-1); + var G2 = (3-Math.sqrt(3))/6; + + var F3 = 1/3; + var G3 = 1/6; + + // 2D simplex noise + functions.simplex2 = function(xin, yin) { + var n0, n1, n2; // Noise contributions from the three corners + // Skew the input space to determine which simplex cell we're in + var s = (xin+yin)*F2; // Hairy factor for 2D + var i = Math.floor(xin+s); + var j = Math.floor(yin+s); + var t = (i+j)*G2; + var x0 = xin-i+t; // The x,y distances from the cell origin, unskewed. + var y0 = yin-j+t; + // For the 2D case, the simplex shape is an equilateral triangle. + // Determine which simplex we are in. + var i1, j1; // Offsets for second (middle) corner of simplex in (i,j) coords + if(x0>y0) { // lower triangle, XY order: (0,0)->(1,0)->(1,1) + i1=1; j1=0; + } else { // upper triangle, YX order: (0,0)->(0,1)->(1,1) + i1=0; j1=1; + } + // A step of (1,0) in (i,j) means a step of (1-c,-c) in (x,y), and + // a step of (0,1) in (i,j) means a step of (-c,1-c) in (x,y), where + // c = (3-sqrt(3))/6 + var x1 = x0 - i1 + G2; // Offsets for middle corner in (x,y) unskewed coords + var y1 = y0 - j1 + G2; + var x2 = x0 - 1 + 2 * G2; // Offsets for last corner in (x,y) unskewed coords + var y2 = y0 - 1 + 2 * G2; + // Work out the hashed gradient indices of the three simplex corners + i &= 255; + j &= 255; + var gi0 = gradP[i+perm[j]]; + var gi1 = gradP[i+i1+perm[j+j1]]; + var gi2 = gradP[i+1+perm[j+1]]; + // Calculate the contribution from the three corners + var t0 = 0.5 - x0*x0-y0*y0; + if(t0<0) { + n0 = 0; + } else { + t0 *= t0; + n0 = t0 * t0 * gi0.dot2(x0, y0); // (x,y) of grad3 used for 2D gradient + } + var t1 = 0.5 - x1*x1-y1*y1; + if(t1<0) { + n1 = 0; + } else { + t1 *= t1; + n1 = t1 * t1 * gi1.dot2(x1, y1); + } + var t2 = 0.5 - x2*x2-y2*y2; + if(t2<0) { + n2 = 0; + } else { + t2 *= t2; + n2 = t2 * t2 * gi2.dot2(x2, y2); + } + // Add contributions from each corner to get the final noise value. + // The result is scaled to return values in the interval [-1,1]. + return 70 * (n0 + n1 + n2); + }; + + // 3D simplex noise + functions.simplex3 = function(xin, yin, zin) { + var n0, n1, n2, n3; // Noise contributions from the four corners + + // Skew the input space to determine which simplex cell we're in + var s = (xin+yin+zin)*F3; // Hairy factor for 2D + var i = Math.floor(xin+s); + var j = Math.floor(yin+s); + var k = Math.floor(zin+s); + + var t = (i+j+k)*G3; + var x0 = xin-i+t; // The x,y distances from the cell origin, unskewed. + var y0 = yin-j+t; + var z0 = zin-k+t; + + // For the 3D case, the simplex shape is a slightly irregular tetrahedron. + // Determine which simplex we are in. + var i1, j1, k1; // Offsets for second corner of simplex in (i,j,k) coords + var i2, j2, k2; // Offsets for third corner of simplex in (i,j,k) coords + if(x0 >= y0) { + if(y0 >= z0) { i1=1; j1=0; k1=0; i2=1; j2=1; k2=0; } + else if(x0 >= z0) { i1=1; j1=0; k1=0; i2=1; j2=0; k2=1; } + else { i1=0; j1=0; k1=1; i2=1; j2=0; k2=1; } + } else { + if(y0 < z0) { i1=0; j1=0; k1=1; i2=0; j2=1; k2=1; } + else if(x0 < z0) { i1=0; j1=1; k1=0; i2=0; j2=1; k2=1; } + else { i1=0; j1=1; k1=0; i2=1; j2=1; k2=0; } + } + // A step of (1,0,0) in (i,j,k) means a step of (1-c,-c,-c) in (x,y,z), + // a step of (0,1,0) in (i,j,k) means a step of (-c,1-c,-c) in (x,y,z), and + // a step of (0,0,1) in (i,j,k) means a step of (-c,-c,1-c) in (x,y,z), where + // c = 1/6. + var x1 = x0 - i1 + G3; // Offsets for second corner + var y1 = y0 - j1 + G3; + var z1 = z0 - k1 + G3; + + var x2 = x0 - i2 + 2 * G3; // Offsets for third corner + var y2 = y0 - j2 + 2 * G3; + var z2 = z0 - k2 + 2 * G3; + + var x3 = x0 - 1 + 3 * G3; // Offsets for fourth corner + var y3 = y0 - 1 + 3 * G3; + var z3 = z0 - 1 + 3 * G3; + + // Work out the hashed gradient indices of the four simplex corners + i &= 255; + j &= 255; + k &= 255; + var gi0 = gradP[i+ perm[j+ perm[k ]]]; + var gi1 = gradP[i+i1+perm[j+j1+perm[k+k1]]]; + var gi2 = gradP[i+i2+perm[j+j2+perm[k+k2]]]; + var gi3 = gradP[i+ 1+perm[j+ 1+perm[k+ 1]]]; + + // Calculate the contribution from the four corners + var t0 = 0.6 - x0*x0 - y0*y0 - z0*z0; + if(t0<0) { + n0 = 0; + } else { + t0 *= t0; + n0 = t0 * t0 * gi0.dot3(x0, y0, z0); // (x,y) of grad3 used for 2D gradient + } + var t1 = 0.6 - x1*x1 - y1*y1 - z1*z1; + if(t1<0) { + n1 = 0; + } else { + t1 *= t1; + n1 = t1 * t1 * gi1.dot3(x1, y1, z1); + } + var t2 = 0.6 - x2*x2 - y2*y2 - z2*z2; + if(t2<0) { + n2 = 0; + } else { + t2 *= t2; + n2 = t2 * t2 * gi2.dot3(x2, y2, z2); + } + var t3 = 0.6 - x3*x3 - y3*y3 - z3*z3; + if(t3<0) { + n3 = 0; + } else { + t3 *= t3; + n3 = t3 * t3 * gi3.dot3(x3, y3, z3); + } + // Add contributions from each corner to get the final noise value. + // The result is scaled to return values in the interval [-1,1]. + return 32 * (n0 + n1 + n2 + n3); + + }; + + // ##### Perlin noise stuff + + function fade(t) { + return t*t*t*(t*(t*6-15)+10); + } + + function lerp(a, b, t) { + return (1-t)*a + t*b; + } + + // 2D Perlin Noise + functions.perlin2 = function(x, y) { + // Find unit grid cell containing point + var X = Math.floor(x), Y = Math.floor(y); + // Get relative xy coordinates of point within that cell + x = x - X; y = y - Y; + // Wrap the integer cells at 255 (smaller integer period can be introduced here) + X = X & 255; Y = Y & 255; + + // Calculate noise contributions from each of the four corners + var n00 = gradP[X+perm[Y]].dot2(x, y); + var n01 = gradP[X+perm[Y+1]].dot2(x, y-1); + var n10 = gradP[X+1+perm[Y]].dot2(x-1, y); + var n11 = gradP[X+1+perm[Y+1]].dot2(x-1, y-1); + + // Compute the fade curve value for x + var u = fade(x); + + // Interpolate the four results + return lerp( + lerp(n00, n10, u), + lerp(n01, n11, u), + fade(y)); + }; + + // 3D Perlin Noise + functions.perlin3 = function(x, y, z) { + // Find unit grid cell containing point + var X = Math.floor(x), Y = Math.floor(y), Z = Math.floor(z); + // Get relative xyz coordinates of point within that cell + x = x - X; y = y - Y; z = z - Z; + // Wrap the integer cells at 255 (smaller integer period can be introduced here) + X = X & 255; Y = Y & 255; Z = Z & 255; + + // Calculate noise contributions from each of the eight corners + var n000 = gradP[X+ perm[Y+ perm[Z ]]].dot3(x, y, z); + var n001 = gradP[X+ perm[Y+ perm[Z+1]]].dot3(x, y, z-1); + var n010 = gradP[X+ perm[Y+1+perm[Z ]]].dot3(x, y-1, z); + var n011 = gradP[X+ perm[Y+1+perm[Z+1]]].dot3(x, y-1, z-1); + var n100 = gradP[X+1+perm[Y+ perm[Z ]]].dot3(x-1, y, z); + var n101 = gradP[X+1+perm[Y+ perm[Z+1]]].dot3(x-1, y, z-1); + var n110 = gradP[X+1+perm[Y+1+perm[Z ]]].dot3(x-1, y-1, z); + var n111 = gradP[X+1+perm[Y+1+perm[Z+1]]].dot3(x-1, y-1, z-1); + + // Compute the fade curve value for x, y, z + var u = fade(x); + var v = fade(y); + var w = fade(z); + + // Interpolate + return lerp( + lerp( + lerp(n000, n100, u), + lerp(n001, n101, u), w), + lerp( + lerp(n010, n110, u), + lerp(n011, n111, u), w), + v); + }; + return functions; +})(this); diff --git a/tileinfo.js b/tileinfo.js index d59a2fd..31367c8 100644 --- a/tileinfo.js +++ b/tileinfo.js @@ -1,18 +1,18 @@ -const tileTypes = -[ -{name: "Grass", textureID: 0, buildPrice: 20, capturePrice:10, capturePower: 10, captureTime: 2, sellPrice:5, recapturePrice: 15, recapturePower: 100, recaptureTime: 10}, -{name: "Hills", textureID: 1, buildPrice: 20, capturePrice:10, capturePower: 10, captureTime: 2, sellPrice:5, recapturePrice: 15, recapturePower: 100, recaptureTime: 10}, -{name: "Sea", textureID: 2, buildPrice: 20, capturePrice:10, capturePower: 10, captureTime: 2, sellPrice:5, recapturePrice: 15, recapturePower: 100, recaptureTime: 10} -]; - -const structureTypes = -[ -{name: "Air", textureID:null, claimable: true, buildable: false, destroyable: false, maxQuantity:null, buildPrice: null, sellPrice: null, buildableOn: null}, -{name: "Rock", textureID:4, claimable: false, buildable: false, destroyable: false, maxQuantity:null, buildPrice: null, sellPrice: null, buildableOn: [0,1]}, -{name: "Town", textureID:32, claimable: false, buildable: true, destroyable: true, maxQuantity:10, buildPrice: 10, sellPrice: 5, buildableOn: [0,2]}, -{name: "City", textureID:33, claimable: false, buildable: true, destroyable: true, maxQuantity:10, buildPrice: 20, sellPrice: 10, buildableOn: [0,2]}, -{name: "Capitol", textureID:34, claimable: false, buildable: true, destroyable: false, maxQuantity:1, buildPrice: 30, sellPrice: 20, buildableOn: [0,2]}, -] - - -module.exports = {tileTypes, structureTypes} +const tileTypes = +[ +{name: "Grass", textureID: 0, buildPrice: 20, capturePrice:10, capturePower: 10, captureTime: 2, sellPrice:5, recapturePrice: 15, recapturePower: 100, recaptureTime: 10}, +{name: "Hills", textureID: 1, buildPrice: 20, capturePrice:10, capturePower: 10, captureTime: 2, sellPrice:5, recapturePrice: 15, recapturePower: 100, recaptureTime: 10}, +{name: "Sea", textureID: 2, buildPrice: 20, capturePrice:10, capturePower: 10, captureTime: 2, sellPrice:5, recapturePrice: 15, recapturePower: 100, recaptureTime: 10} +]; + +const structureTypes = +[ +{name: "Air", textureID:null, claimable: true, buildable: false, destroyable: false, maxQuantity:null, buildPrice: null, sellPrice: null, buildableOn: null}, +{name: "Rock", textureID:4, claimable: false, buildable: false, destroyable: false, maxQuantity:null, buildPrice: null, sellPrice: null, buildableOn: [0,1]}, +{name: "Town", textureID:32, claimable: false, buildable: true, destroyable: true, maxQuantity:10, buildPrice: 10, sellPrice: 5, buildableOn: [0,2]}, +{name: "City", textureID:33, claimable: false, buildable: true, destroyable: true, maxQuantity:10, buildPrice: 20, sellPrice: 10, buildableOn: [0,2]}, +{name: "Capitol", textureID:34, claimable: false, buildable: true, destroyable: false, maxQuantity:1, buildPrice: 30, sellPrice: 20, buildableOn: [0,2]}, +] + + +module.exports = {tileTypes, structureTypes} diff --git a/tt.js b/tt.js index c23ce9a..b318a2a 100644 --- a/tt.js +++ b/tt.js @@ -1,10 +1,10 @@ - -let os = require('os'); -var i = 0; -var j = 0; -var jh = 0 - - -process.stdout.write('Hello World' + os.EOL); -console.log(Boolean(process.stdout.isTTY)) -process.title = "Server" + +let os = require('os'); +var i = 0; +var j = 0; +var jh = 0 + + +process.stdout.write('Hello World' + os.EOL); +console.log(Boolean(process.stdout.isTTY)) +process.title = "Server" diff --git a/util.js b/util.js index 102b476..284a94f 100644 --- a/util.js +++ b/util.js @@ -1,7 +1,7 @@ -function randomNumber(min, max) { - return Math.floor(Math.random() * (max - min) + min); -} -function clamp(number, min, max) { - return Math.max(min, Math.min(number, max)); -} -module.exports = {randomNumber, clamp} +function randomNumber(min, max) { + return Math.floor(Math.random() * (max - min) + min); +} +function clamp(number, min, max) { + return Math.max(min, Math.min(number, max)); +} +module.exports = {randomNumber, clamp} diff --git a/worldgen.js b/worldgen.js index 039e4c1..0a07073 100644 --- a/worldgen.js +++ b/worldgen.js @@ -1,40 +1,40 @@ -var noise = require('./perlin.js'); -const util = require("./util.js") - -function generateWorld(gridSize, perlinScale){ - let x, y = 0 - - let tempWorld = Array.from(Array(gridSize[0]), () => new Array(gridSize[1])); - for (x = 0; x < gridSize[0]; x++){ - for (y = 0; y < gridSize[1]; y++){ - tempWorld[x][y] = {type: 0, structure: 0, color: null, owner: null} - } - } - - noise.seed(Math.random()) - for(x = 0; x < gridSize[0]; x++){ - for(y = 0; y < gridSize[1]; y++){ - - var value = (noise.perlin2(x/perlinScale, y/perlinScale))*10; - if (value >= -3) { - tempWorld[x][y].type = 0 - } else if (value < -3) { - tempWorld[x][y].type = 1 - } - if (value > 1.4) { - tempWorld[x][y].type = 2 - } - - } - } - for (i = 0; i < gridSize[0]*gridSize[1]/15; i){ - x = util.randomNumber(0,gridSize[0]); - y = util.randomNumber(0,gridSize[1]); - if (tempWorld[x][y].type != 1) { - i++; - tempWorld[x][y].structure = util.randomNumber(1,4) - } -} - return tempWorld; -} -module.exports = { generateWorld }; +var noise = require('./perlin.js'); +const util = require("./util.js") + +function generateWorld(gridSize, perlinScale){ + let x, y = 0 + + let tempWorld = Array.from(Array(gridSize[0]), () => new Array(gridSize[1])); + for (x = 0; x < gridSize[0]; x++){ + for (y = 0; y < gridSize[1]; y++){ + tempWorld[x][y] = {type: 0, structure: 0, color: null, owner: null} + } + } + + noise.seed(Math.random()) + for(x = 0; x < gridSize[0]; x++){ + for(y = 0; y < gridSize[1]; y++){ + + var value = (noise.perlin2(x/perlinScale, y/perlinScale))*10; + if (value >= -3) { + tempWorld[x][y].type = 0 + } else if (value < -3) { + tempWorld[x][y].type = 1 + } + if (value > 1.4) { + tempWorld[x][y].type = 2 + } + + } + } + for (i = 0; i < gridSize[0]*gridSize[1]/15; i){ + x = util.randomNumber(0,gridSize[0]); + y = util.randomNumber(0,gridSize[1]); + if (tempWorld[x][y].type != 1) { + i++; + tempWorld[x][y].structure = util.randomNumber(1,4) + } +} + return tempWorld; +} +module.exports = { generateWorld }; diff --git a/www/index.html b/www/index.html index c14ce19..6c34303 100644 --- a/www/index.html +++ b/www/index.html @@ -1,35 +1,46 @@ - - -
-