Tetris Game
Score: 0
Game Over
<!DOCTYPE html>
<html>
<head>
<title>Tetris Game</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
body {
background-color: #000000;
color: #ffffff;
font-family: 'Courier New', Courier, monospace;
font-size: 24px;
letter-spacing: 2px;
text-align: center;
}
canvas {
border: 2px solid #ffffff;
}
</style>
</head>
<body>
<canvas id="canvas" width="240" height="480"></canvas>
<script>
// Tetris Game Logic
const canvas = document.getElementById('canvas');
const context = canvas.getContext('2d');
const tetrisMatrix = createMatrix(12, 20);
const colors = [
null,
'#ff0000',
'#00ff00',
'#0000ff',
'#ffff00',
'#00ffff',
'#ff00ff',
'#ffffff'
];
let player = {
matrix: null,
position: {x: 0, y: 0},
score: 0
};
let dropCounter = 0;
let dropInterval = 1000;
let lastTime = 0;
let gameOver = false;
function createMatrix(width, height) {
const matrix = [];
while (height--) {
matrix.push(new Array(width).fill(0));
}
return matrix;
}
function drawMatrix(matrix, offset) {
matrix.forEach((row, y) => {
row.forEach((value, x) => {
if (value !== 0) {
context.fillStyle = colors[value];
context.fillRect(
x + offset.x,
y + offset.y,
1, 1
);
}
});
});
}
function collide(tetrisMatrix, player) {
const [matrix, offset] = [player.matrix, player.position];
for (let y = 0; y < matrix.length; ++y) {
for (let x = 0; x < matrix[y].length; ++x) {
if (matrix[y][x] !== 0 &&
(tetrisMatrix[y + offset.y] &&
tetrisMatrix[y + offset.y][x + offset.x]) !== 0) {
return true;
}
}
}
return false;
}
function mergeMatrix(tetrisMatrix, player) {
player.matrix.forEach((row, y) => {
row.forEach((value, x) => {
if (value !== 0) {
tetrisMatrix[y + player.position.y][x + player.position.x] = value;
}
});
});
}
function rotateMatrix(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();
}
}
function rotate(player, direction) {
const matrix = player.matrix;
rotateMatrix(matrix, direction);
if (collide(tetrisMatrix, player)) {
rotateMatrix(matrix, -direction);
}
}
function drop() {
dropCounter = 0;
player.position.y++;
if (collide(tetrisMatrix, player)) {
player.position.y--;
mergeMatrix(tetrisMatrix, player);
playerReset();
gameOver = collide(tetrisMatrix, player);
}
}
function playerMove(offset) {
player.position.x += offset;
if (collide(tetrisMatrix, player)) {
player.position.x -= offset;
}
}
function playerReset() {
const pieces = 'ILJOTSZ';
player.matrix = createPiece(pieces[pieces.length * Math.random() | 0]);
player.position.y = 0;
player.position.x = (tetrisMatrix[0].length / 2 | 0) - (player.matrix[0].length / 2 | 0);
if (collide(tetrisMatrix, player)) {
tetrisMatrix.forEach(row => row.fill(0));
player.score = 0;
gameOver = true;
}
}
function playerDrop() {
while (!collide(tetrisMatrix, player)) {
player.position.y++;
}
player.position.y--;
drop();
}
function playerRandomize() {
const piece = createPiece('ILJOTSZ'[Math.floor(Math.random() * 7)]);
player.matrix = piece.matrix;
player.color = piece.color;
player.position.y = 0;
player.position.x = (tetrisMatrix[0].length / 2 | 0) - (player.matrix[0].length / 2 | 0);
if (collide(tetrisMatrix, player)) {
tetrisMatrix.forEach(row => row.fill(0));
player.score = 0;
gameOver = true;
}
}
function createPiece(type) {
switch (type) {
case 'I':
return {
matrix: [
[0, 0, 0, 0],
[1, 1, 1, 1],
[0, 0, 0, 0],
[0, 0, 0, 0]
],
color: '#00ffff'
};
case 'L':
return {
matrix: [
[0, 0, 0],
[1, 1, 1],
[1, 0, 0]
],
color: '#ff8000'
};
case 'J':
return {
matrix: [
[0, 0, 0],
[1, 1, 1],
[0, 0, 1]
],
color: '#0000ff'
};
case 'O':
return {
matrix: [
[1, 1],
[1, 1]
],
color: '#ffff00'
};
case 'T':
return {
matrix: [
[0, 0, 0],
[1, 1, 1],
[0, 1, 0]
],
color: '#cc00cc'
};
case 'S':
return {
matrix: [
[0, 0, 0],
[0, 1, 1],
[1, 1, 0]
],
color: '#00ff00'
};
case 'Z':
return {
matrix: [
[0, 0, 0],
[1, 1, 0],
[0, 1, 1]
],
color: '#ff0000'
};
}
}
function updateScore() {
document.getElementById('score').innerHTML = player.score;
}
function update(time = 0) {
if (gameOver) {
document.getElementById('gameover').style.display = 'block';
document.getElementById('start').style.display = 'block';
return;
}
const deltaTime = time - lastTime;
lastTime = time;
dropCounter += deltaTime;
if (dropCounter > dropInterval) {
drop();
}
context.fillStyle = '#000000';
context.fillRect(0, 0, canvas.width, canvas.height);
drawMatrix(tetrisMatrix, {x: 0, y: 0});
drawMatrix(player.matrix, player.position);
updateScore();
requestAnimationFrame(update);
}
document.addEventListener('keydown', event => {
if (event.keyCode === 37) {
playerMove(-1);
} else if (event.keyCode === 39) {
playerMove(1);
} else if (event.keyCode === 40) {
playerDrop();
} else if (event.keyCode === 81) {
rotate(player, -1);
} else if (event.keyCode === 87) {
rotate(player, 1);
}
});
function startGame() {
document.getElementById('gameover').style.display = 'none';
document.getElementById('start').style.display = 'none';
dropInterval = 1000;
player.score = 0;
playerRandomize();
updateScore();
gameOver = false;
requestAnimationFrame(update);
}
document.getElementById('start').addEventListener('click', () => {
startGame();
});
</script>
<h2>Tetris Game</h2>
<div>Score: <span id="score">0</span></div>
<div id="gameover">Game Over</div>
<button id="start">Start Game</button>
</body>
</html>