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); } }