forked from Spandan-Bhattacharya/Solve_it
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Added Tetris Game (Spandan-Bhattacharya#290)
- Loading branch information
1 parent
eab3963
commit 537e8f2
Showing
4 changed files
with
349 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,271 @@ | ||
document.getElementById('restartButton').addEventListener('click', restartGame); | ||
function restartGame() { | ||
cancelAnimationFrame(rAF); | ||
gameOver = false; | ||
|
||
for (let row = -2; row < playfield.length; row++) { | ||
for (let col = 0; col < playfield[row].length; col++) { | ||
playfield[row][col] = 0; | ||
} | ||
} | ||
|
||
tetrominoSequence.length = 0; | ||
tetromino = getNextTetromino(); | ||
|
||
rAF = requestAnimationFrame(loop); | ||
} | ||
function getRandomInt(min, max) { | ||
min = Math.ceil(min); | ||
max = Math.floor(max); | ||
|
||
return Math.floor(Math.random() * (max - min + 1)) + min; | ||
} | ||
|
||
function generateSequence() { | ||
const sequence = ['I', 'J', 'L', 'O', 'S', 'T', 'Z']; | ||
|
||
while (sequence.length) { | ||
const rand = getRandomInt(0, sequence.length - 1); | ||
const name = sequence.splice(rand, 1)[0]; | ||
tetrominoSequence.push(name); | ||
} | ||
} | ||
|
||
// get the next tetromino in the sequence | ||
function getNextTetromino() { | ||
if (tetrominoSequence.length === 0) { | ||
generateSequence(); | ||
} | ||
|
||
const name = tetrominoSequence.pop(); | ||
const matrix = tetrominos[name]; | ||
|
||
const col = playfield[0].length / 2 - Math.ceil(matrix[0].length / 2); | ||
|
||
const row = name === 'I' ? -1 : -2; | ||
|
||
return { | ||
name: name, | ||
matrix: matrix, | ||
row: row, | ||
col: col | ||
}; | ||
} | ||
|
||
function rotate(matrix) { | ||
const N = matrix.length - 1; | ||
const result = matrix.map((row, i) => | ||
row.map((val, j) => matrix[N - j][i]) | ||
); | ||
|
||
return result; | ||
} | ||
|
||
function isValidMove(matrix, cellRow, cellCol) { | ||
for (let row = 0; row < matrix.length; row++) { | ||
for (let col = 0; col < matrix[row].length; col++) { | ||
if (matrix[row][col] && ( | ||
cellCol + col < 0 || | ||
cellCol + col >= playfield[0].length || | ||
cellRow + row >= playfield.length || | ||
|
||
playfield[cellRow + row][cellCol + col]) | ||
) { | ||
return false; | ||
} | ||
} | ||
} | ||
|
||
return true; | ||
} | ||
|
||
function placeTetromino() { | ||
for (let row = 0; row < tetromino.matrix.length; row++) { | ||
for (let col = 0; col < tetromino.matrix[row].length; col++) { | ||
if (tetromino.matrix[row][col]) { | ||
|
||
if (tetromino.row + row < 0) { | ||
return showGameOver(); | ||
} | ||
|
||
playfield[tetromino.row + row][tetromino.col + col] = tetromino.name; | ||
} | ||
} | ||
} | ||
|
||
for (let row = playfield.length - 1; row >= 0;) { | ||
if (playfield[row].every(cell => !!cell)) { | ||
|
||
for (let r = row; r >= 0; r--) { | ||
for (let c = 0; c < playfield[r].length; c++) { | ||
playfield[r][c] = playfield[r - 1][c]; | ||
} | ||
} | ||
} | ||
else { | ||
row--; | ||
} | ||
} | ||
|
||
tetromino = getNextTetromino(); | ||
} | ||
|
||
function showGameOver() { | ||
cancelAnimationFrame(rAF); | ||
gameOver = true; | ||
|
||
context.fillStyle = 'black'; | ||
context.globalAlpha = 0.75; | ||
context.fillRect(0, canvas.height / 2 - 30, canvas.width, 60); | ||
|
||
context.globalAlpha = 1; | ||
context.fillStyle = 'white'; | ||
context.font = '36px monospace'; | ||
context.textAlign = 'center'; | ||
context.textBaseline = 'middle'; | ||
context.fillText('GAME OVER!', canvas.width / 2, canvas.height / 2); | ||
} | ||
|
||
const canvas = document.getElementById('game'); | ||
const context = canvas.getContext('2d'); | ||
const grid = 32; | ||
const tetrominoSequence = []; | ||
|
||
const playfield = []; | ||
|
||
for (let row = -2; row < 20; row++) { | ||
playfield[row] = []; | ||
|
||
for (let col = 0; col < 10; col++) { | ||
playfield[row][col] = 0; | ||
} | ||
} | ||
|
||
const tetrominos = { | ||
'I': [ | ||
[0, 0, 0, 0], | ||
[1, 1, 1, 1], | ||
[0, 0, 0, 0], | ||
[0, 0, 0, 0] | ||
], | ||
'J': [ | ||
[1, 0, 0], | ||
[1, 1, 1], | ||
[0, 0, 0], | ||
], | ||
'L': [ | ||
[0, 0, 1], | ||
[1, 1, 1], | ||
[0, 0, 0], | ||
], | ||
'O': [ | ||
[1, 1], | ||
[1, 1], | ||
], | ||
'S': [ | ||
[0, 1, 1], | ||
[1, 1, 0], | ||
[0, 0, 0], | ||
], | ||
'Z': [ | ||
[1, 1, 0], | ||
[0, 1, 1], | ||
[0, 0, 0], | ||
], | ||
'T': [ | ||
[0, 1, 0], | ||
[1, 1, 1], | ||
[0, 0, 0], | ||
] | ||
}; | ||
|
||
const colors = { | ||
'I': 'cyan', | ||
'O': 'yellow', | ||
'T': 'purple', | ||
'S': 'green', | ||
'Z': 'red', | ||
'J': 'blue', | ||
'L': 'orange' | ||
}; | ||
|
||
let count = 0; | ||
let tetromino = getNextTetromino(); | ||
let rAF = null; | ||
let gameOver = false; | ||
|
||
function loop() { | ||
rAF = requestAnimationFrame(loop); | ||
context.clearRect(0, 0, canvas.width, canvas.height); | ||
|
||
for (let row = 0; row < 20; row++) { | ||
for (let col = 0; col < 10; col++) { | ||
if (playfield[row][col]) { | ||
const name = playfield[row][col]; | ||
context.fillStyle = colors[name]; | ||
|
||
context.fillRect(col * grid, row * grid, grid - 1, grid - 1); | ||
} | ||
} | ||
} | ||
|
||
if (tetromino) { | ||
|
||
if (++count > 35) { | ||
tetromino.row++; | ||
count = 0; | ||
|
||
if (!isValidMove(tetromino.matrix, tetromino.row, tetromino.col)) { | ||
tetromino.row--; | ||
placeTetromino(); | ||
} | ||
} | ||
|
||
context.fillStyle = colors[tetromino.name]; | ||
|
||
for (let row = 0; row < tetromino.matrix.length; row++) { | ||
for (let col = 0; col < tetromino.matrix[row].length; col++) { | ||
if (tetromino.matrix[row][col]) { | ||
|
||
context.fillRect((tetromino.col + col) * grid, (tetromino.row + row) * grid, grid - 1, grid - 1); | ||
} | ||
} | ||
} | ||
} | ||
} | ||
|
||
document.addEventListener('keydown', function (e) { | ||
if (gameOver) return; | ||
|
||
if (e.which === 37 || e.which === 39) { | ||
const col = e.which === 37 | ||
? tetromino.col - 1 | ||
: tetromino.col + 1; | ||
|
||
if (isValidMove(tetromino.matrix, tetromino.row, col)) { | ||
tetromino.col = col; | ||
} | ||
} | ||
|
||
if (e.which === 38) { | ||
const matrix = rotate(tetromino.matrix); | ||
if (isValidMove(matrix, tetromino.row, tetromino.col)) { | ||
tetromino.matrix = matrix; | ||
} | ||
} | ||
|
||
if (e.which === 40) { | ||
const row = tetromino.row + 1; | ||
|
||
if (!isValidMove(tetromino.matrix, row, tetromino.col)) { | ||
tetromino.row = row - 1; | ||
|
||
placeTetromino(); | ||
return; | ||
} | ||
|
||
tetromino.row = row; | ||
} | ||
}); | ||
|
||
rAF = requestAnimationFrame(loop); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
<!DOCTYPE html> | ||
<html> | ||
<head> | ||
<title>Tetris Game</title> | ||
<meta charset="UTF-8"> | ||
<link rel="stylesheet" href="./style.css"> | ||
</head> | ||
<body background="../assets/bg.webp"> | ||
<div id="container"> | ||
|
||
<canvas width="320" height="640" id="game"></canvas> | ||
<div class="btn"> | ||
<button id="restartButton">Restart</button> | ||
<a href="../index.html"><button>Back to Home</button></a> | ||
</div> | ||
</div> | ||
<script src="./app.js"></script> | ||
</body> | ||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
html, body { | ||
height: 100%; | ||
margin: 0; | ||
} | ||
|
||
body { | ||
display: flex; | ||
align-items: center; | ||
justify-content: center; | ||
} | ||
|
||
canvas { | ||
border: 1px solid white; | ||
height: 80%; | ||
} | ||
#container{ | ||
display: flex; | ||
align-items: center; | ||
justify-content: center; | ||
flex-direction: column; | ||
height: 100%; | ||
} | ||
|
||
button { | ||
margin-top: 20px; | ||
padding: 10px 20px; | ||
font-size: 16px; | ||
background-color: #1665cc; | ||
color: #fff; | ||
border: none; | ||
border-radius: 4px; | ||
cursor: pointer; | ||
transition: all 0.3s ease; | ||
margin-right: 1rem; | ||
} | ||
|
||
.btn{ | ||
display: flex; | ||
justify-content: space-evenly; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters