diff --git a/.gitignore b/.gitignore
index 1c2d52b..62c8935 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1 @@
-.idea/*
+.idea/
\ No newline at end of file
diff --git a/index.html b/index.html
index fbc4c88..c8aadf2 100644
--- a/index.html
+++ b/index.html
@@ -31,6 +31,10 @@
+
+
+
+
diff --git a/js/arena.js b/js/arena.js
index d95615d..175d3bf 100644
--- a/js/arena.js
+++ b/js/arena.js
@@ -2,6 +2,7 @@ class Arena {
constructor(gameInfo, game) {
this.g = gameInfo;
this.game = game;
+ this.p = this.g.player;
this.field = createMatrix(this.g.fieldSize.x, this.g.fieldSize.y);
}
diff --git a/js/game.js b/js/game.js
index 0227e35..e0754e1 100644
--- a/js/game.js
+++ b/js/game.js
@@ -18,6 +18,8 @@ class Game {
}
drawHolding() {
+ if (this.p.holdingTile === null)
+ return;
this.g.contextHold.clearRect(0, 0, this.g.canvasHold.width, this.g.canvasHold.height);
const offset = centerOffset(this.p.holdingTile);
const x = 3 - (this.p.holdingTile[0].length / 2) + offset.x;
@@ -35,8 +37,7 @@ class Game {
});
}
- drawTile(x, y, offset, color, matrix, useContext = this.g.context) {
- const ctx = useContext;
+ drawTile(x, y, offset, color, matrix, ctx = this.g.context) {
switch (this.g.theme) {
case "default":
ctx.fillStyle = color;
@@ -74,6 +75,9 @@ class Game {
}
drawRoundRect(ctx, x + offset.x, y + offset.y, 1, 1, [r1, r2, r3, r4]);
break;
+ case "retro":
+ drawReliefRect(ctx, x + offset.x, y + offset.y, 1, 1, .15, color);
+ break;
default:
this.g.theme = "default";
this.drawTile(x, y, offset, color, matrix, ctx);
@@ -115,6 +119,13 @@ class Game {
this.drawArena();
}
+ redrawScreen() {
+ this.draw();
+ this.drawArena();
+ this.drawHolding();
+ this.drawUpcoming();
+ }
+
registerListeners() {
// Keyboard controls
document.addEventListener('keydown', event => {
diff --git a/js/language.js b/js/language.js
index 68fd030..d04076e 100644
--- a/js/language.js
+++ b/js/language.js
@@ -13,6 +13,7 @@ const en = {
counterTime: "Time: ",
themeDefault: "Default",
themeModern: "Modern",
+ themeRetro: "Retro",
themeSnakes: "Snakes",
titleAppearance: "Appearance",
titleControls: "Controls",
@@ -36,6 +37,7 @@ const de = {
counterTime: "Zeit: ",
themeDefault: "Standard",
themeModern: "Modern",
+ themeRetro: "Retro",
themeSnakes: "Schlangen",
titleAppearance: "Aussehen",
titleControls: "Steuerung",
diff --git a/js/menu.js b/js/menu.js
index 34ba95a..f3ad597 100644
--- a/js/menu.js
+++ b/js/menu.js
@@ -7,10 +7,7 @@ let escState = 1;
window.onresize = () => {
scaleWindow();
- game.draw();
- game.drawArena();
- game.drawUpcoming();
- game.drawHolding();
+ game.redrawScreen();
};
function scaleWindow() {
@@ -93,7 +90,8 @@ document.getElementById("game-reset").addEventListener("click", () => {
document.getElementsByName("theme").forEach((el) => {
el.addEventListener("change", (e) => {
- game.theme = e.target.getAttribute("data-theme");
+ game.g.theme = e.target.getAttribute("data-theme");
+ game.redrawScreen();
});
});
@@ -185,25 +183,10 @@ function fadeBlurOut() {
const scoreEl = document.getElementById("score");
const nativeTransform = getComputedStyle(scoreEl).transform;
function scoreUpdateAni() {
- const scale = 1.5;
- const finalScale = 1;
- let currentScale = 1;
- let upscaling = true;
-
- const id = setInterval(frame, 5);
-
- function frame() {
- if(currentScale <= scale && upscaling) {
- currentScale += 0.02;
- scoreEl.style.transform = nativeTransform + " scale(" + currentScale + ")";
- } else if (currentScale >= finalScale) {
- upscaling = false;
- currentScale -= 0.02;
- scoreEl.style.transform = nativeTransform + " scale(" + currentScale + ")";
- } else {
- clearInterval(id);
- }
- }
+ scoreEl.classList.add("update");
+ setTimeout(() => {
+ scoreEl.classList.remove("update");
+ }, 1500);
}
function showMenu() {
@@ -235,7 +218,7 @@ function hideMenu() {
game.g.lastTimeUpdate = Date.now();
fadeBlurOut();
if(!firstRun) {
- game.update(lastTime);
+ game.update(game.g.lastTime);
}
}
diff --git a/js/tetris.js b/js/tetris.js
index 79af12b..778210e 100644
--- a/js/tetris.js
+++ b/js/tetris.js
@@ -164,6 +164,47 @@ function drawRoundRect(ctx, x, y, w, h, r) {
ctx.fill();
}
+function drawReliefRect(ctx, x, y, w, h, l, clr) {
+ ctx.fillStyle = clr;
+ ctx.fillRect(x + l, y + l, w - (2 * l), h - (2 * l));
+
+ ctx.fillStyle = colorLuminance(clr, .6);
+ ctx.beginPath();
+ ctx.moveTo(x, y);
+ ctx.lineTo(x + w, y);
+ ctx.lineTo(x + w - l, y + l);
+ ctx.lineTo(x + l, y + l);
+ ctx.fill();
+ ctx.closePath();
+
+ ctx.fillStyle = colorLuminance(clr, .3);
+ ctx.beginPath();
+ ctx.moveTo(x, y);
+ ctx.lineTo(x, y + h);
+ ctx.lineTo(x + l, y + h - l);
+ ctx.lineTo(x + l, y + l);
+ ctx.fill();
+ ctx.closePath();
+
+ ctx.fillStyle = colorLuminance(clr, -.6);
+ ctx.beginPath();
+ ctx.moveTo(x, y + h);
+ ctx.lineTo(x + w, y + h);
+ ctx.lineTo(x + w - l, y + h - l);
+ ctx.lineTo(x + l, y + h - l);
+ ctx.fill();
+ ctx.closePath();
+
+ ctx.fillStyle = colorLuminance(clr, -.3);
+ ctx.beginPath();
+ ctx.moveTo(x + w, y);
+ ctx.lineTo(x + w, y + h);
+ ctx.lineTo(x + w - l, y + h - l);
+ ctx.lineTo(x + w - l, y + l);
+ ctx.fill();
+ ctx.closePath();
+}
+
function formatMillis(millis) {
const d = new Date(1000 * Math.round(millis / 1000));
return (d.getUTCMinutes() < 10 ? "0" : "") + d.getUTCMinutes() + ":" + (d.getUTCSeconds() < 10 ? "0" : "") + d.getUTCSeconds();
@@ -242,4 +283,27 @@ const game = new Game();
function startGame() {
game.start();
+}
+
+/**
+ * @return {string}
+ */
+function colorLuminance(hex, lum) {
+
+ // validate hex string
+ hex = String(hex).replace(/[^0-9a-f]/gi, '');
+ if (hex.length < 6) {
+ hex = hex[0] + hex[0] + hex[1] + hex[1] + hex[2] + hex[2];
+ }
+ lum = lum || 0;
+
+ // convert to decimal and change luminosity
+ let rgb = "#", c, i;
+ for (i = 0; i < 3; i++) {
+ c = parseInt(hex.substr(i * 2, 2), 16);
+ c = Math.round(Math.min(Math.max(0, c + (c * lum)), 255)).toString(16);
+ rgb += ("00" + c).substr(c.length);
+ }
+
+ return rgb;
}
\ No newline at end of file
diff --git a/js/touch-control.js b/js/touch-control.js
index 57ad34a..7f99870 100644
--- a/js/touch-control.js
+++ b/js/touch-control.js
@@ -1,27 +1,27 @@
const hammertime = new Hammer(document.getElementById("tetris"));
hammertime.on('swipeleft', (e) => {
- keys.left.action();
+ game.g.keys.left.action();
});
hammertime.on('swiperight', (e) => {
- keys.right.action();
+ game.g.keys.right.action();
});
hammertime.on('swipeup', () => {
- keys.holdTile.action();
+ game.g.keys.holdTile.action();
});
hammertime.on('pandown swipedown', (e) => {
- keys.down.action();
+ game.g.keys.down.action();
});
hammertime.on('tap', (e) => {
if (e.tapCount >= 2) {
- keys.rotateRight.action();
+ game.g.keys.rotateRight.action();
}
});
hammertime.on('press', () => {
- keys.down.action();
+ game.g.keys.down.action();
});
\ No newline at end of file
diff --git a/style.css b/style.css
index 33adaea..b81bf40 100644
--- a/style.css
+++ b/style.css
@@ -212,11 +212,29 @@ body {
#score {
font-weight: 900;
- bottom: 0;
+ bottom: initial;
top: 2.5vh;
font-size: 5vh;
}
+#score.update {
+ animation: scoreUpdate .5s;
+}
+
+@keyframes scoreUpdate {
+ 0% {
+ transform: translateX(-50%) scale(1);
+ }
+
+ 50% {
+ transform: translateX(-50%) scale(1.5);
+ }
+
+ 100% {
+ transform: translateX(-50%) scale(1);
+ }
+}
+
#time:before, #score:before {
content: attr(data-prefix);
}
@@ -230,6 +248,10 @@ body {
max-width: 20vw;
}
+.game-over #score {
+ top: 50%;
+}
+
#footer {
position: absolute;
bottom: 10px;