commit 5123fb654887c2accb04428d4285232427f96ba3
Author: Benjamin Kraft ";
+ table += "
";
+ htmlCredits.append($(table));
+ settings.messages.credits.html = htmlCredits;
+}
\ No newline at end of file
diff --git a/public/data/scripts/Plant.js b/public/data/scripts/Plant.js
new file mode 100644
index 0000000..79d1ac1
--- /dev/null
+++ b/public/data/scripts/Plant.js
@@ -0,0 +1,122 @@
+"use strict"
+
+class Tree{
+
+ constructor(brick){
+ this.pos = brick.pos;
+ this.dim = createVector(random(10, 30), random(100, 200));
+ this.current = createVector(0, 0);
+ this.dispoX = random(brick.dim.x - 40) + 20;
+ this.colorSetup();
+ }
+
+ show(){
+ //Wood
+ fill(this.color.wood);
+ rect(this.pos.x + this.dispoX, this.pos.y - this.dim.y, this.dim.x, this.dim.y);
+
+ //Leaf
+ fill(this.color.leaf);
+ for (let i = 0; i <= TWO_PI; i += PI / 4){
+ let x = this.dispoX + this.pos.x + this.dim.x / 2 + this.dim.x * 2 * sin(i);
+ let y = this.pos.y - this.dim.y + this.dim.x * 2 * cos(i);
+ ellipse(x, y, this.dim.x * 3);
+ }
+ ellipse(this.dispoX + this.pos.x + this.dim.x / 2, this.pos.y - this.dim.y, this.dim.x * 3);
+ }
+
+ colorSetup(){
+ let l = color(colors.brick.tree.leaf),
+ w = color(colors.brick.tree.wood);
+ colorMode(HSB);
+ let leaf = color(hue(l), saturation(l), brightness(l) + random(-10, 10)),
+ wood = color(hue(w), saturation(w), brightness(w) + random(-10, 10));
+ colorMode(RGB);
+ this.color = {
+ leaf: leaf,
+ wood: wood
+ };
+ }
+
+}
+
+class Grass{
+
+ constructor(parent, dispoX){
+ this.pos = parent.pos;
+ this.dispoX = dispoX;
+ this.positions = [];
+ this.flower = ranBool() ? new Flower(this) : null;
+ for (let i = HALF_PI + 0.25; i < HALF_PI + PI - 0.25; i += random(PI / 8, PI / 16)) this.positions.push(createVector(sin(i) * 15, cos(i) * 25));
+ }
+
+ show(){
+ if (this.flower){
+ this.flower.show();
+ }
+ fill(colors.brick.grass);
+ for (let p of this.positions){
+ let x1 = this.pos.x + this.dispoX + p.x;
+ let x2 = this.pos.x + this.dispoX + p.x * 0.5;
+ let y = this.pos.y + p.y;
+ triangle(x1, y, this.pos.x + this.dispoX, this.pos.y, x2, y);
+ }
+ }
+
+}
+
+class Flower{
+
+ constructor(grass){
+ this.pos = grass.pos;
+ this.dim = createVector(3, random(25, 50));
+ this.dispoX = grass.dispoX;
+ this.colorSetup();
+ let cr = random(2, 5);
+ this.radius = {
+ center: cr,
+ petal: cr + random(2, 4)
+ };
+ this.petals = [];
+ for (let i = 0; i < TWO_PI; i += PI / 2){
+ let x = this.dispoX + sin(i) * this.radius.center * 2;
+ let y = cos(i) * this.radius.center * 2;
+ this.petals.push(createVector(x, y));
+ }
+ }
+
+ show(){
+
+ //Haulm
+ strokeWeight(this.dim.x);
+ stroke(colors.brick.flower.haulm);
+ line(this.pos.x + this.dispoX, this.pos.y, this.pos.x + this.dispoX, this.pos.y - this.dim.y);
+
+ //Center
+ noStroke();
+ fill(this.color.center);
+ ellipse(this.pos.x + this.dispoX, this.pos.y - this.dim.y, this.radius.center * 2);
+
+ //Petals
+ fill(this.color.petal);
+ for (let p of this.petals){
+ ellipse(p.x + this.pos.x, p.y + this.pos.y - this.dim.y, this.radius.petal * 2);
+ }
+
+ }
+
+ colorSetup(){
+ let c = color(colors.brick.flower.center),
+ p = color(colors.brick.flower.petal);
+ colorMode(HSB);
+ let center = color(int(random(360)), saturation(c), brightness(c));
+ let petal = color(int(random(360)), saturation(p), brightness(p));
+ colorMode(RGB);
+ this.color = {
+ center: center,
+ petal: petal
+ };
+ }
+
+}
+
diff --git a/public/data/scripts/Player.js b/public/data/scripts/Player.js
new file mode 100644
index 0000000..e334957
--- /dev/null
+++ b/public/data/scripts/Player.js
@@ -0,0 +1,153 @@
+"use strict"
+
+class Player{
+
+ constructor(x, y){
+ this.pos = createVector(x, y);
+ this.vel = createVector(0, 0);
+ this.acc = createVector(0, 0.25);
+ this.radius = 50;
+ this.brick = null;
+ this.colorSetup();
+ }
+
+ update(){
+ this.move();
+ }
+
+ display(){
+ this.show();
+ }
+
+ move(){
+ if (this.brick){
+ this.vel.y = 0;
+ this.pos.add(this.brick.vel);
+ this.pos.y = this.brick.pos.y - this.radius;
+ }
+
+ this.pos.add(this.vel);
+ this.vel.add(this.acc);
+
+ this.vel.x *= 0.95;
+
+ let limit = this.maxVelocityX;
+ if (this.vel.x < -limit) this.vel.x = -limit;
+ if (this.vel.x > limit) this.vel.x = limit;
+ }
+
+ show(){
+ stroke(red(this.color) * 0.5, green(this.color) * 0.5, blue(this.color) * 0.5);
+ strokeWeight(1);
+
+ //Body
+ fill(this.color);
+ ellipse(this.pos.x, this.pos.y, this.radius * 2);
+
+ //Eyes
+ let radius = this.radius * 0.3;
+ let dispoX = 1 / (1 + pow(0.7, this.vel.x)) - 0.5;
+ let dispoY = 1 / (1 + pow(0.7, this.vel.y)) - 0.5;
+ let outerDispoX = dispoX * this.radius / 2;
+ let outerDispoY = dispoY * this.radius / 2;
+ let innerDispoX = outerDispoX + dispoX * radius / 2;
+ let innerDispoY = outerDispoY + dispoY * radius / 2;
+
+ fill(colors.player.eyes.outer);
+ ellipse(this.pos.x + radius + outerDispoX, this.pos.y - radius + outerDispoY, radius, radius * 4/3);
+ ellipse(this.pos.x - radius + outerDispoX, this.pos.y - radius + outerDispoY, radius, radius * 4/3);
+
+ fill(colors.player.eyes.inner);
+ ellipse(this.pos.x + radius + innerDispoX, this.pos.y - radius + innerDispoY, radius / 2, radius * 2/3);
+ ellipse(this.pos.x - radius + innerDispoX, this.pos.y - radius + innerDispoY, radius / 2, radius * 2/3);
+
+ //Mouth
+ let rotation = dispoX / 2;
+
+ fill(red(this.color) / 3, green(this.color) / 3, blue(this.color) / 3);
+ arc(this.pos.x, this.pos.y + this.radius * 0.2 + dispoY * this.radius / 2, this.radius, this.radius * 0.8, PI / 16 + rotation, PI - PI / 16 + rotation, CHORD);
+ }
+
+ collision(bricks, world){
+
+ //Bricks
+ if (!this.touches(this.brick)){
+ let brick = null;
+ for (let b of bricks){
+ if (this.touches(b)){
+ brick = b;
+ break;
+ } else brick = null;
+ }
+ this.brick = brick;
+ }
+
+ let trashHold = 10;
+ //World borders
+ if (this.pos.x - this.radius < world.pos.x) this.pos.x = world.pos.x + this.radius;
+ if (this.pos.x + this.radius > world.pos.x + world.dim.x) this.pos.x = world.pos.x + world.dim.x - this.radius;
+ if (this.pos.y - this.radius < world.pos.y){
+ this.pos.y = world.pos.y + this.radius;
+ this.vel.y *= -1;
+ }
+ if (this.pos.y - this.radius > world.pos.y + world.dim.y) game.lost();
+ }
+
+ touches(object){
+ if (!object) return false;
+
+ let hitbox = object.getHitbox();
+
+ if (object instanceof Brick){
+ if (this.pos.x + this.radius / 2 > hitbox.pos.x && this.pos.x - this.radius / 2 < hitbox.pos.x + hitbox.dim.x &&
+ (this.pos.y + this.radius <= hitbox.pos.y && (this.pos.y + this.radius + this.vel.y >= hitbox.pos.y + hitbox.vel.y
+ || this.pos.y + this.radius + this.vel.y >= hitbox.pos.y))){
+ return true;
+ }
+ }
+ if (object instanceof Coin){
+ let distX = abs(this.pos.x - (hitbox.pos.x + hitbox.dim.x / 2));
+ let distY = abs(this.pos.y - (hitbox.pos.y + hitbox.dim.y / 2));
+ if ((distX <= (hitbox.dim.x / 2) || distY <= (hitbox.dim.y / 2))
+ && distX < (hitbox.dim.x / 2 + this.radius)
+ && distY < (hitbox.dim.y / 2 + this.radius)) return true;
+ let dx = distX - hitbox.dim.x / 2;
+ let dy = distY - hitbox.dim.y / 2;
+ if (dx * dx + dy * dy <= this.radius * this.radius) return true;
+ }
+ return false;
+ }
+
+ walk(d){
+ this.acc.x = d;
+ }
+
+ break(){
+ this.acc.x = 0;
+ }
+
+ jump(){
+ if (!this.brick) return;
+ this.vel.y = -abs(this.vel.x * 0.3) - this.jumpVelocity + this.brick.vel.y;
+ this.brick = null;
+ new Sound(Sound.Jump()).play();
+ }
+
+ fall(d){
+ this.acc.y += d * 0.5;
+ }
+
+ setColor(color){
+ this.color = color;
+ }
+
+ colorSetup(){
+ let h = int(random(360));
+ h = floor(h / 60) * 60;
+ let c = color(colors.player.body);
+ colorMode(HSB);
+ this.color = color(h, saturation(c), brightness(c));
+ colorMode(RGB);
+ }
+
+}
\ No newline at end of file
diff --git a/public/data/scripts/Sound.js b/public/data/scripts/Sound.js
new file mode 100644
index 0000000..1b52295
--- /dev/null
+++ b/public/data/scripts/Sound.js
@@ -0,0 +1,110 @@
+"use strict"
+
+let audioOptions = {
+ sound: true,
+ music: true
+};
+
+class Sound{
+
+ constructor(type){
+ this.sound = random(audio.sound[type]);
+ }
+
+ static Won(){return "won";}
+
+ static Lost(){return "lost";}
+
+ static Coin(){return "coin";}
+
+ static Jump(){return "jump";}
+
+ play(){
+ this.sound.play();
+ updateVolume();
+ }
+}
+
+function toggleSounds(){
+ audioOptions.sound = !audioOptions.sound;
+ $("#soundVolume").prop("disabled", !audioOptions.sound);
+ updateVolume();
+}
+
+function toggleMusic(){
+ audioOptions.music = !audioOptions.music;
+ $("#musicVolume").prop("disabled", !audioOptions.music);
+ updateVolume();
+}
+
+function updateVolume(){
+ let soundVolume = $("#soundVolume").val() / 100,
+ musicVolume = $("#musicVolume").val() / 100;
+ soundVolume = !audioOptions.sound ? 0 : soundVolume;
+ musicVolume = !audioOptions.music ? 0 : musicVolume;
+ setVolume("sound", soundVolume);
+ setVolume("music", musicVolume);
+}
+
+function getVolume(type){
+ let val = $("#" + type + "Volume").val();
+ return val / 100;
+}
+
+function setVolume(key, volume){
+ for (let prop in audio){
+ if (prop === key){
+ for (let type in audio[prop]){
+ let audios = audio[prop][type];
+ for (let audio of audios){
+ audio.setVolume(volume);
+ }
+ }
+ }
+ }
+}
+
+function resetMusics(){
+ for (let type in audio.music){
+ let audios = audio.music[type];
+ for (let audio of audios){
+ audio.jump();
+ audio.pause();
+ }
+ }
+}
+
+function loadAudioFiles(loadedCallback){
+ soundFormats("mp3", "wav");
+ audio = JSON.parse(JSON.stringify(settings.audio));
+ loader = new Loader(Loader.Circle(), "Loading Assets...", loadedCallback);
+ let count = 0, index = 0;
+ for (let prop in audio){
+ let type = audio[prop];
+ for (let key in type){
+ let files = type[key];
+ for (let file of files){
+ count++;
+ }
+ }
+ }
+ for (let prop in audio){
+ let type = audio[prop];
+ for (let key in type){
+ let files = type[key];
+ for (let file of files){
+ loadSound(file, updateProgress);
+ function updateProgress(song){
+ files[files.indexOf(file)] = song;
+ index++;
+ loader.updateProgress(index / count, song.file);
+ }
+ }
+ }
+ }
+}
+
+function audioFilesLoaded(){
+ updateVolume();
+ loadNewGame();
+}
\ No newline at end of file
diff --git a/public/data/scripts/events.js b/public/data/scripts/events.js
new file mode 100644
index 0000000..b592547
--- /dev/null
+++ b/public/data/scripts/events.js
@@ -0,0 +1,79 @@
+"use strict"
+
+function keyPressed(){
+ if (!game) return false;
+ if (!game.ready) return false;
+ switch(keyCode){
+ case LEFT_ARROW:
+ game.player.walk(-1);
+ break;
+ case RIGHT_ARROW:
+ game.player.walk(1);
+ break;
+ case UP_ARROW:
+ game.player.jump();
+ break;
+ case DOWN_ARROW:
+ game.player.fall(1);
+ break;
+ case 68: //D
+ debug = !debug;
+ break;
+ case 78: //N
+ loadNewGame();
+ break;
+ case 76: //L
+ game.lost();
+ break;
+ case 27: //ESC
+ case 9: //TAB
+ toggleMenu($("#menuOpener"));
+ break;
+ case 32: //Spacebar
+ game.toggleRun();
+ break;
+ }
+ return false;
+}
+
+function keyReleased(){
+ if (!game) return false;
+ if (!game.ready) return true;
+ switch(keyCode){
+ case LEFT_ARROW:
+ if (!keyIsDown(RIGHT_ARROW)) game.player.break();
+ break;
+ case RIGHT_ARROW:
+ if (!keyIsDown(LEFT_ARROW)) game.player.break();
+ break;
+ case DOWN_ARROW:
+ game.player.fall(-1);
+ break;
+ }
+}
+
+function mouseMoved(){
+ globalCursor ? globalCursor.standStillTime = 0 : null;
+}
+
+function mouseDragged(){
+
+}
+
+function mousePressed(){
+
+}
+
+function mouseReleased(){
+
+}
+
+window.onresize = function(){
+ let i = 0;
+ function resize(){
+ resizeCanvas($("#canvasHolder").outerWidth(), $("#canvasHolder").outerHeight(), true);
+ i++;
+ if (i < 5) window.setTimeout(resize, 0);
+ }
+ resize();
+}
\ No newline at end of file
diff --git a/public/data/scripts/lib/benjo_library.js b/public/data/scripts/lib/benjo_library.js
new file mode 100644
index 0000000..a145901
--- /dev/null
+++ b/public/data/scripts/lib/benjo_library.js
@@ -0,0 +1,678 @@
+let TOP = 1,
+ RIGHT = 2,
+ BOTTOM = 3,
+ LEFT = 4,
+ TOP_RIGHT = 5,
+ BOTTOM_RIGHT = 6,
+ BOTTOM_LEFT = 7,
+ TOP_LEFT = 8;
+
+function collisionDetection(obj0, obj1){
+
+ let sp = strokePadding;
+ if (sp == null) sp = 0;
+
+ if (obj0.isEllipse && obj1.isRectangle){
+
+ //Ball
+ let b = obj0;
+
+ //Rectangle
+ let r = obj1;
+
+ for (let 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
+ let bcx = b.x;
+
+ // Ball Center Y
+ let bcy = b.y;
+
+ // Ball Border X
+ let bbx = b.x + sin(i) * b.r;
+
+ // Ball Border Y inverted because Y = 0 is the TOP of the screen
+ let bby = b.y - cos(i) * b.r;
+
+ // Rectangle Width
+ let rW = r.width + 2 * sp;
+
+ // Rectangle Height
+ let rH = r.height + 2 * sp;
+
+ // Rectangle Border X
+ let rX = r.x - sp;
+
+ // Rectangle Border Y
+ let 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
+ let b1 = obj0;
+
+ //Ball 2
+ let 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){
+
+ let 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){
+
+ let 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){
+ let cornerX, cornerY;
+ 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:
+ cornerX = obj1.x;
+ cornerY = obj1.y;
+ break;
+ case TOP_RIGHT:
+ cornerX = obj1.x + obj1.width;
+ cornerY = obj1.y;
+ break;
+ case BOTTOM_LEFT:
+ cornerX = obj1.x;
+ cornerY = obj1.y + obj1.height;
+ break;
+ case BOTTOM_RIGHT:
+ cornerX = obj1.x + obj1.width;
+ cornerY = obj1.y + obj1.height;
+ break;
+ }
+
+ let nx = ball.x - cornerX;
+ let ny = ball.y - cornerY;
+ let length = sqrt(nx * nx + ny * ny);
+ nx /= length;
+ ny /= length;
+
+ let 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){
+ let cornerX, cornerY;
+ 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:
+ cornerX = obj1.x;
+ cornerY = obj1.y + obj1.height;
+ break;
+ case BOTTOM_RIGHT:
+ cornerX = obj1.x + obj1.width;
+ cornerY = obj1.y + obj1.height;
+ break;
+ }
+ let nx = ball.x - cornerX;
+ let ny = ball.y - cornerY;
+ let length = sqrt(nx * nx + ny * ny);
+ nx /= length;
+ ny /= length;
+
+ let 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
+ let b1 = obj0;
+
+ //Ball 2
+ let 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
+ let collisionAngle = atan2((b2.y - b1.y), (b2.x - b1.x));
+
+ //Converting directions of velocity vector of balls into angles
+ let d1 = atan2(b1.v.y, b1.v.x);
+ let d2 = atan2(b2.v.y, b2.v.x);
+
+ //Ignoring mass effects new velocites are simply magnitude multiplied with value of angle differences
+ let newXspeed1 = b1.v.mag * cos(d1 - collisionAngle);
+ let newYspeed1 = b1.v.mag * sin(d1 - collisionAngle);
+ let newXspeed2 = b2.v.mag * cos(d2 - collisionAngle);
+ let 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
+ let finalXspeed1 = ((b1.mass - b2.mass) * newXspeed1 + b2.mass * 2 * newXspeed2) / (b1.mass + b2.mass);
+ let finalYspeed1 = newYspeed1;
+ let finalXspeed2 = (b1.mass * 2 * newXspeed1 + (b2.mass - b1.mass) * newXspeed2) / (b1.mass + b2.mass);
+ let finalYspeed2 = newYspeed2;
+
+ //Values of collisionAngle
+ let cosAngle = cos(collisionAngle);
+ let 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
+ let u1x = cosAngle * finalXspeed1 - sinAngle * finalYspeed1;
+ let u1y = sinAngle * finalXspeed1 + cosAngle * finalYspeed1;
+ let u2x = cosAngle * finalXspeed2 - sinAngle * finalYspeed2;
+ let 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){
+
+ time = floor(time / 10);
+
+ let hs = String(floor(time % 100));
+ let fs = String(floor((time / 100) % 60));
+
+ if (hoursWanted){
+ let min = String(floor(((time / 100) / 60) % 60));
+ let 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;
+
+ let timeString = hr + ":" + min + ":" + fs + ":" + hs;
+ } else {
+ let 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;
+
+ let timeString = min + ":" + fs + ":" + hs;
+ }
+
+
+
+ return timeString;
+}
+
+
+function setCookie(name, value, years){
+ let expires = "";
+ if (years){
+ let 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){
+ let nameEQ = name + "=";
+ let ca = document.cookie.split(';');
+ for (let i = 0; i < ca.length; i++){
+ let 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 (let i = 0; i < arguments.length; i++) setCookie(arguments[i], "", -1);
+}
+
+function deleteAllCookies(){
+ let cookies = document.cookie.split(";");
+ for (let 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);
+};
+
+//Divides big Array into big multidimensional Array
+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;
+}
+
+String.prototype.isValidHEX = function(){
+ return /(^#[0-9A-Fa-f]{6}$)|(^#[0-9A-Fa-f]{3}$)/i.test(this);
+}
+
+String.prototype.capitalize = function(){
+ return this.charAt(0).toUpperCase() + this.slice(1);
+}
+
+function debugInformation(){
+ let x = 0,
+ y = 0;
+ textSize(12);
+ textStyle(NORMAL);
+ stroke(255);
+ strokeWeight(1);
+ fill(255);
+ text("FPS : " + round(frameRate()), 10 + x, 10 + textAscent("FPS : ") + y);
+ text("MouseX : " + round(mouseX + x), 10 + x, 10 + textAscent("FPS : ") + 10 + textAscent("MouseX : ") + y);
+ text("MouseY : " + round(-mouseY - y), 10 + x, 10 + textAscent("FPS : ") + 10 + textAscent("MouseX : ") + 10 + textAscent("MouseY : ") + y);
+}
+
+
+
+function ColorPicker(editor) {
+ this.movingObject = "";
+
+ this.updateFromGraphical = function(){
+ this.h = (1 - $("#hue_picker").position().top / $("#hue").height()) * 360;
+ this.s = ($("#sb_picker").position().left + 8) / $("#saturation").width() * 100;
+ this.v = (1 - ($("#sb_picker").position().top + 8) / $("#value").height()) * 100;
+
+ this.r = HSVtoRGB(this.h, this.s, this.v).r;
+ this.g = HSVtoRGB(this.h, this.s, this.v).g;
+ this.b = HSVtoRGB(this.h, this.s, this.v).b;
+
+ this.hex = RGBtoHEX(this.r, this.g, this.b);
+
+ this.updateInterface();
+ }
+
+ this.updateFromHSV = function(){
+ this.h = $($("#color_picker_hsv input")[0]).val();
+ this.s = $($("#color_picker_hsv input")[1]).val();
+ this.v = $($("#color_picker_hsv input")[2]).val();
+
+ this.r = HSVtoRGB(this.h, this.s, this.v).r;
+ this.g = HSVtoRGB(this.h, this.s, this.v).g;
+ this.b = HSVtoRGB(this.h, this.s, this.v).b;
+
+ this.hex = RGBtoHEX(this.r, this.g, this.b);
+
+ this.updateFromHEX(null, true);
+
+ this.updateInterface();
+ }
+
+ this.updateFromRGB = function(){
+ this.r = $($("#color_picker_rgb input")[0]).val();
+ this.g = $($("#color_picker_rgb input")[1]).val();
+ this.b = $($("#color_picker_rgb input")[2]).val();
+
+ this.h = RGBtoHSV(this.r, this.g, this.b).h;
+ this.s = RGBtoHSV(this.r, this.g, this.b).s;
+ this.v = RGBtoHSV(this.r, this.g, this.b).v;
+
+ this.hex = RGBtoHEX(this.r, this.g, this.b);
+
+ this.updateFromHEX(null, true);
+
+ this.updateInterface();
+ }
+
+ this.updateFromHEX = function(input, otf){
+ if (!otf){ //Not on the fly
+ if ($(input).val().isValidHEX()) this.hex = $(input).val();
+ else {
+ alert("Error!");
+ return;
+ }
+ }
+
+ this.r = HEXtoRGB(this.hex).r;
+ this.g = HEXtoRGB(this.hex).g;
+ this.b = HEXtoRGB(this.hex).b;
+
+ this.h = RGBtoHSV(this.r, this.g, this.b).h;
+ this.s = RGBtoHSV(this.r, this.g, this.b).s;
+ this.v = RGBtoHSV(this.r, this.g, this.b).v;
+
+ this.updateInterface();
+ }
+
+ this.updateInterface = function(){
+
+ let r = $($("#color_picker_rgb input")[0]),
+ g = $($("#color_picker_rgb input")[1]),
+ b = $($("#color_picker_rgb input")[2]),
+ h = $($("#color_picker_hsv input")[0]),
+ s = $($("#color_picker_hsv input")[1]),
+ v = $($("#color_picker_hsv input")[2]),
+ hex = $("#color_picker_hex"),
+ bgColor;
+
+ r.val(round(this.r));
+ g.val(round(this.g));
+ b.val(round(this.b));
+ h.val(round(this.h));
+ s.val(round(this.s));
+ v.val(round(this.v));
+ bgColor = color(this.r, 0, 0);
+ r.css({
+ "background-color": bgColor.toString(),
+ "color": fontColor(bgColor)
+ });
+ bgColor = color(0, this.g, 0);
+ g.css({
+ "background-color": bgColor.toString(),
+ "color": fontColor(bgColor)
+ });
+ bgColor = color(0, 0, this.b);
+ b.css({
+ "background-color": bgColor.toString(),
+ "color": fontColor(bgColor)
+ });
+ colorMode(HSL);
+ bgColor = color(this.h, 100, 50);
+ h.css({
+ "background-color": bgColor.toString(),
+ "color": fontColor(bgColor)
+ });
+ bgColor = color(this.h, this.s, 100 - this.s / 2);
+ s.css({
+ "background-color": bgColor.toString(),
+ "color": fontColor(bgColor)
+ });
+ bgColor = color(this.h, 100, this.v / 2);
+ v.css({
+ "background-color": bgColor.toString(),
+ "color": fontColor(bgColor)
+ });
+ colorMode(RGB);
+ hex.val(this.hex);
+ hex.css({
+ "background-color": this.hex,
+ "color": fontColor(color(this.hex))
+ });
+
+
+ let sRGB = HSVtoRGB(this.h, 100, 100);
+ let saturationBackground = "linear-gradient(to right, #FFF 0%, rgb("
+ + sRGB.r + ","
+ + sRGB.g + ","
+ + sRGB.b + ") 100%)";
+ $("#hue_picker").css("top", (1 - this.h / 360) * $("#hue").height());
+ $("#sb_picker").css({
+ "left": this.s / 100 * $("#saturation").width() - 8,
+ "top": (1 - this.v / 100) * $("#value").height() - 8
+ });
+ $("#saturation").css("background", saturationBackground);
+
+ }
+
+ this.mousePressed = function(){
+ let x = winMouseX - $("#saturation").offset().left;
+ let y = winMouseY - $("#value").offset().top;
+ if (x > 0 && x < $("#saturation").width() && y > 0 && y < $("#value").height()){
+ this.movingObject = "sb";
+ }
+ if (x > $("#saturation").width() + 6 && x < $("#saturation").width() + 6 + $("#hue").width() && y > 0 && y < $("#hue").height()){
+ this.movingObject = "hue";
+ }
+ this.mouseDragged();
+ }
+
+ this.mouseDragged = function(){
+ if (this.movingObject == "hue"){
+ let objH = $("#hue");
+ let picker = $("#hue_picker");
+ let h = winMouseY - objH.offset().top;
+ if (h > 0 && h < objH.height()){
+ picker.css("top", h - 1);
+ } else if (h > objH.height()){
+ picker.css("top", objH.height() - 1);
+ } else if (h < 0){
+ picker.css("top", -1);
+ }
+ }
+
+ if (this.movingObject == "sb"){
+ let objS = $("#saturation");
+ let objV = $("#value");
+ let picker = $("#sb_picker");
+ let s = winMouseX - objS.offset().left;
+ let v = winMouseY - objV.offset().top;
+ if (s > 0 && s < objS.width()){
+ picker.css("left", s - 8);
+ } else if (s < 0){
+ picker.css("left", -8);
+ } else if (s < objS.width()){
+ picker.css("left", objS.width() - 8);
+ }
+ if (v > 0 && v < objV.height()){
+ picker.css("top", v - 8);
+ } else if (v < 0){
+ picker.css("top", -8);
+ } else if (v > objV.height()){
+ picker.css("top", objV.height() - 8);
+ }
+ }
+
+ this.updateFromGraphical();
+ }
+
+ this.mouseReleased = function(){
+ this.movingObject = "";
+ }
+
+ this.getColor = function(){
+ return this.hex;
+ }
+}
+
+function fontColor(color){
+ //https://www.nbdtech.com/Blog/archive/2008/04/27/Calculating-the-Perceived-Brightness-of-a-Color.aspx
+ let o = (red(color) * 299 + green(color) * 587 + blue(color) * 114) / 1000;
+ return (o > 125) ? "#000" : "#CCC";
+}
+
+//www.stackoverflow.com -->
+function RGBtoHEX(r, g, b) {
+ let rgb = b | (g << 8) | (r << 16);
+ return '#' + (0x1000000 + rgb).toString(16).slice(1);
+}
+
+function HEXtoRGB(hex) {
+ let shorthandRegex = /^#?([a-fA-F\d])([a-fA-F\d])([a-fA-F\d])$/i;
+ hex = hex.replace(shorthandRegex, function(m, r, g, b) {
+ return r + r + g + g + b + b;
+ });
+ let result = /^#?([a-fA-F\d]{2})([a-fA-F\d]{2})([a-fA-F\d]{2})$/i.exec(hex);
+ return result ? {
+ r: parseInt(result[1], 16),
+ g: parseInt(result[2], 16),
+ b: parseInt(result[3], 16)
+ } : null;
+}
+
+function HSVtoRGB(h, s, v) {
+ let r, g, b, i, f, p, q, t;
+ if (arguments.length === 1) {
+ s = h.s, v = h.v, h = h.h;
+ }
+ h /= 360;
+ s /= 100;
+ v /= 100;
+ i = Math.floor(h * 6);
+ f = h * 6 - i;
+ p = v * (1 - s);
+ q = v * (1 - f * s);
+ t = v * (1 - (1 - f) * s);
+ switch (i % 6) {
+ case 0: r = v, g = t, b = p; break;
+ case 1: r = q, g = v, b = p; break;
+ case 2: r = p, g = v, b = t; break;
+ case 3: r = p, g = q, b = v; break;
+ case 4: r = t, g = p, b = v; break;
+ case 5: r = v, g = p, b = q; break;
+ }
+ return {
+ r: r * 255,
+ g: g * 255,
+ b: b * 255
+ };
+}
+
+function RGBtoHSV(r, g, b) {
+ if (arguments.length === 1) {
+ g = r.g, b = r.b, r = r.r;
+ }
+ let max = Math.max(r, g, b), min = Math.min(r, g, b),
+ d = max - min,
+ h,
+ s = (max === 0 ? 0 : d / max),
+ v = max / 255;
+
+ switch (max) {
+ case min: h = 0; break;
+ case r: h = (g - b) + d * (g < b ? 6: 0); h /= 6 * d; break;
+ case g: h = (b - r) + d * 2; h /= 6 * d; break;
+ case b: h = (r - g) + d * 4; h /= 6 * d; break;
+ }
+
+ return {
+ h: h * 360,
+ s: s * 100,
+ v: v * 100
+ };
+}
+
+
+
+
+function ranBool(chance){
+ if (!chance) chance = 2;
+ return Math.floor(Math.random() * chance + 1) == chance ? true : false;
+}
\ No newline at end of file
diff --git a/public/data/scripts/lib/benjo_library.min.js b/public/data/scripts/lib/benjo_library.min.js
new file mode 100644
index 0000000..ade6468
--- /dev/null
+++ b/public/data/scripts/lib/benjo_library.min.js
@@ -0,0 +1 @@
+let TOP=1,RIGHT=2,BOTTOM=3,LEFT=4,TOP_RIGHT=5,BOTTOM_RIGHT=6,BOTTOM_LEFT=7,TOP_LEFT=8;function collisionDetection(a,e){let j=strokePadding;if(null==j&&(j=0),a.isEllipse&&e.isRectangle){let k=a,l=e;for(let n=0;n";
+ for (let prop in credits[0]){
+ table += " ";
+
+ for (let c of credits){
+ let section = "" + prop.capitalize() + " ";
+ }
+ table += "";
+ for (let prop in c){
+ let link = {open: "", close: ""};
+ if (prop === "link"){
+ link.open = "";
+ link.close = "";
+ }
+ section += " ";
+ table += section;
+ }
+ table += "" + link.open + c[prop] + link.close + " ";
+ }
+ section += "
Oh no, you fell out of the world!
", + "styles": { + "border-color": "rgb(160, 30, 30)", + "height": "auto" + }, + "buttons": [ + { + "text": "Restart", + "styles": { + "background-color": "rgb(160, 60, 60)" + }, + "onclick": "game.restart();" + } + ] + + }, + "newGame": { + "html": "Are you sure you wanna start a new one?
", + "styles": { + "border-color": "rgb(70, 70, 20)", + "height": "auto" + }, + "buttons": [ + { + "text": "New Game", + "styles": { + "background-color": "rgb(60, 160, 60)" + }, + "onclick": "loadNewGame();" + }, + { + "text": "Cancel", + "styles": { + "background-color": "rgb(160, 60, 60)" + }, + "onclick": "game.resume();" + } + ] + }, + "credits": { + "html": "", + "styles": { + "border-color": "rgb(0, 37, 160)", + "background-color": "rgb(83, 61, 255)", + "height": "auto" + }, + "buttons": [ + { + "text": "Continue", + "styles": { + "background-color": "rgb(60, 160, 60)" + }, + "onclick": "game.resume()" + } + ] + } + }, + + "audio": { + "sound": { + "won": [ + "data/audio/sound/cheer0.mp3", + "data/audio/sound/cheer1.wav", + "data/audio/sound/cheer2.wav", + "data/audio/sound/cheer3.wav" + ], + "lost": [ + "data/audio/sound/boo0.wav", + "data/audio/sound/aww0.wav", + "data/audio/sound/aww1.wav" + ], + "jump": [ + "data/audio/sound/jump.mp3" + ], + "coin": [ + "data/audio/sound/electrical_sweep.mp3" + ] + }, + "music":{ + "game": [ + "data/audio/music/background0.mp3", + "data/audio/music/background1.mp3", + "data/audio/music/background2.mp3", + "data/audio/music/background3.mp3", + "data/audio/music/background4.mp3", + "data/audio/music/background5.mp3", + "data/audio/music/background6.mp3", + "data/audio/music/background7.mp3", + "data/audio/music/background8.mp3" + ] + } + }, + + "values": { + "minBrickWidth": "200", + "maxBrickWidth": "800", + "backgroundMoveScale": "500", + "minWorldSize": "5000", + "maxWorldSize": "10000", + "maxMapSize": "300", + "coinSize": "50", + "coinRarity": "20", + "coinDispoY": "10", + "loadedWaitTime": "1000", + "cursorTimeLimit": "1000", + "menuAnimationTime": "200", + "openerAnimationTime": "200", + "maxLevelCount": "5", + "maxVelocityX": [ + "15", + "12", + "10", + "9", + "8" + ], + "jumpVelocity": [ + "15", + "12", + "10", + "8", + "6" + ] + } +} + diff --git a/public/data/styles/color_picker.css b/public/data/styles/color_picker.css new file mode 100644 index 0000000..a5b510e --- /dev/null +++ b/public/data/styles/color_picker.css @@ -0,0 +1,88 @@ +#color_picker{ + width: 300px; + height: 25%; + margin: 20px; + margin-top: 50px; + border: 5px solid #000; + background-color: #000; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + position: relative; +} +#color_picker_numeric{ + width: 80%; + padding: 5%; + margin: 5%; + background-color: #888; + border-radius: 10px; + overflow: hidden; +} +.color_picker_rgb{ + float: left; + width: 22%; + height: 35px; + font-size: 25px; + color: #000; +} +.color_picker_rgb:nth-child(1){ + margin-right: 10%; + margin-left: 3%; + background-color: #F00; + +} +.color_picker_rgb:nth-child(2){ + background-color: #0F0; +} +.color_picker_rgb:nth-child(3){ + margin-left: 10%; + background-color: #00F; + color: #FFF; +} +#color_picker_hex{ + width: 50%; + height: 30px; + font-size: 25px; + margin: 10% 25% 0 25%; +} +#saturation{ + position: relative; + width: calc(100% - 33px); + height: 100%; + background: linear-gradient(to right, #FFF 0%, #F00 100%); + float: left; + margin-right: 6px; +} +#value { + width: 100%; + height: 100%; + background: linear-gradient(to top, #000 0%, rgba(255,255,255,0) 100%); +} +#sb_picker{ + border: 2px solid; + border-color: #FFF; + position: absolute; + width: 14px; + height: 14px; + border-radius: 10px; + bottom: 50px; + left: 50px; + box-sizing: border-box; + z-index: 10; +} +#hue { + width: 27px; + height: 100%; + position: relative; + float: left; + background: linear-gradient(to bottom, #F00 0%, #F0F 17%, #00F 34%, #0FF 50%, #0F0 67%, #FF0 84%, #F00 100%); +} +#hue_picker { + position: absolute; + background: #000; + border-bottom: 1px solid #000; + top: 0; + width: 27px; + height: 2px; +} \ No newline at end of file diff --git a/public/data/styles/font.ttf b/public/data/styles/font.ttf new file mode 100644 index 0000000..199cf40 Binary files /dev/null and b/public/data/styles/font.ttf differ diff --git a/public/data/styles/range_input.css b/public/data/styles/range_input.css new file mode 100644 index 0000000..1d7369c --- /dev/null +++ b/public/data/styles/range_input.css @@ -0,0 +1,88 @@ +input[type=range] { + -webkit-appearance: none; + margin: 18px 0; + width: 100%; +} +input[type=range]:focus { + outline: none; +} +input[type=range]::-webkit-slider-runnable-track { + width: 100%; + height: 8.4px; + cursor: pointer; + animate: 0.2s; + box-shadow: 1px 1px 1px #000000, 0px 0px 1px #0d0d0d; + background: #3071a9; + border-radius: 1.3px; + border: 0.2px solid #010101; +} +input[type=range]::-webkit-slider-thumb { + box-shadow: 1px 1px 1px #000000, 0px 0px 1px #0d0d0d; + border: 1px solid #000000; + height: 36px; + width: 16px; + border-radius: 3px; + background: #ffffff; + cursor: pointer; + -webkit-appearance: none; + margin-top: -14px; +} +input[type=range]:focus::-webkit-slider-runnable-track { + background: #367ebd; +} +input[type=range]::-moz-range-track { + width: 100%; + height: 8.4px; + cursor: pointer; + animate: 0.2s; + box-shadow: 1px 1px 1px #000000, 0px 0px 1px #0d0d0d; + background: #3071a9; + border-radius: 1.3px; + border: 0.2px solid #010101; +} +input[type=range]::-moz-range-thumb { + box-shadow: 1px 1px 1px #000000, 0px 0px 1px #0d0d0d; + border: 1px solid #000000; + height: 36px; + width: 16px; + border-radius: 3px; + background: #ffffff; + cursor: pointer; +} +input[type=range]::-ms-track { + width: 100%; + height: 8.4px; + cursor: pointer; + animate: 0.2s; + background: transparent; + border-color: transparent; + border-width: 16px 0; + color: transparent; +} +input[type=range]::-ms-fill-lower { + background: #2a6495; + border: 0.2px solid #010101; + border-radius: 2.6px; + box-shadow: 1px 1px 1px #000000, 0px 0px 1px #0d0d0d; +} +input[type=range]::-ms-fill-upper { + background: #3071a9; + border: 0.2px solid #010101; + border-radius: 2.6px; + box-shadow: 1px 1px 1px #000000, 0px 0px 1px #0d0d0d; +} +input[type=range]::-ms-thumb { + box-shadow: 1px 1px 1px #000000, 0px 0px 1px #0d0d0d; + border: 1px solid #000000; + height: 36px; + width: 16px; + border-radius: 3px; + background: #ffffff; + cursor: pointer; +} +input[type=range]:focus::-ms-fill-lower { + background: #3071a9; +} +input[type=range]:focus::-ms-fill-upper { + background: #367ebd; +} \ No newline at end of file diff --git a/public/index.html b/public/index.html new file mode 100644 index 0000000..ceeaa27 --- /dev/null +++ b/public/index.html @@ -0,0 +1,50 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +