main v1.0
Benjamin Kraft 2 years ago
commit d0f71bc79d
  1. 2
      .gitignore
  2. 6
      project.json
  3. 40
      public/index.html
  4. 41
      public/scripts/Bird.js
  5. 30
      public/scripts/Cloud.js
  6. 20
      public/scripts/Human.js
  7. 30
      public/scripts/Tree.js
  8. 380
      public/scripts/lib/BenjoLibrary.js
  9. 434
      public/scripts/sketch.js
  10. 103
      public/styles.css
  11. BIN
      public/thumbnail.png

2
.gitignore vendored

@ -0,0 +1,2 @@
.idea

@ -0,0 +1,6 @@
{
"display_name": "2D Openworld",
"info_text": "My first 2D Openworld project. You can explore by moving your cursor to the frame borders.".
"visible": false,
"tags": ["Game", "Simulation"]
}

@ -0,0 +1,40 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.7.2/p5.min.js" type="text/javascript"></script>
<script src="https://code.jquery.com/jquery-3.3.1.min.js" type="text/javascript"></script>
<script src="scripts/lib/BenjoLibrary.js" type="text/javascript"></script>
<script src="scripts/sketch.js" type="text/javascript"></script>
<script src="scripts/Cloud.js" type="text/javascript"></script>
<script src="scripts/Tree.js" type="text/javascript"></script>
<script src="scripts/Bird.js" type="text/javascript"></script>
<link href="styles.css" rel="stylesheet">
<title>2D Openworld</title>
</head>
<body>
<!-- Hide <a> and <input> -->
<a download="worldData.json" href="#" id="saveLink"></a>
<input id="fileBrowser" onchange="uploadWorld()" type="file"/>
<button id="createWorld" onclick="createWorld()">Neue Welt erstellen</button>
<button id="restoreWorld" onclick="$('#fileBrowser')[0].click()">Welt mit Datei wiederherstellen</button>
<button id="toolBarOpener" onclick="toggleToolBar(this)"></button>
<div id="toolBar">
<button class="toolBarEntry" id="downloadButton" onclick="downloadWorld()"></button>
<button class="toolBarEntry" id="uploadButton" onclick="$('#fileBrowser')[0].click()"></button>
<button class="toolBarEntry" id="pauseButton" onclick="togglePause(this)">||</button>
<button class="toolBarEntry" id="infoButton" onclick="toggleInfo()">i</button>
</div>
<div id="infoWrapper">
<div id="info">
<p>
//Hier stehen irgendwann mal Infos
</p>
<center><button onclick="toggleInfo()">OK</button></center>
</div>
</div>
</body>
</html>

@ -0,0 +1,41 @@
class Bird{
constructor(x){
this.x = x;
this.y = random(height * 0.05, height * 0.3);
this.v = random([true, false]) ? random(3, 5) : random(-3, -5);
this.length = random(50, 100);
}
move(){
this.x += this.v;
if (this.x - this.length / 2 > worldWidth) this.x = -this.length / 2;
if (this.x + this.length / 2 < 0) this.x = worldWidth + this.length / 2;
}
show(){
let wing = sin(0.02 * PI * this.x);
if (this.x + this.length / 2 > viewPort.x && this.x - this.length / 2 < viewPort.x + width){
fill(0);
beginShape();
vertex(this.x - this.length / 2, this.y);
vertex(this.x - this.length * 0.4, this.y - this.length * 0.1);
vertex(this.x + this.length * 0.15, this.y - this.length * 0.1);
vertex(this.x + this.length * 0.15, this.y - this.length * 0.1 - this.length * 0.4 * wing);
vertex(this.x + this.length * 0.1, this.y - this.length * 0.1 - this.length * 0.5 * wing);
vertex(this.x + this.length * 0.05, this.y - this.length * 0.1 - this.length * 0.4 * wing);
vertex(this.x, this.y - this.length * 0.1 - this.length * 0.5 * wing);
vertex(this.x - this.length * 0.05, this.y - this.length * 0.1 - this.length * 0.4 * wing);
vertex(this.x - this.length * 0.1, this.y - this.length * 0.1 - this.length * 0.5 * wing);
vertex(this.x - this.length * 0.15, this.y - this.length * 0.1 - this.length * 0.4 * wing);
vertex(this.x - this.length * 0.15, this.y - this.length * 0.1);
vertex(this.x + this.length * 0.4, this.y - this.length * 0.1);
vertex(this.x + this.length / 2, this.y);
vertex(this.x + this.length * 0.4, this.y + this.length * 0.1);
vertex(this.x - this.length * 0.4, this.y + this.length * 0.1);
endShape();
fill(255);
ellipse(this.x + ((this.v > 0) ? 1 : -1) * this.length * 0.4, this.y - this.length * 0.025, this.length * 0.05);
}
}
}

