diff --git a/package.json b/package.json index be78d2e..e23006f 100644 --- a/package.json +++ b/package.json @@ -20,6 +20,7 @@ }, "homepage": "https://github.com/GuildCrafts/browser-games#readme", "dependencies": { - "http-server": "^0.9.0" + "http-server": "^0.9.0", + "jquery-confirm": "^3.2.3" } } diff --git a/public/css/tetris.css b/public/css/tetris.css new file mode 100644 index 0000000..d50a6ea --- /dev/null +++ b/public/css/tetris.css @@ -0,0 +1,31 @@ +body { + background-color: rgb(0, 0, 0); + background-image: url(http://www.zingerbugimages.com/backgrounds/charcoal_gray_mini_bricks_seamless_pattern.gif); + /*background-position: top left;*/ + /*background-repeat: repeat; + background-attachment: fixed;*/ + text-align: left; +} + +#score { + font-family: serif; + font-size: 3em; + width: 250px; + height: 50px; + background-color: yellow; + box-shadow: 10px 10px 5px #888888; + padding-right: 30px; +} + +canvas { + border: outset 10px #fff; + height: 90vh; + border-style: inset; +} + +h1 { + font-family: Helvetica, Arial, sans-serif; + font-weight: bold; + font-size: 6em; + text-align: right; + } diff --git a/public/js/tetris.js b/public/js/tetris.js index 6eb954f..99e209c 100644 --- a/public/js/tetris.js +++ b/public/js/tetris.js @@ -1,161 +1,26 @@ const canvas = document.getElementById('tetris'); const context = canvas.getContext('2d'); -context.scale(20, 20); - -context.fillStyle = "#000"; -context.fillRect(0,0, canvas.width, canvas.height); - -const I = [ - [ - [0, 0, 0, 0], - [1, 1, 1, 1], - [0, 0, 0, 0], - [0, 0, 0, 0], - ], - [ - [0, 0, 1, 0], - [0, 0, 1, 0], - [0, 0, 1, 0], - [0, 0, 1, 0], - ], - [ - [0, 0, 0, 0], - [0, 0, 0, 0], - [1, 1, 1, 1], - [0, 0, 0, 0], - ], - [ - [0, 1, 0, 0], - [0, 1, 0, 0], - [0, 1, 0, 0], - [0, 1, 0, 0], - ] -]; - -const J = [ - [ - [1, 0, 0], - [1, 1, 1], - [0, 0, 0] - ], - [ - [0, 1, 1], - [0, 1, 0], - [0, 1, 0] - ], - [ - [0, 0, 0], - [1, 1, 1], - [0, 0, 1] - ], - [ - [0, 1, 0], - [0, 1, 0], - [1, 1, 0] - ] -]; - -const L = [ - [ - [0, 0, 1], - [1, 1, 1], - [0, 0, 0] - ], - [ - [0, 1, 0], - [0, 1, 0], - [0, 1, 1] - ], - [ - [0, 0, 0], - [1, 1, 1], - [1, 0, 0] - ], - [ - [1, 1, 0], - [0, 1, 0], - [0, 1, 0] - ] -]; -const O = [ - [ - [0, 0, 0, 0], - [0, 1, 1, 0], - [0, 1, 1, 0], - [0, 0, 0, 0], - ] -]; +context.scale(20, 20); -const S = [ - [ - [0, 1, 1], - [1, 1, 0], - [0, 0, 0] - ], - [ - [0, 1, 0], - [0, 1, 1], - [0, 0, 1] - ], - [ - [0, 0, 0], - [0, 1, 1], - [1, 1, 0] - ], - [ - [1, 0, 0], - [1, 1, 0], - [0, 1, 0] - ] -]; +function arenaSweep() { + let rowCount = 1; + outer: for(let y = arena.length - 1; y > 0; --y) { + for (let x = 0; x < arena[y].length; ++x) { + if(arena[y][x] === 0) { + continue outer; + } + } + const row = arena.splice(y, 1)[0].fill(0); + arena.unshift(row); + ++y; -const T = [ - [ - [0, 1, 0], - [1, 1, 1], - [0, 0, 0] - ], - [ - [0, 1, 0], - [0, 1, 1], - [0, 1, 0] - ], - [ - [0, 0, 0], - [1, 1, 1], - [0, 1, 0] - ], - [ - [0, 1, 0], - [1, 1, 0], - [0, 1, 0] - ] -]; + player.score += rowCount * 10; + rowCount *= 2; + } +} -const Z = [ - [ - [1, 1, 0], - [0, 1, 1], - [0, 0, 0] - ], - [ - [0, 0, 1], - [0, 1, 1], - [0, 1, 0] - ], - [ - [0, 0, 0], - [1, 1, 0], - [0, 1, 1] - ], - [ - [0, 1, 0], - [1, 1, 0], - [1, 0, 0] - ] -]; function collide(arena, player) { const [m, o] = [player.matrix, player.position]; @@ -177,6 +42,65 @@ function createMatrix(width, height) { return matrix; } +function createPiece(type){ + if(type === "T") { + return [ + [0, 0, 0], + [1, 1, 1], + [0, 1, 0], + ]; + } else if(type === "O") { + return [ + [2, 2], + [2, 2], + ]; + } else if(type === "L") { + return [ + [0, 3, 0], + [0, 3, 0], + [0, 3, 3], + ]; +} else if(type === "J") { + return [ + [0, 4, 0], + [0, 4, 0], + [4, 4, 0], + ]; +} else if(type === "I") { + return [ + [0, 5, 0, 0], + [0, 5, 0, 0], + [0, 5, 0, 0], + [0, 5, 0, 0], + ]; +}else if(type === "S") { + return [ + [0, 6, 6], + [6, 6, 0], + [0, 0, 0], + ]; + }else if(type === "Z") { + return [ + [7, 7, 0], + [0, 7, 7], + [0, 0, 0], + ]; + } +} + +const piecesColors = [ + null, + 'red', + 'blue', + 'Yellow', + 'green', + 'purple', + 'orange', + 'pink', +]; + + + function draw() { context.fillStyle = "#000"; @@ -185,11 +109,12 @@ function draw() { drawMatrix(player.matrix, player.position); } + function drawMatrix(matrix, offset) { matrix.forEach((row, y) => { row.forEach((value, x) => { if(value !== 0) { - context.fillStyle = "red"; + context.fillStyle = piecesColors[value]; context.fillRect(x + offset.x, y + offset.y, 1,1); @@ -198,6 +123,7 @@ matrix.forEach((row, y) => { }); } + function merge(arena, player) { player.matrix.forEach((row, y) => { row.forEach((value, x) => { @@ -212,15 +138,64 @@ function playerDrop() { if(collide(arena, player)) { player.position.y--; merge(arena, player); - player.position.y = 0; + playerReset(); + arenaSweep(); + updateScore(); } dropCounter = 0; } +function playerMove(direction) { + player.position.x += direction; + if(collide(arena, player)) { + player.position.x -= direction; + } +} + + + + + + function playerRotate(direction) { + const position = player.position.x; + let offset = 1; + rotate(player.matrix, direction); + while (collide(arena, player)) { + player.position.x += offset; + offset = -(offset + (offset > 0 ? 1 : -1)); + if (offset > player.matrix[0].lenght) { + rotate(player.matrix, -direction); + player.position.x = position; + return; + } + } + } + +function rotate(matrix, direction){ + for(let y = 0; y < matrix.length; ++y) { + for (let x = 0; x < y; ++x) { + [ + matrix[x][y], + matrix[y][x], + ] = [ + matrix[y][x], + matrix[x][y], + ]; + } + } + + if (direction > 0) { + matrix.forEach(row => row.reverse()); + } else { + matrix.reverse(); + } +} + let dropCounter = 0; let dropInterval = 1000; let lastTime = 0; + function update(time = 0) { const deltaTime = time - lastTime; lastTime = time; @@ -230,27 +205,91 @@ function update(time = 0) { playerDrop(); } + draw(); requestAnimationFrame(update); } +function levelSpeed() { + if (score > 30) { + let dropInterval = 3000; + + } +} console.log(score) +levelSpeed() + +function updateScore() { + document.getElementById('score').innerText = "Score: " +player.score; +} + const arena = createMatrix(12,20); -let matrix = I[0]; const player = { - position:{x:5, y:5}, - matrix:matrix, + position:{x:0, y:0}, + matrix:null, + score: 0, } document.addEventListener('keydown', event => { if (event.keyCode === 37) { - player.position.x--; + playerMove(-1); } else if ( event.keyCode === 39) { - player.position.x++; - } else if ( event.keyCode === 40) + playerMove(1); + } else if ( event.keyCode === 40) { playerDrop(); + } else if ( event.keyCode === 81) { + playerRotate(-1); + } else if ( event.keyCode === 87) { + playerRotate(1); + } }); -update(); +$("#alert_text").hide(); +$("#tryAgain").hide(); + + + +function playerReset() { + const pieces = "ILJOTSZ"; + player.matrix = createPiece(pieces[pieces.length * Math.random() | 0]); + player.position.y = 0; + player.position.x = (arena[0].length / 2 | 0) - (player.matrix[0].length / 2 | 0); + + if(collide(arena, player)) { + arena.forEach(row => row.fill(0)); + player.score = 0; + + $(function() { + $("#alert_text").show(); + $("#tryAgain").show(); + $( "#status" ).dialog(); + $("#tryAgain").click(function(){ + + }) + update(); + }) + + updateScore(); + } + +} +// } + + +playerReset(); +updateScore(); +draw() +$('#pause').click(update); + + +$('#exit').click(function() { + window.location.href='index.html' +}); + +$( "#start" ).click(function() { + update(); + playerDrop(); + $("#start").html('RESUME'); +}); diff --git a/public/tetris.html b/public/tetris.html index 0e27ebd..1afb609 100644 --- a/public/tetris.html +++ b/public/tetris.html @@ -1,13 +1,32 @@ - - - Tetris - - - + + + + + + + + Tetris + + + + + + + + +
+ +
+
+
+

GAME OVER!

+

Try again

+
+ - - - + + +