let trees = [], birds = [], clouds = [], humans = [], ground = [], time = 12, // in hours cycleTime = 10, // in minutes worldWidth = 40000, viewPort = {x: Math.round(worldWidth / 2 - window.innerWidth / 2), y: 0, v: 20}, waveDispo = 0, cliffDispo = 25, STRAIGHT_GROUND = 0, SMALL_HILLS = 1, LARGE_HILL = 2, LAKE = 3, gameIsRunning = false; function setup(){ setFrameRate(120); createCanvas(window.innerWidth, window.innerHeight); background(160, 160, 255); noStroke(); $("#saveLink").hide(); $("#fileBrowser").hide(); $("#toolBarOpener").hide(); $("#infoWrapper").hide(); $("button").on("click", function(){this.blur();}); } function createWorld(){ $("#restoreWorld, #createWorld").hide(); fill(80); rect(width * 0.1, height * 0.5 - 25, width * 0.8, 50); fill(0, 255, 0); let x = 0, createProgress = 0, y = random(height * 0.7, height * 0.8), treeDist = 0, a = 0, c = 1, b = 0, biome, biomeX = 0, biomeDistance = 1, usedBiomes = [], biomes = [STRAIGHT_GROUND, SMALL_HILLS, LARGE_HILL, LAKE], isWooden; function create(){ //Updating progressbar createProgress++; rect(width * 0.1, height * 0.5 - 25, width * 0.8 * (createProgress / (worldWidth * 2)), 50); //Main creating if (ground.length < worldWidth){ //Ground let biomeRemainder = (x - biomeX) % biomeDistance; if (biomeRemainder == 0){ biome = random(biomes); if (usedBiomes.includes(biome)) biome = random(biomes); usedBiomes.push(biome); biomeX = x; isWooden = biome == LAKE ? false : random([true, false]); biomeDistance = round(random(1000, 1500)); a = 0, c = 1, b = 0; } switch (biome){ case STRAIGHT_GROUND: a = 0; if (y < height * 0.3) a = -1; if (y > height * 0.95) a = 1; //y = noise(x / 100, y / 100) * height; y += random(-0.25 - a, 0.25 - a); break; case SMALL_HILLS: if (biomeRemainder == round(biomeDistance / 12) || biomeRemainder == round(biomeDistance * 5 / 12) || biomeRemainder == round(biomeDistance * 0.75)) c = -1; if (biomeRemainder == round(biomeDistance * 0.25) || biomeRemainder == round(biomeDistance * 7 / 12) || biomeRemainder == round(biomeDistance * 11 / 12)) c = 1; if (y < height * 0.3){ c = -1; b = -0.5; } else if (y > height * 0.9){ c = 1; b = 0.5; } else b = 0; a -= random(0.005, 0.015) * c; y += random(2 * a - b); break; case LARGE_HILL: if (biomeRemainder == round(biomeDistance * 0.25)) c = -1; if (biomeRemainder == round(biomeDistance * 0.75)) c = 1; if (y < height * 0.3){ c = -1; b = -1; } else if (y > height * 0.9){ c = 1; b = 1; } else b = 0; a -= random(0.0025, 0.0075) * c; y += random(2 * a - b); break; } ground[x] = {y: y, biome: biome, isWooden: isWooden}; //Trees let treeH, treeW, valid; treeDist++; if (isWooden) valid = random(100) < 1 ? true : false; if (!isWooden) valid = random(1000) < 0.5 ? true : false; treeH = random(height * 0.3, height * 0.5), treeW = random(40, 60); if (treeDist < treeH * 0.25) valid = false; try{if (ground[round(x - treeW / 2)].biome == LAKE || biomeRemainder > biomeDistance - treeW || y - treeH < height * 0.15) valid = false;} catch(e){} if (valid){ trees.push(new Tree(x, treeW, treeH)); treeDist = 0; } //Clouds let cloudY, cloudW, cloudH; valid = random(1000) < 1 ? true : false; if (valid){ cloudY = random(0, 200), cloudW = random(100, 500), cloudH = random(50, 80); clouds.push(new Cloud(x, cloudY, cloudW, cloudH)); } //Birds valid = random(1000) < 1 ? true : false; if (valid){ birds.push(new Bird(x)); } x++; } //Reset some variables if (x == worldWidth){ x = 0; a = 0; } //Ground details if (ground.length == worldWidth){ try{ if (ground[x].biome != LAKE && ground[x + cliffDispo * 2].biome == LAKE){ a++; ground[x].y += a * a * 0.01; } else if (ground[x].biome != LAKE && ground[x - cliffDispo * 2].biome == LAKE){ a--; ground[x].y += a * a * 0.01; } else if (ground[x].biome == LAKE) a = cliffDispo * 2; else a = 0; }catch(e){} x++; } //End progress if bar is full if (createProgress == worldWidth * 2){ clearInterval(interval); trees.shuffle(); clouds.shuffle(); birds.shuffle(); $("#toolBarOpener").show(); gameIsRunning = true; } if (createProgress < worldWidth * 2){ setTimeout(create, 0); } } let interval = setInterval(create, 0); } function downloadWorld(){ let newGround = [], newTrees = [], newBirds = [], newClouds= [], worldValues = [{time: time, viewPort: {x: viewPort.x, y: viewPort.y}}]; for (let g of ground) newGround.push({y: round(g.y), b: g.biome, w: g.isWooden ? 1 : 0}); for (let t of trees) newTrees.push({x: round(t.x), w: round(t.width), h: round(t.height), c: t.color}); for (let b of birds) newBirds.push({x: round(b.x), y: round(b.y), v: round(b.v * 100) / 100, l: round(b.length)}); for (let c of clouds) newClouds.push({x: round(c.x), y: round(c.y), w: round(c.width), h: round(c.height), b: round(c.brightness * 100) / 100}); let str = JSON.stringify(newGround.partitiate(1)) + ", " + JSON.stringify(newTrees.partitiate(1)) + ", " + JSON.stringify(newBirds.partitiate(1)) + ", " + JSON.stringify(newClouds.partitiate(1)) + ", " + JSON.stringify(worldValues); let data = 'data:application/json;charset=utf-8,['+ encodeURIComponent(str) + "]"; $("#saveLink").attr("href", data); $("#saveLink")[0].click(); } function uploadWorld(){ gameIsRunning = false; let files = document.getElementById("fileBrowser").files; let fr = new FileReader(), recovery = {ground: ground, trees: trees, birds: birds, clouds: clouds, time: time, viewPort: viewPort}; fr.onload = function(e){ try{ let data = JSON.parse(e.target.result); let newGround = data[0].departitiate(); let newTrees = data[1].departitiate(); let newBirds = data[2].departitiate(); let newClouds = data[3].departitiate(); ground = [], trees = [], birds = [], clouds = []; for (let g of newGround) ground.push({y: g.y, biome: g.b, isWooden: g.w == 1 ? true : false}); for (let t of newTrees){ let i = newTrees.indexOf(t); trees.push(new Tree(t.x, t.w, t.h)); trees[i].color = t.c; } for (let b of newBirds){ let i = newBirds.indexOf(b); birds.push(new Bird(b.x)); birds[i].y = b.y; birds[i].v = b.v; birds[i].length = b.l; } for (let c of newClouds){ let i = newClouds.indexOf(c); clouds.push(new Cloud(c.x, c.y, c.w, c.h)); clouds[i].brightness = c.b; } time = data[4][0].time; viewPort = {x: data[4][0].viewPort.x, y: data[4][0].viewPort.y, v: recovery.viewPort.v}; $("#restoreWorld, #createWorld").hide(); $("#toolBarOpener").show(); } catch(e){ ground = recovery.ground; trees = recovery.trees; birds = recovery.birds; clouds = recovery.clouds; time = recovery.time; viewPort = recovery.viewPort; waveDispo = recovery.waveDispo; window.alert("Data is damaged!"); } if (ground.length > 0) gameIsRunning = true; else {$("#restoreWorld, #createWorld").show();} } fr.readAsText(files.item(0)); } function draw(){ if (gameIsRunning){ clear(); translate(-viewPort.x, -viewPort.y); updateUnits(); updateGround(); updateTime(); checkViewPort(); } } function updateUnits(){ //Sky background(160, 160, 255); //Clouds for (let c of clouds){ c.move(); c.show(); } //Birds for (let b of birds){ b.move(); b.show(); } //Trees for (let t of trees){ t.show(); } //Humans for (let h of humans){ h.move(); h.show(); } } function updateGround(){ let x, y, lake = false, grassH = 20, waveH = 2; waveDispo += 1; waveDispo %= 8 * PI; function wave(x){ return sin((0.25 * (x - waveDispo))) * 3; } // grass fill(100, 200, 100); beginShape(); for (x = viewPort.x; x <= viewPort.x + width; x++){ //console.log(x); let g = ground[x]; if (g.biome == LAKE) vertex(x, height); else vertex(x, g.y); } for (x = viewPort.x + width; x >= viewPort.x; x--){ let g = ground[x]; if (g.biome == LAKE) vertex(x, height); else vertex(x, g.y + grassH); } endShape(); // water fill(100, 100, 255); beginShape(); for (x = viewPort.x; x <= viewPort.x + width; x++){ let g = ground[x]; if (g.biome == LAKE) vertex(x, g.y + grassH / 2 + waveH + cliffDispo + wave(x)); else vertex(x, height); } for (x = viewPort.x + width - 1; x >= viewPort.x; x--){ vertex(x, height); } endShape(); // water --> waves fill(50, 50, 255); beginShape(); for (x = viewPort.x; x <= viewPort.x + width; x++){ let g = ground[x]; if (g.biome == LAKE) vertex(x, g.y + grassH / 2 + cliffDispo + wave(x)); else vertex(x, height); } for (x = viewPort.x + width - 1; x >= viewPort.x; x--){ let g = ground[x]; if (g.biome == LAKE) vertex(x, g.y + grassH / 2 + cliffDispo + wave(x) + waveH); else vertex(x, height); } endShape(); // dirt fill(80, 60, 40); beginShape(); for (x = viewPort.x; x <= viewPort.x + width; x++){ let g = ground[x]; if (g.biome == LAKE) vertex(x, height); else vertex(x, g.y + grassH); } for (x = viewPort.x + width; x >= viewPort.x; x--){ vertex(x, height); } endShape(); } function updateTime(){ function getDayBrightness(){ let value = sin(PI / 12 * (time - 8)) + 0.25; value = value > 1 ? 1 : value; value = value < 0.1 ? 0.1 : value; return value; } let timeTick = 24 / (60 * cycleTime * frameRate()); time += (timeTick == Infinity ? 0 : timeTick); fill(0, 0, 0, 255 - 255 * getDayBrightness()); rect(viewPort.x, viewPort.y, width, height); } function checkViewPort(){ let scrollBegin = 100; if (winMouseX <= scrollBegin && viewPort.x > 0) viewPort.x -= round(viewPort.v * (scrollBegin - winMouseX) / scrollBegin); if (winMouseX >= width - scrollBegin && viewPort.x < worldWidth - width - viewPort.v) viewPort.x += round(viewPort.v * (winMouseX - (width - scrollBegin)) / scrollBegin); if (viewPort.x < 0) viewPort.x = 0; if (viewPort.x >= worldWidth + width) viewPort.x = worldWidth - width - 1; } function togglePause(obj){ gameIsRunning = !gameIsRunning; if (gameIsRunning) $(obj).html("||"); else $(obj).html("►"); } function toggleToolBar(obj){ if ($(obj).css("top") == "0px"){ $(obj).animate({top: 103}, {top: "easeOut"}); $("#toolBar").animate({top: 0}, {top: "easeOut"}); } if ($(obj).css("top") == "103px"){ $(obj).animate({top: 0}, {top: "easeOut"}); $("#toolBar").animate({top: -103}, {top: "easeOut"}); } } function toggleInfo(){ $("#pauseButton")[0].click(); $("#infoWrapper").toggle(); } Array.prototype.departitiate = function(){ let newArr = []; for (let i = 0; i < this.length; i++){ let a = this[i]; for (let j = 0; j < a.length; j++){ let object = a[j]; newArr.push(object); //for (let k = 0; k < b.length; k++){} } } return newArr; }