@ -0,0 +1,30 @@
class Cloud{
constructor(x, y, w, h){
this.x = x;
this.y = y;
this.width = w;
this.height = h;
this.v = 0.25;
this.brightness = random(0.75, 1);
}
move(){
this.x += this.v;
if (this.x - this.width / 2 > worldWidth){
this.x = -this.width;
}
}
show(){
fill(255 * this.brightness);
if (this.x + this.width * 9 / 8 > viewPort.x && this.x - this.width * 9 / 8 < viewPort.x + width){
ellipse(this.x + this.width / 4, this.y + this.height * 2 / 3, this.width / 2, this.height / 2);
ellipse(this.x + this.width / 2, this.y + this.height * 2 / 3, this.width / 2, this.height / 2);
ellipse(this.x + this.width * 3 / 4, this.y + this.height * 2 / 3, this.width / 2, this.height / 2);
ellipse(this.x + this.width * 3 / 8, this.y + this.height * 1 / 3, this.width / 2, this.height / 2);
ellipse(this.x + this.width * 5 / 8, this.y + this.height * 1 / 3, this.width / 2, this.height / 2);
}
}
}

@ -0,0 +1,20 @@
function Human(x, h, v){
this.x = x;
this.height = h;
this.male = random([true, false]);
this.legDist = 0;
this.v = v;
this.move = function(d){
this.x += this.v * d;
}
this.show = function(){
var y = ground[this.x];
stroke(0);
fill(0);
strokeWeight(1);
line(this.x, y - this.height * 0.4, this.x, y - this.height * 0.85);
ellipse(this.x, y - this.height * 0.925, this.height * 0.1, this.height * 0.15);
}
}

@ -0,0 +1,30 @@
class Tree{
constructor(x, w, h){
this.x = x;
this.width = w;
this.height = h;
let c = round(random(60, 100));
this.color = {r: c, g: round(random(170, 230)), b: c};
}
show(){
if (this.x + this.height * 0.375 > viewPort.x && this.x - this.height * 0.375 < viewPort.x + width){
let yArr = [];
for (let x = this.x - this.width / 2; x < this.x + this.width / 2; x++){
try{yArr.push(ground[round(x)].y);}
catch(e){}
}
let crownY = max(yArr) - this.height;
fill(80, 50, 40);
rect(this.x - this.width / 2, crownY, this.width, this.height);
fill(this.color.r, this.color.g, this.color.b);
ellipse(this.x, crownY, this.height / 2, this.height / 2);
for (let i = 0; i < TWO_PI; i += 1 / 4 * PI){
let x = this.x + this.height / 4 * sin(i);
let y = crownY + this.height / 4 * cos(i);
ellipse(x, y, this.height / 2, this.height / 2);
}
}
}
}

@ -0,0 +1,380 @@
var TOP = 1;
var RIGHT = 2
var BOTTOM = 3;
var LEFT = 4;
var TOP_RIGHT = 5;
var BOTTOM_RIGHT = 6;
var BOTTOM_LEFT = 7;
var TOP_LEFT = 8;
var wWidth = window.innerWidth;
var wHeight = window.innerHeight;
var oldWHeight;
var oldWWidth;
function updateVars(){
oldWWidth = wWidth;
oldWHeight = wHeight;
wWidth = window.innerWidth;
wHeight = window.innerHeight;
}
function collisionDetection(obj0, obj1){
var sp = strokePadding;
if (sp == null) sp = 0;
if (obj0.isEllipse && obj1.isRectangle){
//Ball
var b = obj0;
//Rectangle
var r = obj1;
for (var i = 0; i < TWO_PI; i += PI / 32){
/* Check every borderpoint of the ball beginning
at the top in clock direction up to top again */
// Ball Center X
var bcx = b.x;
// Ball Center Y
var bcy = b.y;
// Ball Border X
var bbx = b.x + sin(i) * b.r;
// Ball Border Y inverted because Y = 0 is the TOP of the screen
var bby = b.y - cos(i) * b.r;
// Rectangle Width
var rW = r.width + 2 * sp;
// Rectangle Height
var rH = r.height + 2 * sp;
// Rectangle Border X
var rX = r.x - sp;
// Rectangle Border Y
var rY = r.y - sp;
// Objects touch
if (bbx > rX && bbx < rX + rW
&& bby > rY && bby < rY + rH){
// STRAIGHT FACES //
//Top/Bottom touch
if (bcx > rX && bcx < rX + rW){
//Top touch
if (b.v.y > 0) return {isTouching: true, location: TOP};
//Bottom touch
if (b.v.y < 0) return {isTouching: true, location: BOTTOM};
}
//Left/Right touch
if (bcy > rY && bcy < rY + rH){
//Left touch
if (b.v.x > 0) return {isTouching: true, location: LEFT};
//Right touch
if (b.v.x < 0) return {isTouching: true, location: RIGHT};
}
// CORNERS //
// BOTTOM Left/Right
if (i > 0 && i <= PI / 2) return {isTouching: true, location: BOTTOM_LEFT};
//LEFT Bottom/Top
if (i > PI / 2 && i <= PI) return {isTouching: true, location: TOP_LEFT};
//TOP Left/Right
if (i > PI && i <= PI + PI / 2) return {isTouching: true, location: TOP_RIGHT};
//RIGHT Bottom/Top
if (i > PI + PI / 2 && i <= TWO_PI) return {isTouching: true, location: BOTTOM_RIGHT};
}
}
}
if (obj0.isEllipse && obj1.isEllipse){
//Ball 1
var b1 = obj0;
//Ball 2
var b2 = obj1;
//Balls are close to each other
if (b1.x + b1.r > b2.x - b2.r
&& b1.x - b1.r < b2.x + b2.r
&& b1.y + b1.r > b2.y - b2.r
&& b1.y - b1.r < b2.y + b2.r){
var distance = sqrt(pow(b1.x - b2.x, 2) + pow(b1.y - b2.y, 2));
if (distance < b1.r + b2.r) return {isTouching: true};
}
}
return {isTouching: false, location: 0};
}
function performCollision(obj0, obj1, collision){
if (obj0.isEllipse){
var ball = obj0;
//Ball collides with frameborder
if (obj1.isFrameborder){
switch (collision.location){
case BOTTOM:
ball.v.y *= -1;
break;
case LEFT:
case RIGHT:
ball.v.x *= -1;
break;
}
if (testMode && collision.location == TOP) ball.v.y *= -1;
ball.move();
}
//Ball collides with any brick
if (obj1.isBrick){
switch (collision.location){
case TOP:
case BOTTOM:
ball.v.y *= -1;
ball.move();
return;
case LEFT:
case RIGHT:
ball.v.x *= -1;
ball.move();
return;
case TOP_LEFT:
var cornerX = obj1.x;
var cornerY = obj1.y;
break;
case TOP_RIGHT:
var cornerX = obj1.x + obj1.width;
var cornerY = obj1.y;
break;
case BOTTOM_LEFT:
var cornerX = obj1.x;
var cornerY = obj1.y + obj1.height;
break;
case BOTTOM_RIGHT:
var cornerX = obj1.x + obj1.width;
var cornerY = obj1.y + obj1.height;
break;
}
var nx = ball.x - cornerX;
var ny = ball.y - cornerY;
var length = sqrt(nx * nx + ny * ny);
nx /= length;
ny /= length;
var projection = ball.v.x * nx + ball.v.y * ny;
ball.v.x = ball.v.x - 2 * projection * nx;
ball.v.y = ball.v.y - 2 * projection * ny;
ball.move();
}
//Ball collides with paddleboard
if (obj1.isPaddle){
switch (collision.location){
case TOP:
case TOP_LEFT:
case TOP_RIGHT:
ball.v.x = ball.calcVelocityX(obj1, ball.v.x);
ball.v.y = -ball.calcVelocityY();
ball.move();
return;
case LEFT:
case RIGHT:
ball.v.x *= -1;
ball.move();
return;
case BOTTOM_LEFT:
var cornerX = obj1.x;
var cornerY = obj1.y + obj1.height;
break;
case BOTTOM_RIGHT:
var cornerX = obj1.x + obj1.width;
var cornerY = obj1.y + obj1.height;
break;
}
var nx = ball.x - cornerX;
var ny = ball.y - cornerY;
var length = sqrt(nx * nx + ny * ny);
nx /= length;
ny /= length;
var projection = ball.v.x * nx + ball.v.y * ny;
ball.v.x = ball.v.x - 2 * projection * nx;
ball.v.y = ball.v.y - 2 * projection * ny;
ball.move();
}
//Ball collides with other ball
if (obj1.isEllipse){
//Ball 1
var b1 = obj0;
//Ball 2
var b2 = obj1;
//Set mass equal to radius of each ball
b1.mass = b1.r;
b2.mass = b2.r;
//Colliding angle of ball 1 to ball 2 using arc tan of both x and y differences
var collisionAngle = atan2((b2.y - b1.y), (b2.x - b1.x));
//Converting directions of velocity vector of balls into angles
var d1 = atan2(b1.v.y, b1.v.x);
var d2 = atan2(b2.v.y, b2.v.x);
//Ignoring mass effects new velocites are simply magnitude multiplied with value of angle differences
var newXspeed1 = b1.v.mag * cos(d1 - collisionAngle);
var newYspeed1 = b1.v.mag * sin(d1 - collisionAngle);
var newXspeed2 = b2.v.mag * cos(d2 - collisionAngle);
var newYspeed2 = b2.v.mag * sin(d2 - collisionAngle);
//According to the principle of linear momentum, kinetic energy stays the same after collision, so velocities are now related to masses
var finalXspeed1 = ((b1.mass - b2.mass) * newXspeed1 + b2.mass * 2 * newXspeed2) / (b1.mass + b2.mass);
var finalYspeed1 = newYspeed1;
var finalXspeed2 = (b1.mass * 2 * newXspeed1 + (b2.mass - b1.mass) * newXspeed2) / (b1.mass + b2.mass);
var finalYspeed2 = newYspeed2;
//Values of collisionAngle
var cosAngle = cos(collisionAngle);
var sinAngle = sin(collisionAngle);
//To also keep velocites relative to pure collisionAngle, subtract sin*x from cos*x and add sin*y to cos*y because coordSystem has y = 0 on the top
var u1x = cosAngle * finalXspeed1 - sinAngle * finalYspeed1;
var u1y = sinAngle * finalXspeed1 + cosAngle * finalYspeed1;
var u2x = cosAngle * finalXspeed2 - sinAngle * finalYspeed2;
var u2y = sinAngle * finalXspeed2 + cosAngle * finalYspeed2;
//Set new velocities to both balls
b1.v.x = u1x;
b1.v.y = u1y;
b2.v.x = u2x;
b2.v.y = u2y;
//Update magnitude
b1.v.mag = sqrt(pow(b1.v.x, 2) + pow(b1.v.y, 2));
b2.v.mag = sqrt(pow(b2.v.x, 2) + pow(b2.v.y, 2));
//Move balls one vx/vy forward to avoid double inverting collision detection
b1.x += b1.v.x;
b1.y += b1.v.y;
b2.x += b2.v.x;
b2.y += b2.v.y;
}
}
}
function toTimeString(time, hoursWanted){
var time = floor(time / 10);
var hs = String(floor(time % 100));
var fs = String(floor((time / 100) % 60));
if (hoursWanted){
var min = String(floor(((time / 100) / 60) % 60));
var hr = String(floor(((time / 100) / 60) / 60));
if (hs.length < 2) hs = "0" + hs;
if (fs.length < 2) fs = "0" + fs;
if (min.length < 2) min = "0" + min;
if (hr.length < 2) hr = "0" + hr;
var timeString = hr + ":" + min + ":" + fs + ":" + hs;
} else {
var min = String(floor(((time / 100) / 60) % 60));
if (hs.length < 2) hs = "0" + hs;
if (fs.length < 2) fs = "0" + fs;
if (min.length < 2) min = "0" + min;
var timeString = min + ":" + fs + ":" + hs;
}
return timeString;
}
function setCookie(name, value, years){
var expires = "";
if (years){
var date = new Date();
date.setTime(date.getTime() + (years * 365 * 24 * 60 * 60 * 1000));
expires = "; expires=" + date.toUTCString();
}
document.cookie = name + "=" + value + expires + "; path=/";
}
function getCookie(name){
var nameEQ = name + "=";
var ca = document.cookie.split(';');
for (var i = 0; i < ca.length; i++){
var c = ca[i];
while (c.charAt(0) == ' ') c = c.substring(1, c.length);
if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length, c.length);
}
return null;
}
function deleteCookies(){
for (var i = 0; i < arguments.length; i++) setCookie(arguments[i], "", -1);
}
function deleteAllCookies(){
var cookies = document.cookie.split(";");
for (var i = 0; i < cookies.length; i++) deleteCookies(cookies[i].split("=")[0]);
}
Array.prototype.shuffle = function(){
let currentIndex = this.length, temporaryValue, randomIndex;
while (0 != currentIndex) {
randomIndex = floor(random() * currentIndex);
currentIndex -= 1;
temporaryValue = this[currentIndex];
this[currentIndex] = this[randomIndex];
this[randomIndex] = temporaryValue;
}
}
Array.prototype.clone = function() {
return this.slice(0);
};
Array.prototype.partitiate = function(dimensions){
if (dimensions == 0) return this;
let parts = [];
while(this.length) parts.push(this.splice(0, round(pow(this.length, 1 / (1 + 1 / dimensions)))).partitiate(dimensions - 1));
return parts;
}

@ -0,0 +1,434 @@
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;
}

@ -0,0 +1,103 @@
a:link, a:hover, a:active, a:visited{color: #000;}
body{margin: 0; padding: 0; overflow-y:hidden; overflow-x: hidden;}
canvas{margin: 0; padding: 0; border: none; display: block;}
button{cursor: pointer;}
#toolBarOpener{
position: absolute;
display: block;
background-color: #FFF;
left: calc((100% - 50px) / 2);
top: 0;
width: 50px;
height: 20px;
border: none;
border-radius: 0 0 5px 5px;
}
#toolBar{
position: absolute;
display: block;
background-color: #F90;
left: calc((100% - 371px) / 2);
top: -103px;
width: 335px;
height: 70px;
padding: 15px;
border-radius: 0 0 20px 20px;
border: 3px solid #000;
border-top: none;
}
.toolBarEntry{
width: 70px;
height: 70px;
margin: 0 5px 0 5px;
border: 3px solid #000;
border-radius: 10px;
background-color: #FFF;
padding: 0;
font-size: 50px;
}
#downloadButton{color: #0C0;}
#uploadButton{color: #C00;}
#infoButton{color: #00F;}
#createWorld{
position: absolute;
top: calc(100% / 2 - 50px);
left: calc(100% / 2 - 220px);
width: 200px;
height: 100px;
border: 5px solid #000;
border-radius: 10px;
font-size: 25px;
}
#restoreWorld{
position: absolute;
top: calc(100% / 2 - 50px);
left: calc(100% / 2 + 20px);
width: 200px;
height: 100px;
border: 5px solid #000;
border-radius: 10px;
font-size: 25px;
}
#infoWrapper{
position: absolute;
width: 100%;
height: 100%;
z-index: 5;
background-color: rgba(0, 0, 0, 0.3);
}
#info{
position: absolute;
width: 600px;
height: 400px;
margin: auto;
top: 0;
bottom: 0;
left: 0;
right: 0;
border: 7px solid #333;
border-radius: 30px;
font-size: 25px;
background-color: #999;
}
#info button{
width: 100px;
height: 50px;
margin: 30px;
background-color: #0C0;
border: 3px solid #080;
border-radius: 5px;
font-size: 30px;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 107 KiB

Loading…
Cancel
Save