commit
5123fb6548
46 changed files with 2940 additions and 0 deletions
@ -0,0 +1 @@ |
|||||||
|
.idea |
@ -0,0 +1,6 @@ |
|||||||
|
{ |
||||||
|
"display_name": "Jump and run", |
||||||
|
"info_text": "Birthday present for Selina ♥", |
||||||
|
"visible": true, |
||||||
|
"tags": ["Game"] |
||||||
|
} |
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
After Width: | Height: | Size: 318 B |
@ -0,0 +1,54 @@ |
|||||||
|
"use strict" |
||||||
|
|
||||||
|
class Background{ |
||||||
|
|
||||||
|
constructor(world){ |
||||||
|
this.yScale = height * 0.4; |
||||||
|
this.backScale = int(values.backgroundMoveScale); |
||||||
|
} |
||||||
|
|
||||||
|
update(){ |
||||||
|
this.viewPort(); |
||||||
|
} |
||||||
|
|
||||||
|
display(){ |
||||||
|
this.show(); |
||||||
|
} |
||||||
|
|
||||||
|
viewPort(){ |
||||||
|
this.mountainPoints = []; |
||||||
|
this.groundPoints = []; |
||||||
|
this.yOff = height / 2 - (viewPort.y / game.world.dim.y - 0.5) * height / 2; |
||||||
|
for (let x = 0; x < width; x++){ |
||||||
|
let y = noise(x / 100 + viewPort.x / this.backScale) - 0.5; |
||||||
|
this.mountainPoints.push({x: x, y: y * this.yScale + this.yOff}); |
||||||
|
this.groundPoints.push({x: x, y: y * this.yScale * 0.1 + this.yOff + this.yScale / 2}); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
show(){ |
||||||
|
|
||||||
|
//Sky
|
||||||
|
background(colors.background.sky); |
||||||
|
|
||||||
|
//Mountains
|
||||||
|
strokeWeight(2); |
||||||
|
stroke(colors.background.mountains.stroke); |
||||||
|
fill(colors.background.mountains.fill) |
||||||
|
beginShape(); |
||||||
|
for (let p of this.mountainPoints) vertex(p.x, p.y); |
||||||
|
vertex(width, height); |
||||||
|
vertex(0, height); |
||||||
|
vertex(0, this.mountainPoints[0].y); |
||||||
|
endShape(); |
||||||
|
|
||||||
|
//Ground
|
||||||
|
fill(colors.background.ground); |
||||||
|
beginShape(); |
||||||
|
for (let p of this.groundPoints) vertex(p.x, p.y); |
||||||
|
vertex(width, height); |
||||||
|
vertex(0, height); |
||||||
|
vertex(0, this.groundPoints[0].y); |
||||||
|
endShape(); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,104 @@ |
|||||||
|
"use strict" |
||||||
|
|
||||||
|
class Brick{ |
||||||
|
|
||||||
|
constructor(x, y, w, h, v){ |
||||||
|
this.pos = createVector(x, y); |
||||||
|
this.vel = createVector(v.x, v.y); |
||||||
|
this.dim = createVector(w, h); |
||||||
|
this.prepareNoise(); |
||||||
|
} |
||||||
|
|
||||||
|
createTrees(){ |
||||||
|
this.trees = []; |
||||||
|
for (let i = 0; i < int(random(3)); i++) this.trees.push(new Tree(this)); |
||||||
|
} |
||||||
|
|
||||||
|
createPlants(){ |
||||||
|
this.grasses = []; |
||||||
|
for (let i = 0; i < int(random(4)); i++) this.grasses.push(new Grass(this, random(this.dim.x))); |
||||||
|
} |
||||||
|
|
||||||
|
createCoins(){ |
||||||
|
let rarity = int(values.coinRarity); |
||||||
|
this.coin = ranBool(rarity) ? new Coin(this) : null; |
||||||
|
} |
||||||
|
|
||||||
|
update(world){ |
||||||
|
if (!game.paused) { |
||||||
|
this.borders(world); |
||||||
|
this.move(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
display(){ |
||||||
|
let thrashHold = 300; |
||||||
|
if (this.pos.x < viewPort.x + width + thrashHold && this.pos.x + this.dim.x + thrashHold > viewPort.x &&
|
||||||
|
this.pos.y < viewPort.y + height + thrashHold && this.pos.y + this.dim.y > viewPort.y - thrashHold){ |
||||||
|
this.show(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
move(){ |
||||||
|
this.pos.add(this.vel); |
||||||
|
} |
||||||
|
|
||||||
|
borders(world){ |
||||||
|
if (this.pos.x > world.pos.x + world.dim.x - this.dim.x
|
||||||
|
|| this.pos.x < world.pos.x){ |
||||||
|
this.vel.x *= -1; |
||||||
|
} |
||||||
|
if (this.pos.y > world.pos.y + world.dim.y - this.dim.y |
||||||
|
|| this.pos.y < world.pos.y){ |
||||||
|
this.vel.y *= -1; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
show(){ |
||||||
|
noStroke(); |
||||||
|
|
||||||
|
//Brown earth
|
||||||
|
fill(colors.brick.earth); |
||||||
|
rect(this.pos.x, this.pos.y + this.dim.y * 0.3, this.dim.x, this.dim.y * 0.7, this.dim.y / 4); |
||||||
|
|
||||||
|
//Green grass ground
|
||||||
|
fill(colors.brick.ground); |
||||||
|
beginShape(); |
||||||
|
for (let x = 0; x < this.dim.x; x += 5){ |
||||||
|
let y = this.pos.y - this.noiseValues[x] * 3; |
||||||
|
vertex(this.pos.x + x, y); |
||||||
|
if (!(x + 5 < this.dim.x)){ |
||||||
|
vertex(this.pos.x + this.dim.x, y); |
||||||
|
break; |
||||||
|
} |
||||||
|
} |
||||||
|
vertex(this.pos.x + this.dim.x, this.pos.y + this.dim.y / 2); |
||||||
|
vertex(this.pos.x, this.pos.y + this.dim.y / 2); |
||||||
|
endShape(); |
||||||
|
|
||||||
|
//Trees and grasses with flowers
|
||||||
|
for (let t of this.trees) t.show(); |
||||||
|
for (let g of this.grasses) g.show(); |
||||||
|
|
||||||
|
//Coin
|
||||||
|
if (this.coin) this.coin.update(); |
||||||
|
} |
||||||
|
|
||||||
|
getHitbox(){ |
||||||
|
let hitbox = { |
||||||
|
pos: {x: this.pos.x, y: this.pos.y}, |
||||||
|
dim: {x: this.dim.x, y: 0}, |
||||||
|
vel: {x: this.vel.x, y: this.vel.y} |
||||||
|
}; |
||||||
|
return hitbox; |
||||||
|
} |
||||||
|
|
||||||
|
//For better performance
|
||||||
|
prepareNoise(){ |
||||||
|
this.noiseValues = []; |
||||||
|
let trashHold = 100; |
||||||
|
for (let x = random(trashHold); x <= int(values.maxBrickWidth) + trashHold; x++){ |
||||||
|
this.noiseValues.push(noise(x)); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,90 @@ |
|||||||
|
"use strict" |
||||||
|
|
||||||
|
class Coin{ |
||||||
|
|
||||||
|
constructor(brick){ |
||||||
|
this.pos = brick.pos; |
||||||
|
this.dispoX = random(brick.dim.x); |
||||||
|
this.brick = brick; |
||||||
|
this.dir = ranBool() ? 1 : -1; |
||||||
|
this.colorSetup(); |
||||||
|
} |
||||||
|
|
||||||
|
update(){ |
||||||
|
this.blink(); |
||||||
|
this.show(); |
||||||
|
this.collision(); |
||||||
|
} |
||||||
|
|
||||||
|
blink(){ |
||||||
|
this.hue += this.dir * sin(frameCount / 10) * 5; |
||||||
|
this.hue = this.hue < 0 ? this.hue + 360 : this.hue; |
||||||
|
this.hue %= 360; |
||||||
|
|
||||||
|
colorMode(HSB); |
||||||
|
let s = this.color.stroke; |
||||||
|
s = color(this.hue, saturation(s), brightness(s)); |
||||||
|
this.color.stroke = s; |
||||||
|
colorMode(RGB); |
||||||
|
} |
||||||
|
|
||||||
|
show(){ |
||||||
|
fill(this.color.fill); |
||||||
|
stroke(this.color.stroke); |
||||||
|
strokeWeight(4); |
||||||
|
strokeJoin(ROUND); |
||||||
|
|
||||||
|
let size = int(values.coinSize), |
||||||
|
dispoY = int(values.coinDispoY); |
||||||
|
|
||||||
|
let p1 = {x: this.pos.x + this.dispoX, y: this.pos.y - dispoY}, |
||||||
|
p2 = {x: this.pos.x + this.dispoX + size / 3, y: this.pos.y - (dispoY + size / 2)}, |
||||||
|
p3 = {x: this.pos.x + this.dispoX, y: this.pos.y - (dispoY + size)}, |
||||||
|
p4 = {x: this.pos.x + this.dispoX - size / 3, y: this.pos.y - (dispoY + size / 2)}; |
||||||
|
|
||||||
|
quad(p1.x, p1.y, p2.x, p2.y, p3.x, p3.y, p4.x, p4.y); |
||||||
|
|
||||||
|
if (debug){ |
||||||
|
let hitbox = this.getHitbox(); |
||||||
|
noFill(); |
||||||
|
stroke(255, 0, 0); |
||||||
|
rect(hitbox.pos.x, hitbox.pos.y, hitbox.dim.x, hitbox.dim.y); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
collision(){ |
||||||
|
if (game.player.touches(this) && hue(game.player.color) != hue(this.color.fill)){ |
||||||
|
game.player.setColor(this.color.fill); |
||||||
|
new Sound(Sound.Coin()).play(); |
||||||
|
this.brick.coin = null; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
colorSetup(){ |
||||||
|
let s = color(colors.brick.coin.stroke), |
||||||
|
f = color(colors.brick.coin.fill); |
||||||
|
this.hue = int(random(360)); |
||||||
|
this.hue = floor(this.hue / 60) * 60; |
||||||
|
|
||||||
|
colorMode(HSB); |
||||||
|
let stroke = color(this.hue, saturation(s), brightness(s)), |
||||||
|
fill = color(this.hue, saturation(f), brightness(f)); |
||||||
|
|
||||||
|
this.color = { |
||||||
|
stroke: stroke, |
||||||
|
fill: fill |
||||||
|
}; |
||||||
|
colorMode(RGB); |
||||||
|
} |
||||||
|
|
||||||
|
getHitbox(){ |
||||||
|
let size = int(values.coinSize), |
||||||
|
dispoY = int(values.coinDispoY); |
||||||
|
let hitbox = { |
||||||
|
pos: {x: this.pos.x + this.dispoX - size / 3, y: this.pos.y - (dispoY + size)}, |
||||||
|
dim: {x: size * 2 / 3, y: size} |
||||||
|
}; |
||||||
|
return hitbox; |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,318 @@ |
|||||||
|
"use strict" |
||||||
|
|
||||||
|
class Game{ |
||||||
|
|
||||||
|
constructor(){} |
||||||
|
|
||||||
|
load(){ |
||||||
|
let minSize = int(values.minWorldSize), |
||||||
|
maxSize = int(values.maxWorldSize); |
||||||
|
let world = {pos: createVector(0, 0), dim: createVector(random(minSize, maxSize), random(minSize, maxSize))}; |
||||||
|
let bricks = []; |
||||||
|
loader = new Loader(Loader.Bar(), "Loading The Game..."); |
||||||
|
this.createBrick(world.pos.x + int(values.maxBrickWidth), bricks, world, 4); |
||||||
|
} |
||||||
|
|
||||||
|
next(num, bricks, world, loadingParts, percentage, partIndex, info, func){ |
||||||
|
setTimeout(function(){ |
||||||
|
let progress = percentage / loadingParts + partIndex / loadingParts; |
||||||
|
loader.updateProgress(progress, info); |
||||||
|
game[func](num, bricks, world, loadingParts); |
||||||
|
}); |
||||||
|
} |
||||||
|
|
||||||
|
createBrick(x, bricks, world, loadingParts){ |
||||||
|
let minBrickWidth = int(values.minBrickWidth), |
||||||
|
maxBrickWidth = int(values.maxBrickWidth), |
||||||
|
maxWorldSize = int(values.maxWorldSize); |
||||||
|
|
||||||
|
if (x < world.pos.x + world.dim.x - maxBrickWidth){ |
||||||
|
let y = random(world.pos.y, world.pos.y + world.dim.y), |
||||||
|
w = random(minBrickWidth, maxBrickWidth), |
||||||
|
h = 30, |
||||||
|
v = { |
||||||
|
x: ranBool() ? random(-4, 4) : 0, |
||||||
|
y: ranBool() ? random(-4, 4) : 0 |
||||||
|
}; |
||||||
|
bricks.push(new Brick(x, y, w, h, v)); |
||||||
|
x += 400000 / world.dim.y; |
||||||
|
let percentage = (x - maxBrickWidth) / (world.pos.x + world.dim.x - maxBrickWidth * 2); |
||||||
|
this.next(x, bricks, world, loadingParts, percentage, 0, "Building Platforms...", "createBrick"); |
||||||
|
} else { |
||||||
|
this.createTrees(0, bricks, world, loadingParts); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
createTrees(index, bricks, world, loadingParts){ |
||||||
|
bricks[index].createTrees(); |
||||||
|
if (bricks[index + 1]){ |
||||||
|
index++; |
||||||
|
let percentage = index / bricks.length; |
||||||
|
this.next(index, bricks, world, loadingParts, percentage, 1, "Planting Trees...", "createTrees"); |
||||||
|
} else { |
||||||
|
this.createPlants(0, bricks, world, loadingParts); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
createPlants(index, bricks, world, loadingParts){ |
||||||
|
bricks[index].createPlants(); |
||||||
|
if (bricks[index + 1]){ |
||||||
|
index++; |
||||||
|
let percentage = index / bricks.length; |
||||||
|
this.next(index, bricks, world, loadingParts, percentage, 2, "Planting Flowers...", "createPlants"); |
||||||
|
} else { |
||||||
|
this.createCoins(0, bricks, world, loadingParts); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
createCoins(index, bricks, world, loadingParts){ |
||||||
|
bricks[index].createCoins(); |
||||||
|
if (bricks[index + 1]){ |
||||||
|
index++; |
||||||
|
let percentage = index / bricks.length; |
||||||
|
this.next(index, bricks, world, loadingParts, percentage, 3, "Hiding Treasures...", "createCoins"); |
||||||
|
} else { |
||||||
|
this.tidyUp(bricks, world); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
tidyUp(bricks, world){ |
||||||
|
let variables = this.createVariables(bricks, world); |
||||||
|
this.applyVariables(variables); |
||||||
|
this.safeStartingConditions(variables); |
||||||
|
resetMusics(); |
||||||
|
loader.updateProgress(1, "Cleaning up..."); |
||||||
|
//setTimeout(function(){loadAudioFiles(audioFilesLoaded)}, 1000); crashes PC :D
|
||||||
|
setTimeout(function(){game.finishLoading();}, int(values.loadedWaitTime)); |
||||||
|
} |
||||||
|
|
||||||
|
createVariables(bricks, world){ |
||||||
|
let maxWorldSize = int(values.maxWorldSize), |
||||||
|
maxMapSize = int(values.maxMapSize); |
||||||
|
let iconMap = new Map(map(world.dim.x, 0, maxWorldSize, 0, maxMapSize), map(world.dim.y, 0, maxWorldSize, 0, maxMapSize)); |
||||||
|
let player = new Player(random(world.pos.x + width, world.pos.x + world.dim.x - width), random(world.pos.y + height, world.pos.y - height + world.dim.y)); |
||||||
|
let goal = new Goal(); |
||||||
|
let background = new Background(world); |
||||||
|
viewPort.x = player.pos.x - width / 2; |
||||||
|
viewPort.y = player.pos.y - height / 2; |
||||||
|
let showHint = true; |
||||||
|
let showMap = true; |
||||||
|
let isWon = false; |
||||||
|
let level = 0; |
||||||
|
let maxLevel = int(values.maxLevelCount); |
||||||
|
|
||||||
|
let variablesObject = { |
||||||
|
world: world, |
||||||
|
bricks: bricks, |
||||||
|
player: player, |
||||||
|
goal: goal, |
||||||
|
iconMap: iconMap, |
||||||
|
background: background, |
||||||
|
showHint: showHint, |
||||||
|
showMap: showMap, |
||||||
|
isWon: isWon, |
||||||
|
level: level, |
||||||
|
maxLevel: maxLevel |
||||||
|
}; |
||||||
|
|
||||||
|
return variablesObject; |
||||||
|
} |
||||||
|
|
||||||
|
applyVariables(variables){ |
||||||
|
for (let property in variables){ |
||||||
|
this[property] = variables[property]; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
safeStartingConditions(v){ |
||||||
|
let sc = {}; |
||||||
|
for (let key in v){ |
||||||
|
if (v[key] instanceof Array){ |
||||||
|
sc[key] = v[key].clone(); |
||||||
|
} else if (v[key] instanceof Player){ |
||||||
|
sc[key] = new Player(v[key].pos.x, v[key].pos.y); |
||||||
|
} else if (v[key] instanceof Goal){ |
||||||
|
sc[key] = new Goal(); |
||||||
|
} |
||||||
|
} |
||||||
|
sc.isWon = false; |
||||||
|
sc.level = 0; |
||||||
|
this.startingConditions = sc; |
||||||
|
} |
||||||
|
|
||||||
|
finishLoading(){ |
||||||
|
loader.destroy(); |
||||||
|
$("#loaderWrapper").hide(); |
||||||
|
if (!menuOpen) toggleMenu($("#menuOpener")); |
||||||
|
this.nextLevel(); |
||||||
|
this.ready = true; |
||||||
|
this.start(); |
||||||
|
updateMenu(); |
||||||
|
} |
||||||
|
|
||||||
|
start(){ |
||||||
|
this.playMusic(); |
||||||
|
this.resume(); |
||||||
|
} |
||||||
|
|
||||||
|
restart(){ |
||||||
|
this.applyVariables(this.startingConditions); |
||||||
|
this.safeStartingConditions(this.startingConditions); |
||||||
|
this.nextLevel(); |
||||||
|
this.resume(); |
||||||
|
} |
||||||
|
|
||||||
|
update(){ |
||||||
|
if (!this.ready || this.paused){ |
||||||
|
return; |
||||||
|
} |
||||||
|
this.background.update(); |
||||||
|
|
||||||
|
for (let b of this.bricks){ |
||||||
|
b.update(this.world); |
||||||
|
} |
||||||
|
this.goal.update(); |
||||||
|
this.player.update(); |
||||||
|
if (!this.paused){ |
||||||
|
this.player.collision(this.bricks, this.world); |
||||||
|
} |
||||||
|
|
||||||
|
if (this.goal.contains(this.player)
|
||||||
|
&& this.goal.brick == this.player.brick
|
||||||
|
&& !this.paused
|
||||||
|
&& !this.isWon){ |
||||||
|
this.goalReached(); |
||||||
|
} |
||||||
|
|
||||||
|
if (this.levelText.isActive()){ |
||||||
|
this.levelText.update(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
display(){ |
||||||
|
if (!this.ready){ |
||||||
|
return; |
||||||
|
} |
||||||
|
checkViewPort(); |
||||||
|
this.background.display(); |
||||||
|
|
||||||
|
translate(-viewPort.x, -viewPort.y); |
||||||
|
|
||||||
|
for (let b of this.bricks){ |
||||||
|
b.display(this.world); |
||||||
|
} |
||||||
|
if (this.showHint){ |
||||||
|
this.goal.hint(this.player, this.world); |
||||||
|
} |
||||||
|
this.goal.display(); |
||||||
|
this.player.display(); |
||||||
|
|
||||||
|
translate(viewPort.x, viewPort.y); |
||||||
|
|
||||||
|
if (this.showMap){ |
||||||
|
this.iconMap.display(this.player, this.goal, this.world); |
||||||
|
} |
||||||
|
|
||||||
|
if (this.levelText.isActive()){ |
||||||
|
this.levelText.display(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
nextLevel(){ |
||||||
|
this.level++; |
||||||
|
this.goal.setBrick(random(this.bricks)); |
||||||
|
this.player.maxVelocityX = int(values.maxVelocityX[this.level - 1]); |
||||||
|
this.player.jumpVelocity = int(values.jumpVelocity[this.level - 1]); |
||||||
|
this.levelText = new LevelText(this.level); |
||||||
|
} |
||||||
|
|
||||||
|
goalReached(){ |
||||||
|
if (this.level < this.maxLevel) this.nextLevel(); |
||||||
|
else this.won(); |
||||||
|
} |
||||||
|
|
||||||
|
won(){ |
||||||
|
this.isWon = true; |
||||||
|
this.pause(); |
||||||
|
new Sound(Sound.Won()).play(); |
||||||
|
new Message(Message.Won()).display(); |
||||||
|
} |
||||||
|
|
||||||
|
lost(){ |
||||||
|
this.pause(); |
||||||
|
new Sound(Sound.Lost()).play(); |
||||||
|
new Message(Message.Lost()).display(); |
||||||
|
} |
||||||
|
|
||||||
|
pause(){ |
||||||
|
this.paused = true; |
||||||
|
this.pauseMusic(); |
||||||
|
} |
||||||
|
resume(){ |
||||||
|
this.paused = false; |
||||||
|
this.unpauseMusic(); |
||||||
|
} |
||||||
|
|
||||||
|
toggleRun(){ |
||||||
|
if (this.paused) this.resume(); |
||||||
|
else this.pause(); |
||||||
|
} |
||||||
|
toggleMap(){ |
||||||
|
this.showMap = !this.showMap; |
||||||
|
} |
||||||
|
toggleHint(){ |
||||||
|
this.showHint = !this.showHint; |
||||||
|
} |
||||||
|
|
||||||
|
getMusics(){ |
||||||
|
return audio.music.game; |
||||||
|
} |
||||||
|
playMusic(){ |
||||||
|
let musics = this.getMusics(); |
||||||
|
this.songIndex = int(random(musics.length)); |
||||||
|
musics[this.songIndex].play(); |
||||||
|
updateVolume(); |
||||||
|
let self = this; |
||||||
|
setTimeout(function(){ |
||||||
|
musics[self.songIndex].onended(function(){ |
||||||
|
if (!musics[self.songIndex].isPaused()) self.playMusic(); |
||||||
|
}); |
||||||
|
}); |
||||||
|
} |
||||||
|
pauseMusic(){ |
||||||
|
let musics = this.getMusics(); |
||||||
|
if (musics[this.songIndex].isPaused()) return; |
||||||
|
musics[this.songIndex].pause(); |
||||||
|
} |
||||||
|
unpauseMusic(){ |
||||||
|
let musics = this.getMusics(); |
||||||
|
if (musics[this.songIndex].isPlaying()) return; |
||||||
|
musics[this.songIndex].play(); |
||||||
|
updateVolume(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
function checkViewPort(){ |
||||||
|
|
||||||
|
//Between 0.5 and 1
|
||||||
|
let limit = 0.5; |
||||||
|
|
||||||
|
let player = game.player, |
||||||
|
world = game.world; |
||||||
|
|
||||||
|
if (player.pos.x > width * limit + viewPort.x && viewPort.x + width < world.pos.x + world.dim.x) viewPort.x = player.pos.x - width * limit; |
||||||
|
if (player.pos.x < width * (1 - limit) + viewPort.x && viewPort.x > world.pos.x) viewPort.x = player.pos.x - width * (1 - limit); |
||||||
|
|
||||||
|
if (player.pos.y > height * limit + viewPort.y && viewPort.y + height < world.pos.y + world.dim.y) viewPort.y = player.pos.y - height * limit; |
||||||
|
if (player.pos.y < height * (1 - limit) + viewPort.y && viewPort.y > world.pos.y) viewPort.y = player.pos.y - height * (1 - limit); |
||||||
|
} |
||||||
|
|
||||||
|
function loadNewGame(){ |
||||||
|
game = new Game(); |
||||||
|
game.load(); |
||||||
|
} |
||||||
|
|
||||||
|
function requestNewGame(){ |
||||||
|
game.pause(); |
||||||
|
new Message(Message.New()).display(); |
||||||
|
} |
@ -0,0 +1,90 @@ |
|||||||
|
"use strict" |
||||||
|
|
||||||
|
class Goal{ |
||||||
|
|
||||||
|
constructor(){ |
||||||
|
this.dim = createVector(200, 375); |
||||||
|
} |
||||||
|
|
||||||
|
setBrick(b){ |
||||||
|
this.pos = createVector(b.pos.x + b.dim.x / 2, b.pos.y); |
||||||
|
this.vel = b.vel; |
||||||
|
this.brick = b; |
||||||
|
} |
||||||
|
|
||||||
|
update(){ |
||||||
|
let b = this.brick; |
||||||
|
this.pos = createVector(b.pos.x + b.dim.x / 2, b.pos.y); |
||||||
|
} |
||||||
|
|
||||||
|
display(){ |
||||||
|
this.show(); |
||||||
|
} |
||||||
|
|
||||||
|
show(){ |
||||||
|
fill(colors.goal.main); |
||||||
|
noStroke(); |
||||||
|
rect(this.pos.x - this.dim.x / 2, this.pos.y - this.dim.y * 0.76, this.dim.x, this.dim.y * 0.76); |
||||||
|
triangle(this.pos.x - this.dim.x / 2, this.pos.y - this.dim.y * 0.75, this.pos.x, this.pos.y - this.dim.y, this.pos.x + this.dim.x / 2, this.pos.y - this.dim.y * 0.75); |
||||||
|
stroke(colors.goal.roof); |
||||||
|
strokeWeight(20); |
||||||
|
line(this.pos.x - this.dim.x / 2 - this.dim.x * 0.1, this.pos.y - this.dim.y * 0.75 + this.dim.x * 0.1, this.pos.x, this.pos.y - this.dim.y); |
||||||
|
line(this.pos.x + this.dim.x / 2 + this.dim.x * 0.1, this.pos.y - this.dim.y * 0.75 + this.dim.x * 0.1, this.pos.x, this.pos.y - this.dim.y); |
||||||
|
fill(colors.goal.hole); |
||||||
|
noStroke(); |
||||||
|
rect(this.pos.x - this.dim.x / 3, this.pos.y - this.dim.y * 0.41, this.dim.x * 2 / 3, this.dim.y * 0.41); |
||||||
|
arc(this.pos.x, this.pos.y - this.dim.y * 0.4, this.dim.x * 2 / 3, this.dim.x * 2 / 3, PI, TWO_PI); |
||||||
|
} |
||||||
|
|
||||||
|
contains(p){ |
||||||
|
if (p.pos.x + p.radius < this.pos.x + this.dim.x / 2 && p.pos.x - p.radius > this.pos.x - this.dim.x / 2 |
||||||
|
&& p.pos.y - p.radius > this.pos.y - this.dim.y && p.pos.y + p.radius <= this.pos.y){ |
||||||
|
return true; |
||||||
|
} |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
hint(player, world){ |
||||||
|
let pl = player.pos.copy(); |
||||||
|
let gl = this.pos.copy(); |
||||||
|
let v = p5.Vector.sub(gl, pl).normalize(); |
||||||
|
let d = dist(pl.x, pl.y, gl.x, gl.y); |
||||||
|
while (true){ |
||||||
|
v.setMag(v.mag() + 1); |
||||||
|
if (pl.x + v.x > viewPort.x + width - 20 |
||||||
|
|| pl.x + v.x < viewPort.x + 20 |
||||||
|
|| pl.y + v.y > viewPort.y + height - 20 |
||||||
|
|| pl.y + v.y < viewPort.y + 20){ |
||||||
|
break; |
||||||
|
} |
||||||
|
} |
||||||
|
if (v.mag() > d) return; |
||||||
|
|
||||||
|
let pos = p5.Vector.add(pl, v); |
||||||
|
|
||||||
|
//green starts at a distance of worldWidth / 3
|
||||||
|
let r = d / (world.dim.x / 3) * 255; |
||||||
|
|
||||||
|
//Arrow
|
||||||
|
push(); |
||||||
|
translate(pos.x, pos.y); |
||||||
|
rotate(v.heading()); |
||||||
|
strokeWeight(3); |
||||||
|
stroke(0); |
||||||
|
fill(r, 255 - r, 0); |
||||||
|
|
||||||
|
//Arrow
|
||||||
|
beginShape(); |
||||||
|
vertex(0, 0); |
||||||
|
vertex(-10, 10); |
||||||
|
vertex(-10, 5); |
||||||
|
vertex(-30, 5); |
||||||
|
vertex(-30, -5); |
||||||
|
vertex(-10, -5); |
||||||
|
vertex(-10, -10); |
||||||
|
vertex(0, 0); |
||||||
|
endShape(); |
||||||
|
pop(); |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,73 @@ |
|||||||
|
"use strict" |
||||||
|
|
||||||
|
function prepareInterface(){ |
||||||
|
globalCursor = { |
||||||
|
isActive: true, |
||||||
|
standStillTime: 0, |
||||||
|
|
||||||
|
//seconds not moving cursor -> it disappears
|
||||||
|
timeLimit: int(values.cursorTimeLimit) / 1000 |
||||||
|
} |
||||||
|
$("#messageWrapper").hide(); |
||||||
|
$("#menuOpener").click(function(){ |
||||||
|
toggleMenu($(this)); |
||||||
|
}); |
||||||
|
$("button, input").click(function(){ |
||||||
|
$(this).blur(); |
||||||
|
updateMenu(); |
||||||
|
}); |
||||||
|
} |
||||||
|
|
||||||
|
function toggleMenu(opener){ |
||||||
|
menuOpen = !menuOpen; |
||||||
|
let menuAnimationTime = int(values.menuAnimationTime), |
||||||
|
openerAnimationTime = int(values.openerAnimationTime); |
||||||
|
let menuLeft; |
||||||
|
if ($("#menu").css("left") == "0px") menuLeft = -$("#menu").outerWidth(); |
||||||
|
else menuLeft = 0; |
||||||
|
let menuBorder = abs(menuLeft); |
||||||
|
opener.animate({"left": menuBorder - opener.outerWidth()}, openerAnimationTime, function(){ |
||||||
|
opener.hide(); |
||||||
|
$("#menu").show(); |
||||||
|
$("#menu").animate({"left": menuLeft}, menuAnimationTime, function(){ |
||||||
|
menuBorder = int($(this).css("left").substring(0, $(this).css("left").length - 2)) + $(this).outerWidth(); |
||||||
|
opener.show(); |
||||||
|
opener.css("left", menuBorder - opener.outerWidth()); |
||||||
|
opener.animate({"left": menuBorder}, openerAnimationTime, function(){ |
||||||
|
//Animation ended successfully
|
||||||
|
}); |
||||||
|
}); |
||||||
|
}); |
||||||
|
} |
||||||
|
|
||||||
|
function toggleFullscreen(htmlElement){ |
||||||
|
let fs = fullscreen(); |
||||||
|
fullscreen(!fs); |
||||||
|
$(htmlElement).html(fs ? "Fullscreen: Off" : "Fullscreen: On"); |
||||||
|
} |
||||||
|
|
||||||
|
function checkCursor(){ |
||||||
|
globalCursor.standStillTime += 1 / frameRate(); |
||||||
|
if (globalCursor.isActive && globalCursor.standStillTime > globalCursor.timeLimit){ |
||||||
|
globalCursor.isActive = false; |
||||||
|
noCursor(); |
||||||
|
} |
||||||
|
if (!globalCursor.isActive && globalCursor.standStillTime < globalCursor.timeLimit){ |
||||||
|
globalCursor.isActive = true; |
||||||
|
cursor(ARROW); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
function updateMenu(){ |
||||||
|
let val = [ |
||||||
|
["run", game.paused ? "Resume" : "Pause"], |
||||||
|
["restart", "Restart"], |
||||||
|
["new", "New Game"], |
||||||
|
["map", game.showMap ? "Map: On" : "Map: Off"], |
||||||
|
["hint", game.showHint ? "Hint: On" : "Hint: Off"], |
||||||
|
["sound", audioOptions.sound ? "Sound: On" : "Sound: Off"], |
||||||
|
["music", audioOptions.music ? "Music: On" : "Music: Off"] |
||||||
|
]; |
||||||
|
|
||||||
|
for (let v of val) $("#" + v[0]).html(v[1]); |
||||||
|
} |
@ -0,0 +1,39 @@ |
|||||||
|
class LevelText{ |
||||||
|
|
||||||
|
constructor(level){ |
||||||
|
this.text = "Level " + level; |
||||||
|
this.pos = createVector(width / 2, height - 50); |
||||||
|
this.vel = createVector(0, -0.1); |
||||||
|
this.acc = createVector(0, -5); |
||||||
|
this.dim = createVector(textWidth(this.text), 50); |
||||||
|
} |
||||||
|
|
||||||
|
isActive(){ |
||||||
|
return this.pos.y > -this.dim.y; |
||||||
|
} |
||||||
|
|
||||||
|
display(){ |
||||||
|
push(); |
||||||
|
textSize(this.dim.y); |
||||||
|
fill(255, 0, 0); |
||||||
|
stroke(0); |
||||||
|
strokeWeight(5); |
||||||
|
textAlign(CENTER); |
||||||
|
translate(this.pos.x, this.pos.y); |
||||||
|
scale(2, 2 - (this.vel.y / 50)); |
||||||
|
text(this.text, 0, 0); |
||||||
|
pop(); |
||||||
|
} |
||||||
|
|
||||||
|
update(){ |
||||||
|
this.vel.add(this.acc); |
||||||
|
this.pos.add(this.vel); |
||||||
|
if (this.pos.y < height / 2 && this.acc.y != 8 && this.acc.y != -0.25){ |
||||||
|
this.acc.y = 8; |
||||||
|
} |
||||||
|
if (this.vel.y > 0){ |
||||||
|
this.acc.y = -0.25; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,179 @@ |
|||||||
|
"use strict" |
||||||
|
|
||||||
|
class Loader{ |
||||||
|
|
||||||
|
constructor(type, title, loadedCallback){ |
||||||
|
this.type = type; |
||||||
|
this.title = title; |
||||||
|
this.loadedCallback = loadedCallback; |
||||||
|
this.spinnerAngle = 0; |
||||||
|
$("#menu, #menuOpener").hide(); |
||||||
|
} |
||||||
|
|
||||||
|
static Bar(){ |
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
||||||
|
static Circle(){ |
||||||
|
return 1; |
||||||
|
} |
||||||
|
|
||||||
|
updateProgress(progress, infoText){ |
||||||
|
this.progress = progress > 1 ? 1 : progress; |
||||||
|
this.radianAngle = progress * TWO_PI; |
||||||
|
this.strokeWidth = progress * 8 + 2; |
||||||
|
this.infoText = infoText; |
||||||
|
} |
||||||
|
|
||||||
|
update(){ |
||||||
|
this.display(this.getColors()); |
||||||
|
this.spinnerAngle += PI / 16; |
||||||
|
this.spinnerAngle %= TWO_PI; |
||||||
|
if (this.progress === 1 && this.loadedCallback){ |
||||||
|
this.loadedCallback(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
display(c){ |
||||||
|
background(c.background); |
||||||
|
switch (this.type){ |
||||||
|
case Loader.Bar(): |
||||||
|
this.bar(c); |
||||||
|
break; |
||||||
|
case Loader.Circle(): |
||||||
|
this.circle(c); |
||||||
|
break; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
bar(c){ |
||||||
|
let w = width * 0.6, |
||||||
|
h = 30; |
||||||
|
let x = (width - w) / 2, |
||||||
|
y = (height - h) / 2; |
||||||
|
|
||||||
|
this.displayBar(x, y, w, h, c); |
||||||
|
|
||||||
|
this.displaySpinner(width / 2, height * 3 / 4, 30, c.spinner); |
||||||
|
|
||||||
|
fill(c.text.fill); |
||||||
|
stroke(c.text.stroke); |
||||||
|
strokeWeight(5); |
||||||
|
textAlign(CENTER, CENTER); |
||||||
|
|
||||||
|
textSize(height / 32); |
||||||
|
text(str(this.title), width / 2, height / 8); |
||||||
|
|
||||||
|
strokeWeight(2); |
||||||
|
textSize(h / 2); |
||||||
|
text(str(this.infoText), width / 2, y - h * 1.5); |
||||||
|
|
||||||
|
strokeWeight(5); |
||||||
|
stroke(c.progress); |
||||||
|
textSize(height / 16); |
||||||
|
text(int(this.progress * 100) + "%", width / 2, height * 5 / 8); |
||||||
|
} |
||||||
|
|
||||||
|
circle(c){ |
||||||
|
let size = min(width, height) / 2; |
||||||
|
size = size < 100 ? 100 : size; |
||||||
|
let posX = width / 2; |
||||||
|
let posY = height / 2; |
||||||
|
|
||||||
|
this.displayCircle(posX, posY, size, c); |
||||||
|
|
||||||
|
this.displaySpinner(posX, height * 7 / 8, 30, c.spinner); |
||||||
|
|
||||||
|
fill(c.text.fill); |
||||||
|
stroke(c.text.stroke); |
||||||
|
strokeWeight(5); |
||||||
|
|
||||||
|
textSize(height / 32); |
||||||
|
text(this.title, posX, height / 8); |
||||||
|
|
||||||
|
strokeWeight(2); |
||||||
|
textSize(15); |
||||||
|
text(str(this.infoText), width / 2, posY + size / 2 + 30); |
||||||
|
|
||||||
|
stroke(c.progress); |
||||||
|
strokeWeight(5); |
||||||
|
textSize(height / 16); |
||||||
|
text(str(int(this.progress * 100)) + "%", posX, posY); |
||||||
|
} |
||||||
|
|
||||||
|
displayBar(x, y, w, h, c){ |
||||||
|
noFill(); |
||||||
|
stroke(0); |
||||||
|
strokeWeight(5); |
||||||
|
rect(x, y, w, h, h / 4); |
||||||
|
|
||||||
|
w -= (1 - this.progress) * w; |
||||||
|
|
||||||
|
noStroke(); |
||||||
|
fill(c.progress); |
||||||
|
rect(x + 1, y + 1, w - 2 < 0 ? w : w - 2, h - 2, h / 4); |
||||||
|
} |
||||||
|
|
||||||
|
displayCircle(posX, posY, size, c){ |
||||||
|
noFill(); |
||||||
|
for (let i = 0; i < 3; i++){ |
||||||
|
stroke(i == 1 ? c.progress: 0); |
||||||
|
strokeWeight(i == 1 ? 5 : 2); |
||||||
|
if (this.radianAngle < TWO_PI && i == 1){ |
||||||
|
arc(posX, posY, size, size, -HALF_PI, this.radianAngle - HALF_PI); |
||||||
|
} else { |
||||||
|
ellipse(posX, posY, size + (i - 1) * 10); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
displaySpinner(x, y, r, c){ |
||||||
|
let c2 = c; |
||||||
|
colorMode(HSB); |
||||||
|
let c1 = color(hue(c2), saturation(c2), brightness(c2) / 5); |
||||||
|
colorMode(RGB); |
||||||
|
let length = PI + HALF_PI; |
||||||
|
for (let i = this.spinnerAngle; i < this.spinnerAngle + length; i += PI / 16){ |
||||||
|
strokeWeight((i - this.spinnerAngle) / length * 10); |
||||||
|
//stroke(lerpColor(c1, c2, (i - this.spinnerAngle) / length));
|
||||||
|
stroke(c2); |
||||||
|
let x1 = sin(i) * r + x, |
||||||
|
y1 = cos(i) * r + y, |
||||||
|
x2 = sin(i + PI / 16) * r + x, |
||||||
|
y2 = cos(i + PI / 16) * r + y; |
||||||
|
line(x1, y1, x2, y2); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
getColors(){ |
||||||
|
return { |
||||||
|
background: color(colors.loader.background), |
||||||
|
progress: color(colors.loader.finished), |
||||||
|
spinner: color(colors.loader.spinner), |
||||||
|
text: { |
||||||
|
fill: color(colors.loader.text.fill), |
||||||
|
stroke: color(colors.loader.text.stroke) |
||||||
|
}, |
||||||
|
}; |
||||||
|
} |
||||||
|
|
||||||
|
destroy(){ |
||||||
|
$("#loader").html(""); |
||||||
|
$("#menu, #menuOpener").show(); |
||||||
|
loader = null; |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
function drawGradient(x, y, w, h, c1, c2, r){ |
||||||
|
strokeWeight(1); |
||||||
|
for (let i = x; i <= x + w; i++){ |
||||||
|
let inter = map(i, x, x + w, 0, 1); |
||||||
|
let c = lerpColor(c1, c2, inter); |
||||||
|
let b = r - pow(r * r - (i - x - r) * (i - x - r), 0.5); |
||||||
|
b = (i - x > r && i < x + w - r) ? 0 : b; |
||||||
|
b = i > x + w - r ? r - pow(r * r - (i - x - w + r) * (i - x - w + r), 0.5) : b; |
||||||
|
stroke(c); |
||||||
|
line(i, y + b + 1, i, y + h - b - 2); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,46 @@ |
|||||||
|
"use strict" |
||||||
|
|
||||||
|
class Map{ |
||||||
|
|
||||||
|
constructor(w, h){ |
||||||
|
let x = width - w - 20; |
||||||
|
let y = height - h - 20; |
||||||
|
this.pos = createVector(x, y); |
||||||
|
this.dim = createVector(w, h); |
||||||
|
this.bricks = []; |
||||||
|
} |
||||||
|
|
||||||
|
display(player, goal, world){ |
||||||
|
this.show(player, goal, world); |
||||||
|
} |
||||||
|
|
||||||
|
show(player, goal, world){ |
||||||
|
let x = width - this.dim.x - 20; |
||||||
|
let y = height - this.dim.y - 20; |
||||||
|
this.pos = createVector(x, y); |
||||||
|
|
||||||
|
fill(colors.map.background.fill); |
||||||
|
stroke(colors.map.background.stroke); |
||||||
|
strokeWeight(10); |
||||||
|
rect(this.pos.x, this.pos.y, this.dim.x, this.dim.y, this.dim.x * 0.05); |
||||||
|
|
||||||
|
let goalX = map(goal.pos.x, 0, world.dim.x, this.pos.x + 10, this.pos.x + this.dim.x - 10), |
||||||
|
goalY = map(goal.pos.y, 0, world.dim.y, this.pos.y + 10, this.pos.y + this.dim.y - 10); |
||||||
|
stroke(colors.goal.main); |
||||||
|
point(goalX, goalY); |
||||||
|
|
||||||
|
let playerX = map(player.pos.x, 0, world.dim.x, this.pos.x + 10, this.pos.x + this.dim.x - 10), |
||||||
|
playerY = map(player.pos.y, 0, world.dim.y, this.pos.y + 10, this.pos.y + this.dim.y - 10); |
||||||
|
stroke(player.color); |
||||||
|
point(playerX, playerY); |
||||||
|
|
||||||
|
let flagH = 30, |
||||||
|
flagW = 15; |
||||||
|
stroke(0); |
||||||
|
strokeWeight(2); |
||||||
|
line(goalX, goalY, goalX, goalY - flagH); |
||||||
|
fill(255, 0, 0); |
||||||
|
rect(goalX, goalY - flagH + 2, flagW, flagH * 0.3); |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,83 @@ |
|||||||
|
"use strict" |
||||||
|
|
||||||
|
class Message{ |
||||||
|
|
||||||
|
constructor(type){ |
||||||
|
let set = settings.messages[type]; |
||||||
|
this.getFullHTML(set); |
||||||
|
} |
||||||
|
|
||||||
|
static Won(){return "won";} |
||||||
|
|
||||||
|
static Lost(){return "lost";} |
||||||
|
|
||||||
|
static New(){return "newGame";} |
||||||
|
|
||||||
|
static Credits(){return "credits";} |
||||||
|
|
||||||
|
getFullHTML(set){ |
||||||
|
let self = this; |
||||||
|
this.html = set.html; |
||||||
|
this.styles = set.styles; |
||||||
|
this.buttons = []; |
||||||
|
for (let b of set.buttons){ |
||||||
|
let htmlButton = $("<button></button>"); |
||||||
|
htmlButton.text(b.text); |
||||||
|
htmlButton.css(b.styles); |
||||||
|
htmlButton.click(function(){self.buttonClicked(b);}); |
||||||
|
this.buttons.push(htmlButton); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
buttonClicked(setButton){ |
||||||
|
eval(setButton.onclick); |
||||||
|
this.destroy(this); |
||||||
|
} |
||||||
|
|
||||||
|
display(){ |
||||||
|
let pane = $("<div></div>"); |
||||||
|
pane.css(this.styles); |
||||||
|
pane.append(this.html); |
||||||
|
for (let b of this.buttons) pane.append(b); |
||||||
|
pane.attr("id", "message"); |
||||||
|
$("#messageWrapper").append(pane); |
||||||
|
$("#messageWrapper").show(); |
||||||
|
} |
||||||
|
|
||||||
|
destroy(obj){ |
||||||
|
$("#messageWrapper").hide(); |
||||||
|
$("#messageWrapper").html(""); |
||||||
|
obj = null; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
function prepareCredits(){ |
||||||
|
credits = credits.credits; |
||||||
|
|
||||||
|
let htmlCredits = $("<div></div>"); |
||||||
|
htmlCredits.attr("id", "creditsTableWrapper"); |
||||||
|
|
||||||
|
let table = "<table id=\"creditsTable\" align=\"center\">"; |
||||||
|
table += "<tr>"; |
||||||
|
for (let prop in credits[0]){ |
||||||
|
table += "<th>" + prop.capitalize() + "</th>"; |
||||||
|
} |
||||||
|
table += "</tr>"; |
||||||
|
|
||||||
|
for (let c of credits){ |
||||||
|
let section = "<tr>"; |
||||||
|
for (let prop in c){ |
||||||
|
let link = {open: "", close: ""}; |
||||||
|
if (prop === "link"){ |
||||||
|
link.open = "<a href=\"" + c[prop] + "\" target=\"_blank\">"; |
||||||
|
link.close = "</a>"; |
||||||
|
} |
||||||
|
section += "<td>" + link.open + c[prop] + link.close + "</td>"; |
||||||
|
} |
||||||
|
section += "</tr>"; |
||||||
|
table += section; |
||||||
|
} |
||||||
|
table += "</table>"; |
||||||
|
htmlCredits.append($(table)); |
||||||
|
settings.messages.credits.html = htmlCredits; |
||||||
|
} |
@ -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 |
||||||
|
}; |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
@ -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); |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -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(); |
||||||
|
} |
@ -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(); |
||||||
|
} |
@ -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; |
||||||
|
} |
File diff suppressed because one or more lines are too long
@ -0,0 +1,62 @@ |
|||||||
|
"use strict" |
||||||
|
|
||||||
|
let debug = false, |
||||||
|
viewPort = {x: 0, y: 0}; |
||||||
|
|
||||||
|
let game, |
||||||
|
menuOpen = false, |
||||||
|
globalCursor, |
||||||
|
loader, |
||||||
|
settings, |
||||||
|
colors, |
||||||
|
values, |
||||||
|
audio, |
||||||
|
font, |
||||||
|
credits; |
||||||
|
|
||||||
|
function preload(){ |
||||||
|
settings = loadJSON("data/settings/Settings.json"); |
||||||
|
font = loadFont("data/styles/font.ttf"); |
||||||
|
credits = loadJSON("data/settings/Credits.json"); |
||||||
|
} |
||||||
|
|
||||||
|
function setup(){ |
||||||
|
canvasSetup(); |
||||||
|
createVariables(); |
||||||
|
loadAudioFiles(audioFilesLoaded); |
||||||
|
prepareInterface(); |
||||||
|
} |
||||||
|
|
||||||
|
function draw(){ |
||||||
|
checkCursor(); |
||||||
|
|
||||||
|
if (loader){ |
||||||
|
loader.update(); |
||||||
|
} |
||||||
|
|
||||||
|
if (game){ |
||||||
|
game.update(); |
||||||
|
game.display(); |
||||||
|
} |
||||||
|
|
||||||
|
if (debug) debugInformation(); |
||||||
|
} |
||||||
|
|
||||||
|
function canvasSetup(){ |
||||||
|
setFrameRate(60); |
||||||
|
let c = createCanvas($("#canvasHolder").width(), $("#canvasHolder").height()); |
||||||
|
c.parent("canvasHolder"); |
||||||
|
textFont(font); |
||||||
|
textAlign(CENTER, CENTER); |
||||||
|
} |
||||||
|
|
||||||
|
function createVariables(){ |
||||||
|
colors = settings.colors; |
||||||
|
values = settings.values; |
||||||
|
prepareCredits(); |
||||||
|
} |
||||||
|
|
||||||
|
function showCredits(){ |
||||||
|
game.pause(); |
||||||
|
new Message(Message.Credits()).display(); |
||||||
|
} |
@ -0,0 +1,86 @@ |
|||||||
|
{ |
||||||
|
"credits": [ |
||||||
|
{ |
||||||
|
"title": "Electrical Sweep", |
||||||
|
"artist": "Sweeper", |
||||||
|
"link": "https://soundbible.com/1795-Electrical-Sweep.html", |
||||||
|
"license": "Public Domain" |
||||||
|
}, |
||||||
|
{ |
||||||
|
"title": "Jump", |
||||||
|
"artist": "snottyboy", |
||||||
|
"link": "https://soundbible.com/1343-Jump.html", |
||||||
|
"license": "Attribution 3.0" |
||||||
|
}, |
||||||
|
{ |
||||||
|
"title": "boo 01", |
||||||
|
"artist": "tim.kahn", |
||||||
|
"link": "https://freesound.org/people/tim.kahn/sounds/336997/", |
||||||
|
"license": "Attribution 3.0" |
||||||
|
}, |
||||||
|
{ |
||||||
|
"title": "Cheer crowd", |
||||||
|
"artist": "Johanneskristjansson", |
||||||
|
"link": "https://freesound.org/people/Johanneskristjansson/sounds/371339/", |
||||||
|
"license": "Attribution 3.0" |
||||||
|
}, |
||||||
|
{ |
||||||
|
"title": "cheer 01", |
||||||
|
"artist": "tim.kahn", |
||||||
|
"link": "https://freesound.org/people/tim.kahn/sounds/337000/", |
||||||
|
"license": "Attribution 3.0" |
||||||
|
}, |
||||||
|
{ |
||||||
|
"title": "awww 01", |
||||||
|
"artist": "tim.kahn", |
||||||
|
"link": "https://freesound.org/people/tim.kahn/sounds/336998/", |
||||||
|
"license": "Attribution 3.0" |
||||||
|
}, |
||||||
|
{ |
||||||
|
"title": "Evolution", |
||||||
|
"artist": "Josh Woodward", |
||||||
|
"link": "https://www.youtube.com/watch?v=RA6XneJGwfQ", |
||||||
|
"license": "Creative Commons - Attribution" |
||||||
|
}, |
||||||
|
{ |
||||||
|
"title": "Home Improvement", |
||||||
|
"artist": "Josh Woodward", |
||||||
|
"link": "https://youtu.be/NMi9Nrm1Mfs?t=2359", |
||||||
|
"license": "Creative Commons - Attribution" |
||||||
|
}, |
||||||
|
{ |
||||||
|
"title": "Incoherent", |
||||||
|
"artist": "Josh Woodward", |
||||||
|
"link": "https://www.youtube.com/watch?v=bxgzIOS-lSs", |
||||||
|
"license": "Creative Commons - Attribution" |
||||||
|
}, |
||||||
|
{ |
||||||
|
"title": "Cherubs", |
||||||
|
"artist": "Josh Woodward", |
||||||
|
"link": "https://www.youtube.com/watch?v=pzUkoJonpro", |
||||||
|
"license": "Creative Commons - Attribution" |
||||||
|
}, |
||||||
|
{ |
||||||
|
"title": "Let it in", |
||||||
|
"artist": "Josh Woodward", |
||||||
|
"link": "https://www.youtube.com/watch?v=M-GylSik2h8", |
||||||
|
"license": "Creative Commons - Attribution" |
||||||
|
}, |
||||||
|
{ |
||||||
|
"title": "California Lullabye", |
||||||
|
"artist": "Josh Woodward", |
||||||
|
"link": "https://www.youtube.com/watch?v=WmWHcyLsqHQ", |
||||||
|
"license": "Creative Commons - Attribution" |
||||||
|
}, |
||||||
|
{ |
||||||
|
"title": "Memorized", |
||||||
|
"artist": "Josh Woodward", |
||||||
|
"link": "https://www.youtube.com/watch?v=2eFKOxfUYwE", |
||||||
|
"license": "Creative Commons - Attribution" |
||||||
|
} |
||||||
|
] |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,215 @@ |
|||||||
|
{ |
||||||
|
"colors": { |
||||||
|
"background": { |
||||||
|
"mountains": { |
||||||
|
"stroke": "rgb(0, 0, 0)", |
||||||
|
"fill": "rgb(60, 60, 60)" |
||||||
|
}, |
||||||
|
"ground": "rgb(40, 100, 30)", |
||||||
|
"sky":"rgb(110, 130, 230)" |
||||||
|
}, |
||||||
|
"map": { |
||||||
|
"background": { |
||||||
|
"stroke": "rgb(0, 0, 0)", |
||||||
|
"fill": "rgb(90, 110, 210)" |
||||||
|
} |
||||||
|
}, |
||||||
|
"player": { |
||||||
|
"body": "hsb(0, 100%, 100%)", |
||||||
|
"eyes": { |
||||||
|
"inner": "rgb(0, 0, 0)" , |
||||||
|
"outer": "rgb(255, 255, 255)" |
||||||
|
} |
||||||
|
}, |
||||||
|
"goal": { |
||||||
|
"main": "#473115", |
||||||
|
"roof": "#32210b", |
||||||
|
"hole": "#14100b" |
||||||
|
}, |
||||||
|
"brick": { |
||||||
|
"earth": "rgb(81, 54, 37)", |
||||||
|
"ground": "rgb(40, 150, 20)", |
||||||
|
"grass": "#2c8300", |
||||||
|
"flower": { |
||||||
|
"center": "hsb(0, 100%, 100%)", |
||||||
|
"petal": "hsb(0, 100%, 100%)", |
||||||
|
"haulm": "#2c8300" |
||||||
|
}, |
||||||
|
"tree": { |
||||||
|
"leaf": "hsb(110, 100%, 50%)", |
||||||
|
"wood": "hsb(32, 100%, 25%)" |
||||||
|
}, |
||||||
|
"coin": { |
||||||
|
"fill": "hsb(0, 100%, 100%)", |
||||||
|
"stroke": "hsb(0, 100%, 100%)" |
||||||
|
} |
||||||
|
}, |
||||||
|
"loader": { |
||||||
|
"background": "#3c598d", |
||||||
|
"start": "hsb(120, 100%, 30%)", |
||||||
|
"finished": "#00d3db", |
||||||
|
"spinner": "#00d3db", |
||||||
|
"text": { |
||||||
|
"fill": "rgb(0, 0, 0)", |
||||||
|
"stroke": "#00d3db" |
||||||
|
} |
||||||
|
} |
||||||
|
}, |
||||||
|
|
||||||
|
"messages": { |
||||||
|
"won": { |
||||||
|
"html": "<p>You won the game! :D Wanna start another?</p>", |
||||||
|
"styles": { |
||||||
|
"border-color": "rgb(30, 120, 30)", |
||||||
|
"height": "auto" |
||||||
|
}, |
||||||
|
"buttons": [ |
||||||
|
{ |
||||||
|
"text": "Restart", |
||||||
|
"styles": { |
||||||
|
"background-color": "rgb(60, 160, 60)" |
||||||
|
}, |
||||||
|
"onclick": "game.restart();" |
||||||
|
}, |
||||||
|
{ |
||||||
|
"text": "New Game", |
||||||
|
"styles": { |
||||||
|
"background-color": "rgb(60, 160, 60)" |
||||||
|
}, |
||||||
|
"onclick": "loadNewGame();" |
||||||
|
}, |
||||||
|
{ |
||||||
|
"text": "Continue", |
||||||
|
"styles": { |
||||||
|
"background-color": "rgb(60, 160, 60)" |
||||||
|
}, |
||||||
|
"onclick": "game.resume()" |
||||||
|
} |
||||||
|
] |
||||||
|
}, |
||||||
|
"lost": { |
||||||
|
"html": "<p>Oh no, you fell out of the world!</p>", |
||||||
|
"styles": { |
||||||
|
"border-color": "rgb(160, 30, 30)", |
||||||
|
"height": "auto" |
||||||
|
}, |
||||||
|
"buttons": [ |
||||||
|
{ |
||||||
|
"text": "Restart", |
||||||
|
"styles": { |
||||||
|
"background-color": "rgb(160, 60, 60)" |
||||||
|
}, |
||||||
|
"onclick": "game.restart();" |
||||||
|
} |
||||||
|
] |
||||||
|
|
||||||
|
}, |
||||||
|
"newGame": { |
||||||
|
"html": "<p>Are you sure you wanna start a new one?</p>", |
||||||
|
"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" |
||||||
|
] |
||||||
|
} |
||||||
|
} |
||||||
|
|
@ -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; |
||||||
|
} |
Binary file not shown.
@ -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; |
||||||
|
} |
@ -0,0 +1,50 @@ |
|||||||
|
<!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://cdnjs.cloudflare.com/ajax/libs/p5.js/0.7.2/addons/p5.dom.min.js" type="text/javascript"></script> |
||||||
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.7.2/addons/p5.sound.min.js" type="text/javascript"></script> |
||||||
|
<script src="https://code.jquery.com/jquery-3.3.1.min.js" type="text/javascript"></script> |
||||||
|
<script src="data/scripts/lib/benjo_library.js" type="text/javascript"></script> |
||||||
|
<script src="data/scripts/events.js" type="text/javascript"></script> |
||||||
|
<script src="data/scripts/sketch.js" type="text/javascript"></script> |
||||||
|
<script src="data/scripts/Game.js" type="text/javascript"></script> |
||||||
|
<script src="data/scripts/Player.js" type="text/javascript"></script> |
||||||
|
<script src="data/scripts/Brick.js" type="text/javascript"></script> |
||||||
|
<script src="data/scripts/Goal.js" type="text/javascript"></script> |
||||||
|
<script src="data/scripts/Plant.js" type="text/javascript"></script> |
||||||
|
<script src="data/scripts/Map.js" type="text/javascript"></script> |
||||||
|
<script src="data/scripts/Background.js" type="text/javascript"></script> |
||||||
|
<script src="data/scripts/Interface.js" type="text/javascript"></script> |
||||||
|
<script src="data/scripts/Message.js" type="text/javascript"></script> |
||||||
|
<script src="data/scripts/Coin.js" type="text/javascript"></script> |
||||||
|
<script src="data/scripts/Sound.js" type="text/javascript"></script> |
||||||
|
<script src="data/scripts/Loader.js" type="text/javascript"></script> |
||||||
|
<script src="data/scripts/LevelText.js" type="text/javascript"></script> |
||||||
|
<link href="styles.css" rel="stylesheet"> |
||||||
|
<link href="data/styles/color_picker.css" rel="stylesheet"> |
||||||
|
<link href="data/styles/range_input.css" rel="stylesheet"> |
||||||
|
<link href="data/images/favicon.ico" rel="icon" type="image/x-icon"> |
||||||
|
<title>Jump and Run</title> |
||||||
|
</head> |
||||||
|
<body> |
||||||
|
<div id="p5_loading"></div> |
||||||
|
<div id="canvasHolder"></div> |
||||||
|
<div id="messageWrapper" style="display: none"></div> |
||||||
|
<div id="menuOpener"></div> |
||||||
|
<div id="menu"> |
||||||
|
<button id="run" onclick="game.toggleRun();"></button> |
||||||
|
<button id="restart" onclick="game.restart();"></button> |
||||||
|
<button id="new" onclick="requestNewGame();"></button> |
||||||
|
<button id="map" onclick="game.toggleMap();"></button> |
||||||
|
<button id="hint" onclick="game.toggleHint();"></button> |
||||||
|
<button id="fs" onclick="toggleFullscreen(this);">Fullscreen: Off</button> |
||||||
|
<input id="soundVolume" max="100" min="0" oninput="updateVolume();" type="range"/> |
||||||
|
<button id="sound" onclick="toggleSounds();"></button> |
||||||
|
<input id="musicVolume" max="100" min="0" oninput="updateVolume();" type="range"/> |
||||||
|
<button id="music" onclick="toggleMusic();"></button> |
||||||
|
<button id="credits" onclick="showCredits();">Credits</button> |
||||||
|
</div> |
||||||
|
</body> |
||||||
|
</html> |
@ -0,0 +1,125 @@ |
|||||||
|
a:link, a:hover, a:active, a:visited{color: #000;} |
||||||
|
|
||||||
|
html, body{margin: 0; padding: 0; height: 100%; width: 100%;} |
||||||
|
|
||||||
|
canvas{margin: 0; padding: 0; border: none; display: block;} |
||||||
|
|
||||||
|
button:hover{cursor: pointer;} |
||||||
|
|
||||||
|
@font-face{ |
||||||
|
font-family: "Rametto"; |
||||||
|
src: url("data/styles/font.ttf"); |
||||||
|
} |
||||||
|
|
||||||
|
*{ |
||||||
|
font-family: "Rametto"; |
||||||
|
} |
||||||
|
|
||||||
|
#canvasHolder{ |
||||||
|
position: absolute; |
||||||
|
width: 100%; |
||||||
|
height: 100%; |
||||||
|
} |
||||||
|
|
||||||
|
#messageWrapper{ |
||||||
|
position: absolute; |
||||||
|
width: 100%; |
||||||
|
height: 100%; |
||||||
|
background-color: rgba(0, 0, 0, 0.8); |
||||||
|
z-index: 1; |
||||||
|
} |
||||||
|
|
||||||
|
#message{ |
||||||
|
position: absolute; |
||||||
|
top: 50%; |
||||||
|
transform: translateY(-50%); |
||||||
|
width: 700px; |
||||||
|
left: 0; |
||||||
|
right: 0; |
||||||
|
margin: auto; |
||||||
|
background-color: rgb(130, 130, 130); |
||||||
|
border: 10px solid; |
||||||
|
border-radius: 50px; |
||||||
|
text-align: center; |
||||||
|
align-content: center; |
||||||
|
} |
||||||
|
|
||||||
|
#message p{ |
||||||
|
margin: 100px; |
||||||
|
font-size: 35px; |
||||||
|
} |
||||||
|
|
||||||
|
#message button{ |
||||||
|
margin: 20px; |
||||||
|
margin-bottom: 50px; |
||||||
|
font-size: 35px; |
||||||
|
border: 5px solid #000; |
||||||
|
border-radius: 10px; |
||||||
|
} |
||||||
|
|
||||||
|
#menuOpener{ |
||||||
|
position: absolute; |
||||||
|
left: 0; |
||||||
|
top: 0; |
||||||
|
bottom: 0; |
||||||
|
margin: auto; |
||||||
|
height: 100px; |
||||||
|
width: 20px; |
||||||
|
background-color: rgb(70, 70, 70); |
||||||
|
border-radius: 0 20px 20px 0; |
||||||
|
border: 3px solid #000; |
||||||
|
border-left: none; |
||||||
|
} |
||||||
|
#menuOpener:hover{ |
||||||
|
background-color: rgb(50, 50, 50); |
||||||
|
cursor: pointer; |
||||||
|
} |
||||||
|
|
||||||
|
#menu{ |
||||||
|
position: absolute; |
||||||
|
top: 50%; |
||||||
|
transform: translateY(-50%); |
||||||
|
left: -450px; |
||||||
|
width: 400px; |
||||||
|
background-color: rgb(90, 90, 90); |
||||||
|
border-radius: 0 20px 20px 0; |
||||||
|
border: 10px solid #000; |
||||||
|
border-left: none; |
||||||
|
padding: 20px; |
||||||
|
text-align: center; |
||||||
|
} |
||||||
|
#menu button{ |
||||||
|
margin-bottom: 20px; |
||||||
|
width: 100%; |
||||||
|
background-color: rgb(160, 200, 100); |
||||||
|
border: 2px solid #000; |
||||||
|
border-radius: 5px; |
||||||
|
font-size: 30px; |
||||||
|
} |
||||||
|
#menu button:last-child{ |
||||||
|
margin-bottom: 0px; |
||||||
|
} |
||||||
|
#menu button:hover{ |
||||||
|
background-color: rgb(80, 190, 40); |
||||||
|
} |
||||||
|
|
||||||
|
#creditsTableWrapper{ |
||||||
|
margin: 20px; |
||||||
|
height: 500px; |
||||||
|
overflow-x: auto; |
||||||
|
overflow-y: auto; |
||||||
|
} |
||||||
|
#creditsTable{ |
||||||
|
border-collapse: collapse; |
||||||
|
margin: 0px auto; |
||||||
|
} |
||||||
|
#creditsTable, #creditsTable th, #creditsTable td{ |
||||||
|
border: 2px solid #0091a3; |
||||||
|
padding: 5px; |
||||||
|
font-size: 20px; |
||||||
|
border-left: none; |
||||||
|
border-right: none; |
||||||
|
} |
||||||
|
#creditsTable th{ |
||||||
|
font-size: 25px; |
||||||
|
} |
After Width: | Height: | Size: 167 KiB |
Loading…
Reference in new issue