commit
f8fc83424e
13 changed files with 1933 additions and 0 deletions
@ -0,0 +1,3 @@ |
||||
.idea |
||||
.env |
||||
node_modules |
@ -0,0 +1,244 @@ |
||||
<html> |
||||
<head> |
||||
<meta charset="utf-8"> |
||||
<script src="/lib/p5/p5.min.js" type="text/javascript"></script> |
||||
<script src="/lib/jquery/jquery.min.js" type="text/javascript"></script> |
||||
<script src="scripts/lib/BenjoLibrary.js" type="text/javascript"></script> |
||||
<script src="scripts/Main.js" type="text/javascript"></script> |
||||
<script src="scripts/sketch.js" type="text/javascript"></script> |
||||
<script src="scripts/Objects.js" type="text/javascript"></script> |
||||
<script src="scripts/Level.js" type="text/javascript"></script> |
||||
<script src="scripts/Switcher.js" type="text/javascript"></script> |
||||
<script src="scripts/WindowEvents.js" type="text/javascript"></script> |
||||
<script src="scripts/Stats.js" type="text/javascript"></script> |
||||
<link href="stylesheets/styles.css" rel="stylesheet"> |
||||
<link href="pictures/favicon.ico" rel="icon" type="image/x-icon"> |
||||
<title>Bricks v3.1 JS</title> |
||||
</head> |
||||
<body> |
||||
<div id="info"> |
||||
<input id="closeButton" onclick="closeInfo(this)" type="button" value="X"> |
||||
<div id="levelSelector"> |
||||
<span id="levelLabel">Level:</span> |
||||
<input id="levelUp" onclick="addLevel(this, 1)" type="button" value="↑"> |
||||
<span id="currentLevel"></span> |
||||
<input id="levelDown" onclick="addLevel(this, -1)" type="button" value="↓"> |
||||
</div> |
||||
<div id="rekordInfo"> |
||||
<center> |
||||
<table> |
||||
<tr> |
||||
<td>Gesamtspielzeit:</td> |
||||
<td id="totalTimePlayed"></td> |
||||
</tr> |
||||
<tr> |
||||
<td>Gesamtanzahl Blöcke:</td> |
||||
<td id="totalBricksDestroyed"></td> |
||||
</tr> |
||||
</table> |
||||
<table> |
||||
<tr> |
||||
<td>Blöcke</td> |
||||
<td>Level</td> |
||||
<td>Rekordzeit</td> |
||||
</tr> |
||||
</table> |
||||
</center> |
||||
</div> |
||||
<div id="controlsInfo"> |
||||
<table> |
||||
<tr> |
||||
<td>Start / Stop:</td> |
||||
<td>SPACE</td> |
||||
</tr> |
||||
<tr> |
||||
<td>Bewegen:</td> |
||||
<td>← →</td> |
||||
</tr> |
||||
<tr> |
||||
<td>Neustart:</td> |
||||
<td>SHIFT + R</td> |
||||
</tr> |
||||
<tr> |
||||
<td>Daten löschen:</td> |
||||
<td>SHIFT + D</td> |
||||
</tr> |
||||
<tr> |
||||
<td>Interface Aus/An:</td> |
||||
<td>ESC / TAB</td> |
||||
</tr> |
||||
<tr> |
||||
<td colspan="2"> |
||||
<input id="infoButton" onclick="openInstructions(); this.blur();" type="button" value="Anleitung"> |
||||
</td> |
||||
</tr> |
||||
</table> |
||||
</div> |
||||
</div> |
||||
<div id="openButton"> |
||||
<input onclick="openInfo(this)" type="button" value=">>>"> |
||||
</div> |
||||
<div id="timeDiv"> |
||||
<span></span> |
||||
</div> |
||||
<div id="instructions"> |
||||
<div id="instructionsWrapper"> |
||||
<h1 id="instructionsHeader">Anleitung Bricks v3.1</h1> |
||||
<div id="instructionsContent"> |
||||
<h2><u>Über das Spiel:</u></h2> |
||||
<p> |
||||
Die Aufgabe in dem Spiel besteht darin, jeden farbigen Block auf dem Spielfeld |
||||
mithilfe des Paddleboards zu zerstören! |
||||
Spezielle Items können helfen...oder nicht :D |
||||
</p> |
||||
<p> |
||||
Alle deine Statistiken und Fortschritte werden in Cookies gespeichert, |
||||
also stelle sicher, dass dein Browser Cookies zulässt und diese nicht |
||||
automatisch löscht. |
||||
</p> |
||||
<p> |
||||
Ein Level ist gewonnen wenn alle farbigen Blöcke zerstört wurden |
||||
und es ist verloren wenn alle Bälle aus dem Spielfeld verschwinden. Aber keine Sorge, |
||||
du hast eine unendliche Anzahl an Zügen :)<br> |
||||
Jedes mal, wenn du ein Level gewinnst, bist du in der Lage das Nächsthöhere zu starten. |
||||
</p> |
||||
<h2><u>Gameplay → Blöcke:</u></h2> |
||||
<p> |
||||
Bis jetzt gibt es 9 verschiedene Arten von Blöcken: |
||||
</p> |
||||
<table id="colors"> |
||||
<tr> |
||||
<td>1</td> |
||||
<td>Dunkelgrün</td> |
||||
<td></td> |
||||
</tr> |
||||
<tr> |
||||
<td>2</td> |
||||
<td>Hellgrün</td> |
||||
<td></td> |
||||
</tr> |
||||
<tr> |
||||
<td>3</td> |
||||
<td>Hellblau</td> |
||||
<td></td> |
||||
</tr> |
||||
<tr> |
||||
<td>4</td> |
||||
<td>Dunkelblau</td> |
||||
<td></td> |
||||
</tr> |
||||
<tr> |
||||
<td>5</td> |
||||
<td>Violett</td> |
||||
<td></td> |
||||
</tr> |
||||
<tr> |
||||
<td>6</td> |
||||
<td>Rot</td> |
||||
<td></td> |
||||
</tr> |
||||
<tr> |
||||
<td>7</td> |
||||
<td>Orange</td> |
||||
<td></td> |
||||
</tr> |
||||
<tr> |
||||
<td>8</td> |
||||
<td>Gelb</td> |
||||
<td></td> |
||||
</tr> |
||||
<tr> |
||||
<td>(9)</td> |
||||
<td>Grau</td> |
||||
<td></td> |
||||
</tr> |
||||
</table> |
||||
<p> |
||||
Jeder Treffer auf einen Block verringert dessen Status um 1, |
||||
bis dieser 0 ist, denn dann ist der Block "tot" und verschwindet. |
||||
<br> |
||||
Die grauen Blöcke mit dem Wert 9 bzw. -1 sind eine Ausnahme, da sie unzerstörbar sind. |
||||
</p> |
||||
<h2><u>Gameplay → Items:</u></h2> |
||||
<p> |
||||
Ab und zu entsteht ein Item, nachdem ein Block zerstört wurde, um |
||||
es aufzusammeln, benutzt du ganz einfach dein Paddleboard - |
||||
Deine Bälle können sie nicht aufsammeln. |
||||
Je höher dein Level, desto häufiger entstehen Items, du wirst sie |
||||
anfangs also nur sehr selten antreffen. |
||||
</p> |
||||
<p> |
||||
Hier sind alle Items gelistet: |
||||
</p> |
||||
<table id="items"> |
||||
<tr> |
||||
<td>Ball</td> |
||||
<td>→ Boost</td> |
||||
<td></td> |
||||
</tr> |
||||
<tr> |
||||
<td>Paddle</td> |
||||
<td>→ Boost</td> |
||||
<td></td> |
||||
</tr> |
||||
<tr> |
||||
<td>Ball</td> |
||||
<td>→ Slow</td> |
||||
<td></td> |
||||
</tr> |
||||
<tr> |
||||
<td>Paddle</td> |
||||
<td>→ Slow</td> |
||||
<td></td> |
||||
</tr> |
||||
<tr> |
||||
<td>Ball</td> |
||||
<td>→ Creator</td> |
||||
<td></td> |
||||
</tr> |
||||
<tr> |
||||
<td>Brick</td> |
||||
<td>→ Repair</td> |
||||
<td></td> |
||||
</tr> |
||||
</table> |
||||
<p> |
||||
Ein Boost gibt dem Objekt einen permanenten Geschwindigkeitsschub, |
||||
während ein Slow das Gegenteil verursacht.<br> |
||||
Der Ball-Creator fügt dem Spiel einen neuen Ball hinzu. |
||||
</p> |
||||
<p> |
||||
Pass auf bei dem Repair-Item, |
||||
denn das macht <b>jeden</b> Block im aktuellen Spiel |
||||
eine Stufe stärker. |
||||
</p> |
||||
<h2><u>Weitere Informationen:</u></h2> |
||||
<p> |
||||
Dieses Spiel wurde nicht fürs Handy programmiert, dort sind viele Bugs anzutreffen. |
||||
Alle nötigen Hotkeys sind links in der Info-Box aufgelistet. |
||||
</p> |
||||
<p> |
||||
Ich benutze für dieses Spiel JavaScript in Kombination mit der Processing |
||||
Library p5 von Lauren McCarthy und der sehr nützlichen auf HTML-DOM arbeitenden Library jQuery. |
||||
</p> |
||||
<h2><u>Changelog:</u></h2> |
||||
<p> |
||||
<b>Version 3.0:</b><br> |
||||
Erste eigene Web-Version von "Bricks" |
||||
</p> |
||||
<p> |
||||
<b>Version 3.1:</b><br> |
||||
Die ersten 5 Level hinzugefügt. Viel Spaß! |
||||
</p> |
||||
<p style="font-size: 20px; margin-top: 50px;"> |
||||
Erstellt und veröffentlicht von BenjoCraeft,<br> |
||||
Gamer, Programmierer |
||||
</p> |
||||
<p style="font-size: 20px; float: right;"> |
||||
Schließe diese Box mit ESC |
||||
</p> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</body> |
||||
</html> |
After Width: | Height: | Size: 318 B |
@ -0,0 +1,379 @@ |
||||
var strokePadding = 3; |
||||
|
||||
function Level(level){ |
||||
|
||||
this.startingPoint = Math.random(); |
||||
|
||||
var table = tableSwitch(level, this); |
||||
|
||||
this.cols = table.cols; |
||||
this.rows = table.rows; |
||||
|
||||
this.setDefault = function(){ |
||||
|
||||
this.isStarted = false; |
||||
this.isPaused = false; |
||||
this.isWon = false; |
||||
this.isLost = false; |
||||
|
||||
this.levelNum = level; |
||||
this.recordTime = getRecordTime(level); |
||||
this.totalBricksDestroyed = getTotalBricksDestroyed(level); |
||||
this.currentTime = 0; |
||||
|
||||
this.brickPadding = (wWidth * 0.0125 + wHeight * 0.0125) / 2; |
||||
this.brickWidth = (wWidth - this.brickPadding * (this.cols + 1)) / this.cols; |
||||
this.brickHeight = (wHeight * 0.75 - this.brickPadding * (this.rows + 1)) / this.rows; |
||||
|
||||
this.bricks = []; |
||||
this.balls = []; |
||||
this.toBeErased = []; |
||||
this.items = []; |
||||
|
||||
this.itemFrequency = floor(levelCount / this.levelNum) * 2; |
||||
|
||||
var p = new Paddle(); |
||||
p.v = 10; |
||||
p.width = wWidth * 0.15; |
||||
p.x = (wWidth - p.width) / 2; |
||||
p.y = wHeight * 0.95; |
||||
p.height = wHeight * 0.025; |
||||
|
||||
var b = new Ball(); |
||||
b.radius = (wWidth * 0.02 + wHeight * 0.02) / 2; |
||||
b.x = p.x + this.startingPoint * p.width; |
||||
b.y = p.y - b.radius - strokePadding; |
||||
var velocityVector = {mag: (wWidth * 0.01 + wHeight * 0.01) / 3, x: 0, y: 0}; |
||||
b.v = velocityVector; |
||||
b.v.x = b.calcVelocityX(p, 0); |
||||
b.v.y = -b.calcVelocityY(); |
||||
|
||||
this.paddle = p; |
||||
this.balls.push(b); |
||||
|
||||
for (var c = 1; c <= this.cols; c++){ |
||||
for (var r = 1; r <= this.rows; r++){ |
||||
var b = new Brick(); |
||||
b.x = this.brickPadding + (c - 1) * (this.brickWidth + this.brickPadding); |
||||
b.y = this.brickPadding + (r - 1) * (this.brickHeight + this.brickPadding); |
||||
b.width = this.brickWidth; |
||||
b.height = this.brickHeight; |
||||
b.state = designSwitch(level, c, r); |
||||
this.bricks.push(b); |
||||
} |
||||
} |
||||
|
||||
//Border Top
|
||||
bt = new Frameborder(0, -50, wWidth, 50);
|
||||
//Border Bottom
|
||||
bb = new Frameborder(0, wHeight, wWidth, 50); |
||||
//Border Left
|
||||
bl = new Frameborder(-50, 0, 50, wHeight); |
||||
//Border Right
|
||||
br = new Frameborder(wWidth, 0, 50, wHeight); |
||||
|
||||
this.frameBorders = [bt, bb, bl, br]; |
||||
} |
||||
|
||||
this.setDefault(); |
||||
|
||||
//Draw everything and check and react to collisions and events
|
||||
this.drawShapes = function(){ |
||||
|
||||
if (this.isWon || this.isLost) return; |
||||
|
||||
//Background gets cleared and bg color is gray
|
||||
clear(); |
||||
background(100); |
||||
|
||||
//Bricks have black stroke and rounded corners
|
||||
stroke(0); |
||||
strokeWeight(strokePadding * 2); |
||||
strokeJoin(ROUND); |
||||
|
||||
//Counter to check if game is won
|
||||
var brickCounter = 0; |
||||
|
||||
//Draw bricks
|
||||
for (var b of this.bricks){ |
||||
|
||||
//If there are bricks "living" counter goes up and game keeps running
|
||||
if (b.state > 0) brickCounter++; |
||||
|
||||
//Select brick color based on his state
|
||||
var fillColor = colorSwitch(b.state); |
||||
if (!fillColor) continue; |
||||
else fill(fillColor); |
||||
|
||||
//Drawing
|
||||
rect(b.x, b.y, b.width, b.height);
|
||||
} |
||||
|
||||
//If no brick is "living" game is won
|
||||
if (brickCounter == 0) this.gameWon(); //Deactivate in TestMode
|
||||
|
||||
//Draw downfalling items
|
||||
for (var i of this.items){ |
||||
var sw = i.radius * 0.2; |
||||
|
||||
fill(0); |
||||
stroke(0); |
||||
strokeWeight(0); |
||||
ellipse(i.x, i.y, i.radius * 2, i.radius * 2); |
||||
strokeWeight(sw); |
||||
|
||||
var rectX = i.x - i.radius * sin(5 * PI / 8) + sw; |
||||
var rectY = i.y + i.radius * cos(5 * PI / 8) + sw; |
||||
var rectW = i.radius * 2 * sin(5 * PI / 8) - sw * 2; |
||||
var rectH = i.radius * 2 * abs(cos(5 * PI / 8)) - sw * 2; |
||||
|
||||
var lineLength = i.radius * 0.5; |
||||
|
||||
switch(i.item){ |
||||
case FastBall: |
||||
fill("#00FF00"); |
||||
strokeWeight(0); |
||||
ellipse(i.x, i.y, i.radius * 1.25, i.radius * 1.25); |
||||
break; |
||||
case FastPaddle: |
||||
fill("#00FF00"); |
||||
strokeWeight(0); |
||||
rect(rectX, rectY, rectW, rectH); |
||||
break; |
||||
case SlowBall: |
||||
fill("#FF0000"); |
||||
strokeWeight(0); |
||||
ellipse(i.x, i.y, i.radius * 1.25, i.radius * 1.25); |
||||
break; |
||||
case SlowPaddle: |
||||
fill("#FF0000"); |
||||
strokeWeight(0); |
||||
rect(rectX, rectY, rectW, rectH); |
||||
break; |
||||
case CreateBall: |
||||
strokeWeight(sw * 2); |
||||
stroke("#00FF00"); |
||||
line(i.x - lineLength, i.y, i.x + lineLength, i.y); |
||||
line(i.x, i.y - lineLength, i.x, i.y + lineLength); |
||||
break; |
||||
case UpgradeBricks: |
||||
strokeWeight(sw * 2); |
||||
stroke("#FF0000"); |
||||
line(i.x - lineLength, i.y, i.x + lineLength, i.y); |
||||
line(i.x, i.y - lineLength, i.x, i.y + lineLength); |
||||
break; |
||||
} |
||||
} |
||||
|
||||
//Balls and paddleboard are black
|
||||
fill(0); |
||||
stroke(0); |
||||
strokeWeight(strokePadding * 2); |
||||
|
||||
var p = this.paddle; |
||||
|
||||
//Draw paddleboard
|
||||
rect(p.x, p.y, p.width, p.height); |
||||
|
||||
//Ball doesnt need rounded corners
|
||||
strokeWeight(0); |
||||
|
||||
//Draw every ball
|
||||
for (var b of this.balls) ellipse(b.x, b.y, b.radius * 2, b.radius * 2); |
||||
|
||||
//Break if game isnt running
|
||||
if (this.isPaused || !this.isStarted) return; |
||||
|
||||
//Check collision and other situations of balls
|
||||
for(var ball1 of this.balls){ |
||||
|
||||
//Check if ball flew away
|
||||
if (ball1.isLost()) this.toBeErased.push(ball1); |
||||
|
||||
//Check collision with frameborders
|
||||
for (var fb of this.frameBorders){ |
||||
var collision = collisionDetection(ball1, fb); |
||||
if (collision.isTouching) performCollision(ball1, fb, collision); |
||||
} |
||||
|
||||
//Check collision with paddleboard
|
||||
var collision = collisionDetection(ball1, p); |
||||
if (collision.isTouching) performCollision(ball1, p, collision); |
||||
|
||||
//Check collision with bricks
|
||||
for (var brick of this.bricks){ |
||||
if (brick.state == 0) continue; |
||||
var collision = collisionDetection(ball1, brick); |
||||
if (collision.isTouching){ |
||||
performCollision(ball1, brick, collision); |
||||
if (brick.state > 0) brick.state--; |
||||
if (floor(random(this.itemFrequency + 1)) % this.itemFrequency == 0 && brick.state == 0) this.createItem(brick); |
||||
if (brick.state == 0) this.totalBricksDestroyed++; |
||||
setTotalBricksDestroyed(level, this.totalBricksDestroyed); |
||||
} |
||||
} |
||||
|
||||
//Check collision with other balls
|
||||
for (var ball2 of this.balls){ |
||||
if (ball1 == ball2) continue; |
||||
var collision = collisionDetection(ball1, ball2); |
||||
if (collision.isTouching) performCollision(ball1, ball2, collision); |
||||
} |
||||
|
||||
//Check if velocites go to NaN due to mistakes
|
||||
if (isNaN(ball1.v.x) || isNaN(ball1.v.y)){ |
||||
ball1.x = p.x + p.width / 2; |
||||
ball1.y = p.y - ball1.radius - strokePadding * 2; |
||||
ball1.v.x = 0; |
||||
ball1.v.y = ball1.v.mag; |
||||
} |
||||
} |
||||
|
||||
//Checkings for items
|
||||
for (var item of this.items){ |
||||
|
||||
var index = this.items.indexOf(item); |
||||
|
||||
//Check collision with paddleboard
|
||||
var collision = collisionDetection(item, p); |
||||
if (collision.isTouching){ |
||||
this.items.splice(index, 1); |
||||
switch (item.item){ |
||||
case FastBall: |
||||
for (var b of this.balls) for (var v in b.v) b.v[v] *= 1.25; |
||||
break; |
||||
case FastPaddle: |
||||
p.v *= 1.25; |
||||
break; |
||||
case SlowBall: |
||||
for (var b of this.balls) for (var v in b.v) b.v[v] *= 0.75; |
||||
break; |
||||
case SlowPaddle: |
||||
p.v *= 0.75; |
||||
break; |
||||
case CreateBall: |
||||
var p = this.paddle; |
||||
var radius = (wWidth * 0.02 + wHeight * 0.02) / 2 * random(0.75, 1.25); |
||||
var x = p.x + p.width / 2; |
||||
var y = p.y - (radius + strokePadding); |
||||
var v = (wWidth * 0.01 + wHeight * 0.01) / 3; |
||||
var vx = 0; |
||||
var vy = v; |
||||
this.createBall(x, y, radius, v, vx, vy); |
||||
break; |
||||
case UpgradeBricks: |
||||
for (var b of this.bricks) if (b.state > 0 && b.state < stateCount - 1) b.state++; |
||||
break; |
||||
} |
||||
} |
||||
if (item.y - item.radius > wHeight){ |
||||
this.items.splice(index, 1); |
||||
break; |
||||
} |
||||
} |
||||
|
||||
|
||||
//Erase all balls out of screen
|
||||
for (var ball of this.toBeErased){ |
||||
var index = this.balls.indexOf(ball); |
||||
this.balls.splice(index, 1); |
||||
} |
||||
this.toBeErased = []; |
||||
|
||||
//Game is lost of no balls are in there
|
||||
if (this.balls.length == 0) this.gameLost(); |
||||
|
||||
//Break if game isnt running once more because previous checkings could've caused a paused game
|
||||
if (!this.isStarted || this.isPaused) return; |
||||
|
||||
//Finally move objects forward
|
||||
for (var b of this.balls) b.move(); |
||||
for (var i of this.items) i.move(); |
||||
p.move(); |
||||
} |
||||
|
||||
|
||||
this.createItem = function(b){ |
||||
|
||||
var item = floor(random(itemCount)) + 1; |
||||
|
||||
var bx = b.x; |
||||
var by = b.y; |
||||
var bw = b.width; |
||||
var bh = b.height; |
||||
|
||||
var x = bx + bw / 2; |
||||
var y = by + bh / 2; |
||||
var radius = (wHeight + wWidth) / 2 * 0.02; |
||||
|
||||
this.items.push(new Item(x, y, radius, random(1, 6), item)); |
||||
} |
||||
|
||||
this.createBall = function(x, y, r, v, vx, vy){ |
||||
|
||||
var b = new Ball(); |
||||
|
||||
b.x = x; |
||||
b.y = y; |
||||
b.radius = r; |
||||
b.v = {mag: v, x: vx, y: vy}; |
||||
|
||||
this.balls.push(b); |
||||
} |
||||
|
||||
|
||||
this.gameLost = function(){ |
||||
this.isPaused = true; |
||||
this.isLost = true; |
||||
if (!infoIsOpen) openInfo(); |
||||
} |
||||
|
||||
this.gameWon = function(){ |
||||
this.isPaused = true; |
||||
this.isWon = true; |
||||
if (this.levelNum - 1 == levelReached){ |
||||
levelReached++; |
||||
setCookie("levelReached", String(levelReached), 10); |
||||
checkLevelButtons(this.levelNum); |
||||
} |
||||
if (this.currentTime < getRecordTime(this.levelNum)){ |
||||
setRecordTime(this.levelNum, this.currentTime); |
||||
} |
||||
if (!infoIsOpen) openInfo(); |
||||
} |
||||
|
||||
this.restart = function(){this.setDefault();} |
||||
|
||||
this.pause = function(paused){ |
||||
if (this.isWon || this.isLost) return; |
||||
if (paused){ |
||||
pauseAnimation(true); |
||||
this.isPaused = true; |
||||
} else { |
||||
pauseAnimation(false); |
||||
this.isPaused = false; |
||||
if (infoIsOpen) closeInfo(); |
||||
} |
||||
} |
||||
this.start = function(){ |
||||
this.isStarted = true; |
||||
if (infoIsOpen) closeInfo(); |
||||
} |
||||
|
||||
this.lastTime = new Date().getTime(); |
||||
|
||||
this.renderTime = function(){ |
||||
var d = new Date().getTime(); |
||||
var passed = d - this.lastTime; |
||||
this.lastTime = d; |
||||
|
||||
if (!this.isPaused && this.isStarted){ |
||||
this.currentTime += passed; |
||||
setTotalTimePlayed(getTotalTimePlayed() + passed); |
||||
} |
||||
|
||||
var timeString = toTimeString(this.currentTime); |
||||
|
||||
$("#timeDiv span").html(timeString); |
||||
} |
||||
} |
@ -0,0 +1,116 @@ |
||||
var currentGame = null; |
||||
var infoIsMoving = false; |
||||
var infoIsOpen = true; |
||||
var instructionsOpen = false; |
||||
var testMode = false; |
||||
var animationDuration = 300; |
||||
|
||||
|
||||
function addLevel(HTMLInputElement, add){ |
||||
HTMLInputElement.blur(); |
||||
var currentLevelNum = parseInt($("#currentLevel").html()); |
||||
var newLevelNum = currentLevelNum + add; |
||||
$("#currentLevel").html(newLevelNum); |
||||
checkLevelButtons(newLevelNum); |
||||
currentGame = new Level(newLevelNum); |
||||
} |
||||
|
||||
function setRekordInfo(){ |
||||
for (var i = 1; i <= levelCount; i++){ |
||||
|
||||
var bricks = getTotalBricksDestroyed(i); |
||||
|
||||
var time = getRecordTime(i); |
||||
time = time == Infinity ? "---" : toTimeString(time); |
||||
|
||||
$("#rekordInfo table:eq(1) tr:eq(" + i + ") td:eq(0)").text(bricks); |
||||
$("#rekordInfo table:eq(1) tr:eq(" + i + ") td:eq(2)").text(time); |
||||
} |
||||
|
||||
var time = toTimeString(getTotalTimePlayed(), true); |
||||
var bricks = getTotalBricksDestroyedGlobal(); |
||||
|
||||
$("#totalTimePlayed").text(time); |
||||
$("#totalBricksDestroyed").text(bricks); |
||||
} |
||||
|
||||
function checkLevelButtons(level) { |
||||
$("#levelUp").removeAttr("disabled"); |
||||
$("#levelUp").css("cursor", "pointer"); |
||||
$("#levelDown").removeAttr("disabled"); |
||||
$("#levelDown").css("cursor", "pointer"); |
||||
if (level == levelCount || level == levelReached + 1){ |
||||
$("#levelUp").attr("disabled", "disabled"); |
||||
$("#levelUp").css("cursor", "auto"); |
||||
} |
||||
if (level == 1){ |
||||
$("#levelDown").attr("disabled", "disabled"); |
||||
$("#levelDown").css("cursor", "auto"); |
||||
} |
||||
} |
||||
|
||||
function setInfoStyles(){ |
||||
$("#levelLabel, #currentLevel").css("font-size", String($("#levelSelector").outerHeight() * 0.25) + "px"); |
||||
$("#levelUp, #levelDown").css("font-size", String($("#levelSelector").outerHeight() * 0.2) + "px"); |
||||
$("#closeButton").css({ |
||||
"width": String($("#closeButton").outerHeight()) + "px", |
||||
"font-size": String($("#closeButton").outerHeight() * 0.6) + "px" |
||||
}); |
||||
$("#controlsInfo table tr td").css("font-size", String($("#controlsInfo table tr td").innerHeight() * 0.3) + "px"); |
||||
} |
||||
|
||||
function closeInfo(HTMLInputElement){ |
||||
try {HTMLInputElement.blur();}catch(e){} |
||||
if (infoIsMoving) return; |
||||
infoIsMoving = true; |
||||
$("#info *").hide(); |
||||
$("#info").animate({ |
||||
width: 0 |
||||
}, animationDuration, function(){ |
||||
$("#openButton").show(); |
||||
$("#openButton").animate({ |
||||
width: 60 |
||||
}, animationDuration, function(){ |
||||
infoIsMoving = false; |
||||
infoIsOpen = false; |
||||
}); |
||||
}); |
||||
} |
||||
|
||||
function openInfo(HTMLInputElement){ |
||||
try {HTMLInputElement.blur();} catch(e) {} |
||||
if (infoIsMoving){ |
||||
return; |
||||
} |
||||
infoIsMoving = true; |
||||
$("#openButton").animate({ |
||||
width: 0 |
||||
}, animationDuration, function() { |
||||
$("#openButton").hide(); |
||||
$("#info").animate({ |
||||
width: 450 |
||||
}, animationDuration, function() { |
||||
$("#info *").show(); |
||||
infoIsMoving = false; |
||||
infoIsOpen = true; |
||||
}); |
||||
}); |
||||
} |
||||
|
||||
function pauseAnimation(paused){ |
||||
//TODO
|
||||
} |
||||
|
||||
function openInstructions(){ |
||||
$("#instructions").show(); |
||||
instructionsOpen = true; |
||||
} |
||||
|
||||
function closeInstructions(){ |
||||
$("#instructions").hide(); |
||||
instructionsOpen = false; |
||||
} |
||||
|
||||
function toggleTestMode(){ |
||||
testMode = !testMode; |
||||
} |
@ -0,0 +1,76 @@ |
||||
function Paddle(){ |
||||
this.isRectangle = true; |
||||
this.isPaddle = true; |
||||
|
||||
this.move = function(){ |
||||
if (keyIsDown(LEFT_ARROW) && this.x - strokePadding > 0) this.x -= this.v; |
||||
if (keyIsDown(RIGHT_ARROW) && this.x + this.width + strokePadding < wWidth) this.x += this.v; |
||||
} |
||||
} |
||||
|
||||
var itemCount = 6; //Change if necessary
|
||||
|
||||
var FastBall = 1; |
||||
var FastPaddle = 2; |
||||
var SlowBall = 3; |
||||
var SlowPaddle = 4; |
||||
var CreateBall = 5; |
||||
var UpgradeBricks = 6; |
||||
function Item(x, y, radius, v, item){ |
||||
this.isItem = true; |
||||
this.isEllipse = true; |
||||
this.x = x; |
||||
this.y = y; |
||||
this.radius = radius; |
||||
this.v = v; |
||||
this.item = item; |
||||
|
||||
this.move = function() {this.y += this.v} |
||||
} |
||||
|
||||
|
||||
function Brick(){ |
||||
this.isRectangle = true; |
||||
this.isBrick = true; |
||||
} |
||||
|
||||
|
||||
function Frameborder(x, y, width, height){ |
||||
this.x = x; |
||||
this.y = y; |
||||
this.width = width; |
||||
this.height = height; |
||||
this.isRectangle = true; |
||||
this.isFrameborder = true; |
||||
this.isBrick = false; |
||||
} |
||||
|
||||
|
||||
function Ball(){ |
||||
this.isEllipse = true; |
||||
|
||||
this.calcVelocityX = function(p, vx){ |
||||
var divider = (this.x - (p.x - this.radius)) / (p.width + this.radius * 2 + strokePadding * 4); //Number between 0 and 1
|
||||
var range = divider - 0.5; //Number between -0.5 and 0.5
|
||||
range = range * this.v.mag / 0.5; //Number between -magnitude and magnitude
|
||||
range += vx; //Number between -(magnitude+abs(vx)) and magnitude+abs(vx)
|
||||
newVx = range * this.v.mag / (this.v.mag + abs(vx)); //Number between -magnitude and magnitude
|
||||
return newVx; |
||||
} |
||||
|
||||
this.calcVelocityY = function(){ |
||||
var vy = sqrt(pow(this.v.mag, 2) - pow(this.v.x, 2)); //Pythagoras to keep velocity constant
|
||||
return vy; |
||||
} |
||||
|
||||
this.isLost = function(){ |
||||
var b = this; |
||||
if (b.y - b.radius > wHeight) return true; |
||||
return false; |
||||
} |
||||
|
||||
this.move = function(){ |
||||
this.x += this.v.x; |
||||
this.y += this.v.y; |
||||
} |
||||
} |
@ -0,0 +1,69 @@ |
||||
//Only change if added more cases in LevelSwitcher
|
||||
var levelCount = 5; |
||||
|
||||
//Global: Amount of reached levels
|
||||
var levelReached = null; |
||||
|
||||
//Global: Erases every Cookie and starts Level 1 with 0 levelReached
|
||||
function deleteMemory(){ |
||||
clearStorage(); |
||||
currentGame.totalBricksDestroyed = getTotalBricksDestroyed(currentGame.levelNum); |
||||
currentGame.recordTime = getRecordTime(currentGame.levelNum); |
||||
setRekordInfo(); |
||||
$("#currentLevel").text("1"); |
||||
checkLevelButtons(1); |
||||
currentGame = new Level(1); |
||||
} |
||||
|
||||
//Level: Returns the shortest time ever played on that level
|
||||
function getRecordTime(level){ |
||||
var time = getItem("rekordTime" + level); |
||||
time = time == null ? Infinity : parseInt(time); |
||||
return time; |
||||
} |
||||
|
||||
//Global: Returns the total time played from every level
|
||||
function getTotalTimePlayed(){ |
||||
var time = getItem("totalTimePlayed"); |
||||
time = time == null ? 0 : parseInt(time); |
||||
return time; |
||||
} |
||||
|
||||
//Level: Returns the total amount of destroyed bricks of that level
|
||||
function getTotalBricksDestroyed(level){ |
||||
var bricks = getItem("totalBricksDestroyed" + level); |
||||
bricks = bricks == null ? 0 : parseInt(bricks); |
||||
return bricks; |
||||
} |
||||
|
||||
//Global: Returns the total global amount of destroyed bricks
|
||||
function getTotalBricksDestroyedGlobal(){ |
||||
var totalBricks = 0; |
||||
for (var i = 1; i <= levelCount; i++){ |
||||
var bricks = getItem("totalBricksDestroyed" + i); |
||||
bricks = bricks == null ? 0 : parseInt(bricks); |
||||
totalBricks += bricks; |
||||
} |
||||
return totalBricks; |
||||
} |
||||
|
||||
//Level: Sets a new record time for a specific level
|
||||
function setRecordTime(level, time){ |
||||
//storeItem("rekordTime" + level, String(time), 10);
|
||||
time = toTimeString(time); |
||||
$("#rekordInfo table:eq(1) tr:eq(" + level + ") td:eq(2)").text(time); |
||||
} |
||||
|
||||
//Global: Sets the total time played from every level
|
||||
function setTotalTimePlayed(time){ |
||||
//storeItem("totalTimePlayed", String(time), 10);
|
||||
time = toTimeString(time, true); |
||||
$("#totalTimePlayed").text(time); |
||||
} |
||||
|
||||
//Level: Sets the total amount of destroyed bricks for a specific level
|
||||
function setTotalBricksDestroyed(level, bricks){ |
||||
//storeItem("totalBricksDestroyed" + level, String(bricks), 10);
|
||||
$("#rekordInfo table:eq(1) tr:eq(" + level + ") td:eq(0)").text(bricks); |
||||
$("#totalBricksDestroyed").text(getTotalBricksDestroyedGlobal()); |
||||
} |
@ -0,0 +1,168 @@ |
||||
var stateCount = 9; |
||||
|
||||
|
||||
function colorSwitch(state){ |
||||
|
||||
switch (state){ |
||||
case -1: return "#373737"; //Gray - Invincible
|
||||
case 0: return false; //No brick
|
||||
case 1: return "#008800"; //Dark green
|
||||
case 2: return "#33FF33"; //Light green
|
||||
case 3: return "#99BBFF"; //Light blue
|
||||
case 4: return "#0000BB"; //Dark blue
|
||||
case 5: return "#AA00DD"; //Purple
|
||||
case 6: return "#FF0000"; //Red
|
||||
case 7: return "#FF7800"; //Orange
|
||||
case 8: return "#FFFF00"; //Yellow
|
||||
//Add new colors here
|
||||
default: return "#373737"; |
||||
} |
||||
}
|
||||
|
||||
|
||||
function tableSwitch(levelNum, level){ |
||||
|
||||
var c = 0, r = 0; |
||||
|
||||
switch (levelNum){ |
||||
case 1: |
||||
case 2: |
||||
c = 5; |
||||
r = 10; |
||||
break; |
||||
case 3: |
||||
case 4: |
||||
c = 7; |
||||
r = 12; |
||||
break; |
||||
case 5: |
||||
case 6: |
||||
c = 9; |
||||
r = 14; |
||||
break; |
||||
case 7: |
||||
case 8: |
||||
c = 11; |
||||
r = 16; |
||||
break; |
||||
case 9: |
||||
case 10: |
||||
c = 13; |
||||
r = 18; |
||||
break; |
||||
case 11: |
||||
case 12: |
||||
c = 15; |
||||
r = 20; |
||||
break; |
||||
case 13: |
||||
case 14: |
||||
c = 17; |
||||
r = 22; |
||||
break; |
||||
case 15: |
||||
case 16: |
||||
c = 19; |
||||
r = 24; |
||||
break; |
||||
case 17: |
||||
case 18: |
||||
c = 21; |
||||
r = 26; |
||||
break; |
||||
case 19: |
||||
case 20: |
||||
c = 23; |
||||
r = 28; |
||||
break; |
||||
} |
||||
return {cols: c, rows: r}; |
||||
} |
||||
|
||||
function designSwitch(levelNum, c, r){ |
||||
|
||||
var state = 0 |
||||
|
||||
switch (levelNum) { |
||||
case 1: |
||||
if (r == 3 || r == 6 || r == 9) state = 1; |
||||
break; |
||||
case 2: |
||||
if ((c == 1 || c == 3 || c == 5) && r % 2 == 0) state = 1; |
||||
break; |
||||
case 3: |
||||
if (r == 5 || r == 9){ |
||||
if (c == 4) state = -1; |
||||
else if (c == 3 || c == 5) state = 2; |
||||
else state = 1; |
||||
} |
||||
break; |
||||
case 4: |
||||
if (r == 9 && c > 2 && c < 6) state = -1; |
||||
if (r == 8 && c == 4 || r == 7 && c > 2 && c < 6 || r == 6 && c > 1 && c < 7 || r == 5 && c > 2 && c < 6 || r == 4 && c == 4) state = 2; |
||||
break; |
||||
case 5: |
||||
if (r == 1 || r == 14){ |
||||
if (c == 1 || c == 9) state = 3; |
||||
if (c == 2 || c == 3 || c == 7 || c == 8) state = 2; |
||||
if (c > 3 && c < 7) state = 1; |
||||
} |
||||
if (r == 2 || r == 13){ |
||||
if (c < 3 || c > 7) state = 2; |
||||
} |
||||
if (r == 3 || r == 12){ |
||||
if (c == 1 || c == 9) state = 2; |
||||
} |
||||
if (r > 3 && r < 12){ |
||||
if (c == 1 || c == 9) state = 1; |
||||
if (r > 6 && r < 9 && c > 3 && c < 7) state = -1; |
||||
} |
||||
break;
|
||||
case 6: |
||||
|
||||
break; |
||||
case 7: |
||||
|
||||
break; |
||||
case 8: |
||||
|
||||
break; |
||||
case 9: |
||||
|
||||
break; |
||||
case 10: |
||||
|
||||
break; |
||||
case 11: |
||||
|
||||
break; |
||||
case 12: |
||||
|
||||
break; |
||||
case 13: |
||||
|
||||
break; |
||||
case 14: |
||||
|
||||
break; |
||||
case 15: |
||||
|
||||
break; |
||||
case 16: |
||||
|
||||
break; |
||||
case 17: |
||||
|
||||
break; |
||||
case 18: |
||||
|
||||
break; |
||||
case 19: |
||||
|
||||
break; |
||||
case 20: |
||||
|
||||
break; |
||||
} |
||||
return state; |
||||
} |
@ -0,0 +1,61 @@ |
||||
window.onkeydown = function(e){ |
||||
|
||||
var key = e.keyCode ? e.keyCode : e.which; |
||||
|
||||
if (instructionsOpen){ |
||||
if (key == ESCAPE){ |
||||
closeInstructions(); |
||||
e.preventDefault(); |
||||
} |
||||
return; |
||||
} |
||||
|
||||
switch (key) { |
||||
case ESCAPE: |
||||
e.preventDefault(); |
||||
closeInfo(null); |
||||
break; |
||||
case TAB: |
||||
e.preventDefault(); |
||||
openInfo(null); |
||||
break; |
||||
case 32: //Space
|
||||
e.preventDefault(); |
||||
if (currentGame.isPaused){ |
||||
currentGame.pause(false); |
||||
} else if (currentGame.isStarted && !currentGame.isPaused) { |
||||
currentGame.pause(true); |
||||
} |
||||
if (!currentGame.isStarted){ |
||||
currentGame.start(); |
||||
} |
||||
break; |
||||
case SHIFT: |
||||
e.preventDefault(); |
||||
if (keyIsDown(68)){ |
||||
//Shift + D
|
||||
deleteMemory(); |
||||
} else if (keyIsDown(82)){ |
||||
//Shift + R
|
||||
currentGame.restart(); |
||||
} else if (keyIsDown(78)){ |
||||
//Shift + N
|
||||
toggleNotifications(); |
||||
} |
||||
break; |
||||
case 68: //D
|
||||
e.preventDefault(); |
||||
if (keyIsDown(SHIFT)){ |
||||
//D + Shift
|
||||
deleteMemory(); |
||||
} |
||||
break; |
||||
case 82: //R
|
||||
e.preventDefault(); |
||||
if (keyIsDown(SHIFT)){ |
||||
//R + Shift
|
||||
currentGame.restart(); |
||||
} |
||||
break; |
||||
} |
||||
} |
@ -0,0 +1,354 @@ |
||||
var TOP = 1; |
||||
var RIGHT = 2 |
||||
var BOTTOM = 3; |
||||
var LEFT = 4; |
||||
var TOP_RIGHT = 5; |
||||
var BOTTOM_RIGHT = 6; |
||||
var BOTTOM_LEFT = 7; |
||||
var TOP_LEFT = 8; |
||||
|
||||
var wWidth = window.innerWidth; |
||||
var wHeight = window.innerHeight; |
||||
var oldWHeight; |
||||
var oldWWidth; |
||||
|
||||
function updateVars(){ |
||||
oldWWidth = wWidth; |
||||
oldWHeight = wHeight; |
||||
wWidth = window.innerWidth; |
||||
wHeight = window.innerHeight; |
||||
} |
||||
|
||||
function collisionDetection(obj0, obj1){ |
||||
|
||||
var sp = strokePadding; |
||||
|
||||
if (obj0.isEllipse && obj1.isRectangle){ |
||||
|
||||
//Ball
|
||||
var b = obj0; |
||||
|
||||
//Rectangle
|
||||
var r = obj1; |
||||
|
||||
for (var i = 0; i < TWO_PI; i += PI / 32){ |
||||
|
||||
/* Check every borderpoint of the ball beginning |
||||
at the top in clock direction up to top again */ |
||||
|
||||
// Ball Center X
|
||||
var bcx = b.x; |
||||
|
||||
// Ball Center Y
|
||||
var bcy = b.y; |
||||
|
||||
// Ball Border X
|
||||
var bbx = b.x + sin(i) * b.radius; |
||||
|
||||
// Ball Border Y inverted because Y = 0 is the TOP of the screen
|
||||
var bby = b.y - cos(i) * b.radius; |
||||
|
||||
// Rectangle Width
|
||||
var rW = r.width + 2 * sp; |
||||
|
||||
// Rectangle Height
|
||||
var rH = r.height + 2 * sp; |
||||
|
||||
// Rectangle Border X
|
||||
var rX = r.x - sp; |
||||
|
||||
// Rectangle Border Y
|
||||
var rY = r.y - sp; |
||||
|
||||
// Objects touch
|
||||
if (bbx > rX && bbx < rX + rW |
||||
&& bby > rY && bby < rY + rH){ |
||||
|
||||
// STRAIGHT FACES //
|
||||
|
||||
//Top/Bottom touch
|
||||
if (bcx > rX && bcx < rX + rW){
|
||||
|
||||
//Top touch
|
||||
if (b.v.y > 0) return {isTouching: true, location: TOP}; |
||||
|
||||
//Bottom touch
|
||||
if (b.v.y < 0) return {isTouching: true, location: BOTTOM}; |
||||
} |
||||
|
||||
//Left/Right touch
|
||||
if (bcy > rY && bcy < rY + rH){ |
||||
|
||||
//Left touch
|
||||
if (b.v.x > 0) return {isTouching: true, location: LEFT}; |
||||
|
||||
//Right touch
|
||||
if (b.v.x < 0) return {isTouching: true, location: RIGHT}; |
||||
|
||||
} |
||||
|
||||
// CORNERS //
|
||||
|
||||
// BOTTOM Left/Right
|
||||
if (i > 0 && i <= PI / 2) return {isTouching: true, location: BOTTOM_LEFT}; |
||||
|
||||
//LEFT Bottom/Top
|
||||
if (i > PI / 2 && i <= PI) return {isTouching: true, location: TOP_LEFT}; |
||||
|
||||
//TOP Left/Right
|
||||
if (i > PI && i <= PI + PI / 2) return {isTouching: true, location: TOP_RIGHT}; |
||||
|
||||
//RIGHT Bottom/Top
|
||||
if (i > PI + PI / 2 && i <= TWO_PI) return {isTouching: true, location: BOTTOM_RIGHT}; |
||||
} |
||||
} |
||||
|
||||
} |
||||
|
||||
if (obj0.isEllipse && obj1.isEllipse){ |
||||
|
||||
//Ball 1
|
||||
var b1 = obj0; |
||||
|
||||
//Ball 2
|
||||
var b2 = obj1; |
||||
|
||||
//Balls are close to each other
|
||||
if (b1.x + b1.radius > b2.x - b2.radius |
||||
&& b1.x - b1.radius < b2.x + b2.radius |
||||
&& b1.y + b1.radius > b2.y - b2.radius |
||||
&& b1.y - b1.radius < b2.y + b2.radius){ |
||||
|
||||
var distance = sqrt(pow(b1.x - b2.x, 2) + pow(b1.y - b2.y, 2)); |
||||
|
||||
if (distance < b1.radius + b2.radius) return {isTouching: true}; |
||||
} |
||||
} |
||||
return {isTouching: false, location: 0}; |
||||
} |
||||
|
||||
function performCollision(obj0, obj1, collision){ |
||||
if (obj0.isEllipse){ |
||||
|
||||
var ball = obj0; |
||||
|
||||
//Ball collides with frameborder
|
||||
if (obj1.isFrameborder){ |
||||
switch (collision.location){ |
||||
case BOTTOM: |
||||
ball.v.y *= -1; |
||||
break; |
||||
case LEFT: |
||||
case RIGHT: |
||||
ball.v.x *= -1; |
||||
break; |
||||
} |
||||
if (testMode && collision.location == TOP) ball.v.y *= -1; |
||||
ball.move(); |
||||
} |
||||
|
||||
//Ball collides with any brick
|
||||
if (obj1.isBrick){ |
||||
switch (collision.location){ |
||||
case TOP: |
||||
case BOTTOM: |
||||
ball.v.y *= -1; |
||||
ball.move(); |
||||
return; |
||||
case LEFT: |
||||
case RIGHT: |
||||
ball.v.x *= -1; |
||||
ball.move(); |
||||
return; |
||||
case TOP_LEFT: |
||||
var cornerX = obj1.x; |
||||
var cornerY = obj1.y; |
||||
break; |
||||
case TOP_RIGHT: |
||||
var cornerX = obj1.x + obj1.width; |
||||
var cornerY = obj1.y; |
||||
break; |
||||
case BOTTOM_LEFT: |
||||
var cornerX = obj1.x; |
||||
var cornerY = obj1.y + obj1.height; |
||||
break; |
||||
case BOTTOM_RIGHT: |
||||
var cornerX = obj1.x + obj1.width; |
||||
var cornerY = obj1.y + obj1.height; |
||||
break; |
||||
} |
||||
|
||||
var nx = ball.x - cornerX; |
||||
var ny = ball.y - cornerY; |
||||
var length = sqrt(nx * nx + ny * ny); |
||||
nx /= length; |
||||
ny /= length; |
||||
|
||||
var projection = ball.v.x * nx + ball.v.y * ny; |
||||
ball.v.x = ball.v.x - 2 * projection * nx; |
||||
ball.v.y = ball.v.y - 2 * projection * ny; |
||||
|
||||
ball.move(); |
||||
|
||||
} |
||||
|
||||
//Ball collides with paddleboard
|
||||
if (obj1.isPaddle){ |
||||
switch (collision.location){ |
||||
case TOP: |
||||
case TOP_LEFT: |
||||
case TOP_RIGHT: |
||||
ball.v.x = ball.calcVelocityX(obj1, ball.v.x); |
||||
ball.v.y = -ball.calcVelocityY(); |
||||
ball.move(); |
||||
return; |
||||
case LEFT: |
||||
case RIGHT: |
||||
ball.v.x *= -1; |
||||
ball.move(); |
||||
return; |
||||
case BOTTOM_LEFT: |
||||
var cornerX = obj1.x; |
||||
var cornerY = obj1.y + obj1.height; |
||||
break; |
||||
case BOTTOM_RIGHT: |
||||
var cornerX = obj1.x + obj1.width; |
||||
var cornerY = obj1.y + obj1.height; |
||||
break; |
||||
} |
||||
var nx = ball.x - cornerX; |
||||
var ny = ball.y - cornerY; |
||||
var length = sqrt(nx * nx + ny * ny); |
||||
nx /= length; |
||||
ny /= length; |
||||
|
||||
var projection = ball.v.x * nx + ball.v.y * ny; |
||||
ball.v.x = ball.v.x - 2 * projection * nx; |
||||
ball.v.y = ball.v.y - 2 * projection * ny; |
||||
|
||||
ball.move(); |
||||
} |
||||
|
||||
//Ball collides with other ball
|
||||
if (obj1.isEllipse){ |
||||
|
||||
//Ball 1
|
||||
var b1 = obj0; |
||||
|
||||
//Ball 2
|
||||
var b2 = obj1; |
||||
|
||||
//Set mass equal to radius of each ball
|
||||
b1.mass = b1.radius; |
||||
b2.mass = b2.radius; |
||||
|
||||
//Colliding angle of ball 1 to ball 2 using arc tan of both x and y differences
|
||||
var collisionAngle = atan2((b2.y - b1.y), (b2.x - b1.x)); |
||||
|
||||
//Converting directions of velocity vector of balls into angles
|
||||
var d1 = atan2(b1.v.y, b1.v.x); |
||||
var d2 = atan2(b2.v.y, b2.v.x); |
||||
|
||||
//Ignoring mass effects new velocites are simply magnitude multiplied with value of angle differences
|
||||
var newXspeed1 = b1.v.mag * cos(d1 - collisionAngle); |
||||
var newYspeed1 = b1.v.mag * sin(d1 - collisionAngle); |
||||
var newXspeed2 = b2.v.mag * cos(d2 - collisionAngle); |
||||
var newYspeed2 = b2.v.mag * sin(d2 - collisionAngle); |
||||
|
||||
//According to the principle of linear momentum, kinetic energy stays the same after collision, so velocities are now related to masses
|
||||
var finalXspeed1 = ((b1.mass - b2.mass) * newXspeed1 + b2.mass * 2 * newXspeed2) / (b1.mass + b2.mass); |
||||
var finalYspeed1 = newYspeed1; |
||||
var finalXspeed2 = (b1.mass * 2 * newXspeed1 + (b2.mass - b1.mass) * newXspeed2) / (b1.mass + b2.mass); |
||||
var finalYspeed2 = newYspeed2; |
||||
|
||||
//Values of collisionAngle
|
||||
var cosAngle = cos(collisionAngle); |
||||
var sinAngle = sin(collisionAngle); |
||||
|
||||
//To also keep velocites relative to pure collisionAngle, subtract sin*x from cos*x and add sin*y to cos*y because coordSystem has y = 0 on the top
|
||||
var u1x = cosAngle * finalXspeed1 - sinAngle * finalYspeed1; |
||||
var u1y = sinAngle * finalXspeed1 + cosAngle * finalYspeed1; |
||||
var u2x = cosAngle * finalXspeed2 - sinAngle * finalYspeed2; |
||||
var u2y = sinAngle * finalXspeed2 + cosAngle * finalYspeed2; |
||||
|
||||
//Set new velocities to both balls
|
||||
b1.v.x = u1x; |
||||
b1.v.y = u1y; |
||||
b2.v.x = u2x; |
||||
b2.v.y = u2y; |
||||
|
||||
//Update magnitude
|
||||
b1.v.mag = sqrt(pow(b1.v.x, 2) + pow(b1.v.y, 2)); |
||||
b2.v.mag = sqrt(pow(b2.v.x, 2) + pow(b2.v.y, 2)); |
||||
|
||||
|
||||
//Move balls one vx/vy forward to avoid double inverting collision detection
|
||||
b1.x += b1.v.x; |
||||
b1.y += b1.v.y; |
||||
b2.x += b2.v.x; |
||||
b2.y += b2.v.y; |
||||
} |
||||
} |
||||
} |
||||
|
||||
|
||||
|
||||
function toTimeString(time, hoursWanted){ |
||||
|
||||
var time = floor(time / 10); |
||||
|
||||
var hs = String(floor(time % 100)); |
||||
var fs = String(floor((time / 100) % 60)); |
||||
|
||||
if (hoursWanted){ |
||||
var min = String(floor(((time / 100) / 60) % 60)); |
||||
var hr = String(floor(((time / 100) / 60) / 60)); |
||||
|
||||
if (hs.length < 2) hs = "0" + hs; |
||||
if (fs.length < 2) fs = "0" + fs; |
||||
if (min.length < 2) min = "0" + min; |
||||
if (hr.length < 2) hr = "0" + hr; |
||||
|
||||
var timeString = hr + ":" + min + ":" + fs + ":" + hs; |
||||
} else { |
||||
var min = String(floor(((time / 100) / 60) % 60)); |
||||
|
||||
if (hs.length < 2) hs = "0" + hs; |
||||
if (fs.length < 2) fs = "0" + fs; |
||||
if (min.length < 2) min = "0" + min; |
||||
|
||||
var timeString = min + ":" + fs + ":" + hs; |
||||
} |
||||
|
||||
|
||||
|
||||
return timeString; |
||||
} |
||||
|
||||
|
||||
function setCookie(name, value, years){ |
||||
var expires = ""; |
||||
if (years){ |
||||
var date = new Date(); |
||||
date.setTime(date.getTime() + (years * 365 * 24 * 60 * 60 * 1000)); |
||||
expires = "; expires=" + date.toUTCString(); |
||||
} |
||||
document.cookie = name + "=" + value + expires + "; path=/"; |
||||
} |
||||
|
||||
function getCookie(name){ |
||||
var nameEQ = name + "="; |
||||
var ca = document.cookie.split(';'); |
||||
for (var i = 0; i < ca.length; i++){ |
||||
var c = ca[i]; |
||||
while (c.charAt(0) == ' ') c = c.substring(1, c.length); |
||||
if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length, c.length); |
||||
} |
||||
return null; |
||||
} |
||||
|
||||
function deleteCookies(){ |
||||
for (var i = 0; i < arguments.length; i++){ |
||||
setCookie(arguments[i], "", -1); |
||||
} |
||||
} |
@ -0,0 +1,173 @@ |
||||
var lr; |
||||
|
||||
function setup(){ |
||||
|
||||
lr = getItem("levelReached"); |
||||
lr = lr == null ? 0 : parseInt(lr); |
||||
levelReached = lr |
||||
|
||||
createCanvas(window.innerWidth, window.innerHeight); |
||||
|
||||
//Layout Setup
|
||||
$("#openButton").hide(); |
||||
setInfoStyles(); |
||||
for (var i = 1; i <= levelCount; i++){ |
||||
$("#rekordInfo table:eq(1)").append("<tr><td></td><td>" + i + "</td><td></td></tr>"); |
||||
var bgColor; |
||||
var fgColor; |
||||
if (i % 2 == 0){ |
||||
bgColor = "rgba(200, 0, 0, 0.5)"; |
||||
fgColor = "#FFF"; |
||||
} |
||||
if (i % 2 != 0){ |
||||
bgColor = "rgba(0, 200, 0, 0.5)"; |
||||
fgColor = "#000"; |
||||
} |
||||
$("#rekordInfo table:eq(1) tr:eq(" + i + ")").css({ |
||||
"background-color": bgColor, |
||||
"color": fgColor |
||||
}); |
||||
} |
||||
setRekordInfo(); |
||||
|
||||
for (var i = 0; i < stateCount; i++){ |
||||
$("#colors tr:eq(" + i + ") td:eq(2)").html("<canvas id=\"brick" + i + "\"></canvas>"); |
||||
$("#brick" + i).attr({ |
||||
"width": String(wWidth * 0.3 * 0.6), |
||||
"height": String($("#colors").css("font-size").slice(0, 2) * 2) |
||||
}); |
||||
$("#brick" + i).css({ |
||||
"border": strokePadding * 2 + "px solid #000", |
||||
"border-radius": strokePadding * 2 |
||||
}); |
||||
var c = document.getElementById("brick" + i); |
||||
var ctx = c.getContext("2d"); |
||||
ctx.fillStyle = colorSwitch(i + 1); |
||||
ctx.fillRect(0, 0, c.width, c.height); |
||||
} |
||||
|
||||
for (var i = 0; i < itemCount; i++){ |
||||
$("#items tr:eq(" + i + ") td:eq(2)").html("<canvas id=\"item" + i + "\"></canvas>"); |
||||
$("#item" + i).attr({ |
||||
"width": String(wWidth * 0.3 * 0.3), |
||||
"height": String($("#items").css("font-size").slice(0, 2) * 3) |
||||
}); |
||||
|
||||
var c = document.getElementById("item" + i); |
||||
var ctx = c.getContext("2d"); |
||||
|
||||
var ballX = c.width / 2; |
||||
var ballY = c.height / 2; |
||||
var ballR = c.height / 2; |
||||
var lw = ballR * 0.2; |
||||
|
||||
ctx.beginPath(); |
||||
ctx.fillStyle = "#000000"; |
||||
ctx.arc(ballX, ballY, ballR, 0, TWO_PI); |
||||
ctx.fill(); |
||||
ctx.closePath(); |
||||
|
||||
var rectX = ballX - ballR * sin(5 * PI / 8) + lw; |
||||
var rectY = ballY + ballR * cos(5 * PI / 8) + lw; |
||||
var rectW = ballR * 2 * sin(5 * PI / 8) - lw * 2; |
||||
var rectH = ballR * 2 * abs(cos(5 * PI / 8)) - lw * 2; |
||||
|
||||
ctx.beginPath(); |
||||
ctx.lineJoin = "round"; |
||||
switch (i + 1){ |
||||
case FastBall: |
||||
ctx.fillStyle = "#00FF00"; |
||||
ctx.arc(ballX, ballY, ballR * 0.625, 0, TWO_PI); |
||||
ctx.fill(); |
||||
break; |
||||
case FastPaddle: |
||||
ctx.strokeStyle = "#00FF00"; |
||||
ctx.fillStyle = "#00FF00"; |
||||
|
||||
ctx.moveTo(rectX, rectY); |
||||
ctx.lineTo(rectX + rectW, rectY); |
||||
ctx.lineTo(rectX + rectW, rectY + rectH); |
||||
ctx.lineTo(rectX, rectY + rectH); |
||||
ctx.lineTo(rectX, rectY); |
||||
ctx.lineTo(rectX + rectW, rectY); |
||||
ctx.lineTo(rectX, rectY); |
||||
|
||||
ctx.stroke(); |
||||
ctx.fill(); |
||||
break; |
||||
case SlowBall: |
||||
ctx.fillStyle = "#FF0000"; |
||||
ctx.arc(ballX, ballY, ballR * 0.625, 0, TWO_PI); |
||||
ctx.fill(); |
||||
break; |
||||
case SlowPaddle: |
||||
ctx.strokeStyle = "#FF0000"; |
||||
ctx.fillStyle = "#FF0000"; |
||||
|
||||
ctx.moveTo(rectX, rectY); |
||||
ctx.lineTo(rectX + rectW, rectY); |
||||
ctx.lineTo(rectX + rectW, rectY + rectH); |
||||
ctx.lineTo(rectX, rectY + rectH); |
||||
ctx.lineTo(rectX, rectY); |
||||
ctx.lineTo(rectX + rectW, rectY); |
||||
ctx.lineTo(rectX, rectY); |
||||
|
||||
ctx.stroke(); |
||||
ctx.fill(); |
||||
break; |
||||
case CreateBall: |
||||
var lineLength = ballR * 0.5; |
||||
|
||||
ctx.lineWidth = lw; |
||||
ctx.strokeStyle = "#00FF00"; |
||||
|
||||
ctx.moveTo(ballX, ballY); |
||||
ctx.lineTo(ballX + lineLength, ballY); |
||||
ctx.lineTo(ballX - lineLength, ballY); |
||||
ctx.lineTo(ballX, ballY); |
||||
|
||||
ctx.moveTo(ballX, ballY); |
||||
ctx.lineTo(ballX, ballY + lineLength); |
||||
ctx.lineTo(ballX, ballY - lineLength); |
||||
ctx.lineTo(ballX, ballY); |
||||
|
||||
ctx.stroke(); |
||||
break; |
||||
case UpgradeBricks: |
||||
var lineLength = ballR * 0.5; |
||||
|
||||
ctx.lineWidth = lw; |
||||
ctx.strokeStyle = "#FF0000"; |
||||
|
||||
ctx.moveTo(ballX, ballY); |
||||
ctx.lineTo(ballX + lineLength, ballY); |
||||
ctx.lineTo(ballX - lineLength, ballY); |
||||
ctx.lineTo(ballX, ballY); |
||||
|
||||
ctx.moveTo(ballX, ballY); |
||||
ctx.lineTo(ballX, ballY + lineLength); |
||||
ctx.lineTo(ballX, ballY - lineLength); |
||||
ctx.lineTo(ballX, ballY); |
||||
|
||||
ctx.stroke(); |
||||
break; |
||||
case UpgradeBricks: |
||||
} |
||||
ctx.closePath(); |
||||
} |
||||
|
||||
|
||||
//Level Setup
|
||||
var level = levelReached + 1; |
||||
if (level > levelCount) level = levelCount; |
||||
currentGame = new Level(level); |
||||
$("#currentLevel").html(level); |
||||
checkLevelButtons(level); |
||||
openInstructions(); |
||||
} |
||||
|
||||
function draw(){ |
||||
currentGame.drawShapes(); |
||||
currentGame.renderTime(); |
||||
} |
||||
|
@ -0,0 +1,290 @@ |
||||
/* General Styles*/ |
||||
|
||||
body |
||||
{ |
||||
margin: 0; |
||||
padding: 0; |
||||
} |
||||
|
||||
canvas |
||||
{ |
||||
vertical-align: top; |
||||
} |
||||
|
||||
input |
||||
{ |
||||
cursor: pointer; |
||||
} |
||||
|
||||
|
||||
/* Infolable Styles*/ |
||||
|
||||
#info |
||||
{ |
||||
display: block; |
||||
position: absolute; |
||||
height: 80%; |
||||
width: 450px; |
||||
top: 5%; |
||||
background-color: rgba(50, 50, 50, 0.6); |
||||
border-radius: 0 0 40px 0; |
||||
box-shadow: 10px 20px 20px #000; |
||||
color: #FFF; |
||||
} |
||||
|
||||
#info * |
||||
{ |
||||
position: absolute; |
||||
} |
||||
|
||||
#levelSelector, #rekordInfo, #controlsInfo |
||||
{ |
||||
left: 12.5%; |
||||
width: 75%; |
||||
background-color: rgba(50, 50, 50, 0.6); |
||||
border-radius: 10px; |
||||
border: 4px solid #000; |
||||
} |
||||
|
||||
#closeButton |
||||
{ |
||||
right: 0; |
||||
height: 5%; |
||||
background-color: #000; |
||||
border-color: #000; |
||||
color: #FFF; |
||||
border-radius: 0 0 0 10px; |
||||
} |
||||
|
||||
#openButton |
||||
{ |
||||
display: block; |
||||
position: absolute; |
||||
width: 0px; |
||||
height: 50px; |
||||
top: 5%; |
||||
border-radius: 0 5px 5px 0; |
||||
background-color: rgba(50, 50, 50, 0.5); |
||||
box-shadow: 5px 5px 5px #000; |
||||
} |
||||
|
||||
#openButton input |
||||
{ |
||||
height: 100%; |
||||
width: 100%; |
||||
background-color: rgba(0, 0, 0, 0); |
||||
border-color: rgba(50, 50, 50, 0.6); |
||||
border-left: none; |
||||
font-size: 20px; |
||||
} |
||||
|
||||
#levelSelector |
||||
{ |
||||
top: 5%; |
||||
height: 17.5%; |
||||
} |
||||
|
||||
#levelLabel, #currentLevel, #levelUp, #levelDown |
||||
{ |
||||
width: 50%; |
||||
height: 33%; |
||||
text-align: center; |
||||
} |
||||
|
||||
#levelLabel |
||||
{ |
||||
top: 33%; |
||||
left: 0; |
||||
} |
||||
|
||||
#currentLevel |
||||
{ |
||||
top: 33%; |
||||
left: 50%; |
||||
} |
||||
|
||||
#levelUp |
||||
{ |
||||
top: 0; |
||||
left: 50%; |
||||
background-color: lightgreen; |
||||
border-color: lightgreen; |
||||
border-radius: 0 10px 0 0; |
||||
} |
||||
|
||||
#levelDown |
||||
{ |
||||
top: 66%; |
||||
left: 50%; |
||||
background-color: lightcoral; |
||||
border-color: lightcoral; |
||||
border-radius: 0 0 10px 0; |
||||
} |
||||
|
||||
#rekordInfo |
||||
{ |
||||
top: 25%; |
||||
height: 30%; |
||||
overflow-y: scroll; |
||||
} |
||||
|
||||
#rekordInfo * |
||||
{ |
||||
position: relative; |
||||
} |
||||
|
||||
#rekordInfo table |
||||
{ |
||||
width: 95%; |
||||
margin-top: 5%; |
||||
} |
||||
|
||||
#rekordInfo table:nth-child(1) tr td |
||||
{ |
||||
padding: 5%; |
||||
color: #FFF; |
||||
} |
||||
|
||||
#rekordInfo table:nth-child(2) |
||||
{ |
||||
text-align: center; |
||||
border-collapse: collapse; |
||||
border: 5px solid #000; |
||||
} |
||||
|
||||
#rekordInfo table:nth-child(2) tr td |
||||
{ |
||||
width: 33%; |
||||
padding: 0; |
||||
} |
||||
|
||||
#rekordInfo table:nth-child(2) tr:nth-child(1) td |
||||
{ |
||||
height: 50px; |
||||
background-color: rgba(100, 100, 255, 0.5); |
||||
font-weight: bold; |
||||
} |
||||
|
||||
#controlsInfo |
||||
{ |
||||
top: 57.5%; |
||||
height: 37.5%; |
||||
} |
||||
|
||||
#controlsInfo * |
||||
{ |
||||
position: relative; |
||||
} |
||||
|
||||
#controlsInfo table |
||||
{ |
||||
color: #FFF; |
||||
left: 5%; |
||||
height: 100%; |
||||
width: 90%; |
||||
} |
||||
|
||||
#infoButton |
||||
{ |
||||
width: 100%; |
||||
height: 75%; |
||||
font-size: inherit; |
||||
background-color: #FFFF99; |
||||
} |
||||
|
||||
|
||||
/* Instructions */ |
||||
|
||||
#instructions |
||||
{ |
||||
position: absolute; |
||||
display: none; |
||||
width: 100%; |
||||
height: 100%; |
||||
background-color: rgba(0, 0, 0, 0.8); |
||||
} |
||||
|
||||
#instructions p |
||||
{ |
||||
font-size: 23px; |
||||
} |
||||
|
||||
#instructionsWrapper |
||||
{ |
||||
position: absolute; |
||||
width: 30%; |
||||
height: 80%; |
||||
left: 0; |
||||
right: 0; |
||||
top: 0; |
||||
bottom: 0; |
||||
margin: auto; |
||||
background-color: #888; |
||||
padding: 5%; |
||||
border-radius: 50px; |
||||
} |
||||
|
||||
#instructionsHeader |
||||
{ |
||||
position: absolute; |
||||
text-align: center; |
||||
margin: 0; |
||||
top: 5%; |
||||
left: 0; |
||||
width: 100%; |
||||
} |
||||
|
||||
#instructionsContent |
||||
{ |
||||
position: relative; |
||||
height: 100%; |
||||
width: 100%; |
||||
padding-right: 2.5%; |
||||
overflow-y: auto; |
||||
} |
||||
|
||||
#colors, #items |
||||
{ |
||||
width: 100%; |
||||
font-size: 25px; |
||||
} |
||||
|
||||
#colors td, #items td |
||||
{ |
||||
width: 33%; |
||||
} |
||||
|
||||
#colors td:first-child |
||||
{ |
||||
text-align: center; |
||||
} |
||||
|
||||
|
||||
|
||||
/* Other Stuff */ |
||||
|
||||
#timeDiv |
||||
{ |
||||
display: block; |
||||
position: absolute; |
||||
right: 0; |
||||
bottom: 0; |
||||
width: 200px; |
||||
height: 30px; |
||||
font-size: 24px; |
||||
text-align: center; |
||||
color: #BBB; |
||||
background-color: rgb(50, 50, 50); |
||||
border-radius: 10px 0 0 0; |
||||
border-top: 5px solid #000; |
||||
border-left: 5px solid #000; |
||||
} |
||||
|
||||
#testMode |
||||
{ |
||||
display: block; |
||||
position: absolute; |
||||
right: 0; |
||||
top: 0; |
||||
height: 50px; |
||||
} |
After Width: | Height: | Size: 100 KiB |
Loading…
Reference in new issue