diff --git a/menu.js b/menu.js
index 7edc0cc..cd14a2f 100644
--- a/menu.js
+++ b/menu.js
@@ -3,9 +3,14 @@ window.onresize = () => {
};
function scaleWindow() {
+ bgCanvas.height = window.innerHeight - 40;
+ bgCanvas.width = bgCanvas.height / (5 / 3);
+ bgContext.scale(bgCanvas.width / fieldSize.x, bgCanvas.height / fieldSize.y);
+
canvas.height = window.innerHeight - 40;
canvas.width = canvas.height / (5 / 3);
context.scale(canvas.width / fieldSize.x, canvas.height / fieldSize.y);
+
if(!firstRun && isPaused) {
draw();
}
@@ -60,20 +65,20 @@ function fadeBlurIn() {
const finalVal = 15;
let currentVal = 0;
- const id = setInterval(frame, 1);
+ const id = setInterval(frame, 16);
function frame() {
if(currentVal >= finalVal) {
clearInterval(id);
} else {
- currentVal += 0.1;
+ currentVal += 1.6;
blurEl.setAttribute("stdDeviation", currentVal);
}
}
setTimeout(() => {
- blurEl.setAttribute("stdDeviation", finalVal);
- clearInterval(id);
if (currentVal < finalVal) {
+ blurEl.setAttribute("stdDeviation", finalVal);
+ clearInterval(id);
console.log("Performance Issues: system couldn't hold up");
}
}, 1000);
@@ -84,12 +89,12 @@ function fadeBlurOut() {
const finalVal = 0;
let currentVal = 15;
- const id = setInterval(frame, 1);
+ const id = setInterval(frame, 16);
function frame() {
if(currentVal <= finalVal) {
clearInterval(id);
} else {
- currentVal -= 0.1;
+ currentVal -= 1.6;
blurEl.setAttribute("stdDeviation", currentVal);
}
}
@@ -154,4 +159,5 @@ function initGame() {
startGame();
firstRun = false;
switchLang(currentLang);
+
}
\ No newline at end of file
diff --git a/style.css b/style.css
index 4953872..fbe273a 100644
--- a/style.css
+++ b/style.css
@@ -74,14 +74,14 @@ body {
position: absolute;
left: 0;
top: 0;
- filter: none;
+ filter: url(#f2);
}
#background.blurred {
filter: url(#f1);
}
-#tetris {
+#tetris, #tetris-background {
position: absolute;
left: 50%;
top: 50%;
@@ -91,6 +91,13 @@ body {
-o-transform: translate(-50%, -50%);
transform: translate(-50%, -50%);
border: solid .2em #fff;
+ z-index: 1;
+ background: transparent;
+}
+
+#tetris-background {
+ border: none;
+ z-index: 0;
}
#score, #controls {
@@ -155,7 +162,7 @@ body {
}
@media (max-width: 1400px) {
- #tetris {
+ #tetris, #tetris-background {
height: 75%;
}
diff --git a/tetris.js b/tetris.js
index 558eec8..fb349b1 100644
--- a/tetris.js
+++ b/tetris.js
@@ -1,14 +1,33 @@
const canvas = document.getElementById('tetris');
const context = canvas.getContext('2d');
+const bgCanvas = document.getElementById('tetris-background');
+const bgContext = bgCanvas.getContext('2d');
+
const fieldSize = {x: 12, y: 20};
const tileGap = .05;
+/*
+default -> plain squares
+retro -> original look
+modern -> rounded corners
+snake -> all tiles are connected
+ */
+let theme = 'default';
+
let isPaused = true;
let startTime = 0;
let prevUpdateScore = 0;
+if (typeof console === "undefined") {
+ console = {};
+}
+
+let prerenders = [];
+const prerenderWidth = canvas.width / fieldSize.x * 4;
+const prerenderHeight = canvas.height / fieldSize.y * 4;
+
function arenaSweep() {
let rowCount = 1;
outer: for (let y = arena.length - 1; y > 0; --y) {
@@ -26,10 +45,11 @@ function arenaSweep() {
rowCount *= 2;
}
if (player.score - prevUpdateScore > 50) {
- dropInterval -= -20;
+ dropInterval -= 20;
dropInterval = dropInterval > 100 ? dropInterval : 100;
prevUpdateScore = player.score;
}
+ drawArena();
}
function clearScreen() {
@@ -104,24 +124,122 @@ function createPiece(type) {
}
function draw() {
- context.fillStyle = '#000';
- context.fillRect(0, 0, canvas.width, canvas.height);
+ // bgContext.fillStyle = '#000';
+ // bgContext.fillRect(0, 0, canvas.width, canvas.height);
+ context.clearRect(0, 0, canvas.width, canvas.height);
+ // clearScreen();
- drawMatrix(arena, {x: 0, y: 0});
+ // drawMatrix(arena, {x: 0, y: 0}, true);
drawMatrix(player.matrix, player.pos);
}
-function drawMatrix(matrix, offset) {
+function drawArena() {
+ bgContext.fillStyle = '#000';
+ bgContext.fillRect(0, 0, canvas.width, canvas.height);
+ drawMatrix(arena, {x: 0, y: 0}, true);
+}
+
+function drawMatrix(matrix, offset, isBg) {
matrix.forEach((row, y) => {
row.forEach((value, x) => {
if (value !== 0) {
- context.fillStyle = colors[value];
- context.fillRect(x + offset.x + tileGap / 2, y + offset.y + tileGap / 2, 1 - tileGap, 1 - tileGap);
+ drawTile(x, y, offset, colors[value], matrix, isBg);
}
});
});
}
+function drawRoundRect(ctx, x, y, w, h, r) {
+ let r1 = r,
+ r2 = r,
+ r3 = r,
+ r4 = r;
+ if (typeof r === "number") {
+ if (w < 2 * r) r = w / 2;
+ if (h < 2 * r) r = h / 2;
+ } else {
+ r.forEach((corner, index) => {
+ if (w < 2 * r[index]) r[index] = w / 2;
+ if (h < 2 * r[index]) r[index] = h / 2;
+ });
+ r1 = r[0];
+ r2 = r[1];
+ r3 = r[2];
+ r4 = r[3];
+ }
+ ctx.beginPath();
+ ctx.moveTo(x + r1, y);
+ if (r1 > 0) {
+ ctx.arcTo(x + w, y, x + w, y + h, r1);
+ } else {
+ ctx.lineTo(x + w, y);
+ }
+ if (r2 > 0) {
+ ctx.arcTo(x + w, y + h, x, y + h, r2);
+ } else {
+ ctx.lineTo(x + w, y + h);
+ }
+ if (r3 > 0) {
+ ctx.arcTo(x, y + h, x, y, r3);
+ } else {
+ ctx.lineTo(x, y + h);
+ }
+ if (r4 > 0) {
+ ctx.arcTo(x, y, x + w, y, r4);
+ } else {
+ ctx.lineTo(x, y);
+ }
+ ctx.closePath();
+ ctx.fill();
+}
+
+function drawTile(x, y, offset, color, matrix, isBg) {
+ let ctx = context;
+ if (isBg) {
+ ctx = bgContext;
+ }
+ switch (theme) {
+ case "default":
+ ctx.fillStyle = color;
+ ctx.fillRect(x + offset.x + tileGap / 2, y + offset.y + tileGap / 2, 1 - tileGap, 1 - tileGap);
+ break;
+ case "modern":
+ ctx.fillStyle = color;
+ drawRoundRect(ctx, x + offset.x + tileGap / 2, y + offset.y + tileGap / 2, 1 - tileGap, 1 - tileGap, .15);
+ break;
+ case "snakes":
+ ctx.fillStyle = color;
+ let r1 = .15, // top right
+ r2 = .15, // bottom right
+ r3 = .15, // bottom left
+ r4 = .15; // top left
+ // Is there a tile to the left?
+ if (matrix[y][x - 1] > 0) {
+ r3 = 0;
+ r4 = 0;
+ }
+ // Is there a tile to the right?
+ if (matrix[y][x + 1] > 0) {
+ r1 = 0;
+ r2 = 0;
+ }
+ // Is there a tile to the top?
+ if (matrix[y - 1] !== undefined && matrix[y - 1][x] > 0) {
+ r1 = 0;
+ r4 = 0;
+ }
+ // Is there a tile to the bottom?
+ if (matrix[y + 1] !== undefined && matrix[y + 1][x] > 0) {
+ r2 = 0;
+ r3 = 0;
+ }
+ drawRoundRect(ctx, x + offset.x, y + offset.y, 1, 1, [r1, r2, r3, r4]);
+ break;
+ default:
+ break;
+ }
+}
+
function gameOver() {
arena.forEach(row => row.fill(0));
passedTime = 0;
@@ -132,6 +250,33 @@ function gameOver() {
updateScore();
}
+function getCookie(name) {
+ if (document.cookie === "") {
+ return;
+ }
+ const cookies = document.cookie.split(";");
+ for (let i = 0; i < cookies.length; i++) {
+ let biscuit = (cookies[i]).split("=");
+ if (biscuit[0] === name)
+ return {name: biscuit[0], value: biscuit[1]};
+ }
+}
+
+function getCookies() {
+ if (document.cookie === "") {
+ return;
+ }
+ const cookies = document.cookie.split(";");
+ const cookieList = [];
+ for (let i = 0; i < cookies.length; i++) {
+ let biscuit = (cookies[i]).split("=");
+ cookieList.push({
+ name: biscuit[0],
+ value: biscuit[1]
+ });
+ }
+}
+
function merge(arena, player) {
player.matrix.forEach((row, y) => {
row.forEach((value, x) => {
@@ -140,6 +285,7 @@ function merge(arena, player) {
}
});
});
+ drawArena();
}
function playerDrop() {
@@ -189,6 +335,29 @@ function playerRotate(dir) {
}
}
+function prerenderPiece(type, preContext) {
+ createPiece(type).forEach((row, y) => {
+ row.forEach((value, x) => {
+ if (value !== 0) {
+ preContext.fillStyle = colors[value];
+ preContext.fillRect(x + tileGap / 2, y + tileGap / 2, 1 - tileGap, 1 - tileGap);
+ }
+ });
+ });
+}
+
+function prerenderPieces() {
+ const preCanvas = document.createElement('canvas');
+ preCanvas.width = prerenderWidth;
+ preCanvas.height = prerenderHeight;
+ const preContext = preCanvas.getContext("2d");
+ prerenderPiece("I", preContext);
+ prerenders.push({
+ canvas: preCanvas,
+ context: preContext
+ });
+}
+
function rotate(matrix, dir) {
for (let y = 0; y < matrix.length; ++y) {
for (let x = 0; x < y; ++x) {
@@ -209,6 +378,12 @@ function rotate(matrix, dir) {
}
}
+function saveHighscore() {
+ if (getCookie("highscore").value < player.score) {
+ document.cookie = "highscore=" + player.score + "; max-age=" + 60 * 60 * 24 * 365 * 1000 + "; path=/;";
+ }
+}
+
let dropCounter = 0;
let dropInterval = 1000;
@@ -241,6 +416,7 @@ function updateScore() {
if(lastScore !== player.score) {
scoreUpdateAni();
lastScore = player.score;
+ saveHighscore();
}
document.getElementById('score').innerText = player.score.toString();
}
@@ -309,6 +485,7 @@ document.addEventListener('keydown', event => {
function startGame() {
arena = createMatrix(fieldSize.x, fieldSize.y);
+ drawArena();
playerReset();
update();
updateScore();