Simple HTML Tetris Game with Instructions
<html>
<head>
<title>Tetris</title>
<style>
body {
background-color: #222;
color: #eee;
font-family: sans-serif;
text-align: center;
}
#canvas {
border: 5px solid #444;
}
</style>
</head>
<body>
<h1>Tetris</h1>
<canvas id="canvas" width="200" height="400"></canvas>
<script>
let canvas = document.getElementById('canvas');
let ctx = canvas.getContext('2d');
let score = 0;
let level = 1;
let lines = 0;
let board = [];
for (let i = 0; i < 20; i++) {
board[i] = new Array(10).fill(0);
}
let current;
let currentX = 4;
let currentY = 0;
let pieces = [
[1, 1, 1, 1],
[2, 2, 2],
[3, 3, 3],
[4, 4],
[5, 5, 5],
[6, 6, 6],
[7, 7, 7]
];
let colors = ['#2C3E50', '#E74C3C', '#2980B9', '#8E44AD', '#F1C40F', '#27AE60', '#16A085'];
function draw(){
ctx.fillStyle = '#222';
ctx.fillRect(0, 0, canvas.width, canvas.height);
drawBoard();
drawPiece();
drawScore();
}
function drawBoard(){
for (let r = 0; r < 20; r++){
for (let c = 0; c < 10; c++){
if (board[r][c] !== 0) {
ctx.fillStyle = colors[board[r][c] - 1];
ctx.fillRect(c * 20, r * 20, 20, 20);
}
}
}
}
function drawPiece(){
for (let r = 0; r < current.length; r++){
for (let c = 0; c < current[r].length; c++){
if (current[r][c] !== 0) {
ctx.fillStyle = colors[current[r][c] - 1];
ctx.fillRect((currentX + c) * 20, (currentY + r) * 20, 20, 20);
}
}
}
}
function drawScore(){
ctx.fillStyle = '#eee';
ctx.font = '20px sans-serif';
ctx.fillText(`Score: ${score}`, 110, 20);
ctx.fillText(`Level: ${level}`, 110, 40);
ctx.fillText(`Lines: ${lines}`, 110, 60);
}
function newPiece(){
let random = Math.floor(Math.random() * pieces.length);
current = pieces[random];
currentX = 4;
currentY = 0;
}
function tick(){
if (valid(0, 1)) {
currentY++;
} else {
freeze();
clearLines();
newPiece();
}
}
function valid(offsetX, offsetY, newCurrent){
offsetX = offsetX || 0;
offsetY = offsetY || 0;
offsetX = currentX + offsetX;
offsetY = currentY + offsetY;
newCurrent = newCurrent || current;
for (let r = 0; r < newCurrent.length; r++){
for (let c = 0; c < newCurrent[r].length; c++){
if (newCurrent[r][c] !== 0 &&
(board[r + offsetY] === undefined ||
board[r + offsetY][c + offsetX] === undefined ||
board[r + offsetY][c + offsetX] !== 0)) {
return false;
}
}
}
return true;
}
function freeze(){
for (let r = 0; r < current.length; r++){
for (let c = 0; c < current[r].length; c++){
if (current[r][c] !== 0) {
board[r + currentY][c + currentX] = current[r][c];
}
}
}
}
function rotate(dir){
let offset = 1;
let kick = 0;
let newCurrent = [];
if (dir === 'left') {
offset = -1;
kick = -1;
}
for (let r = 0; r < current.length; r++){
newCurrent[r] = [];
for (let c = 0; c < current[r].length; c++){
newCurrent[r][c] = current[current.length - c - 1][r];
}
}
if (valid(offset, 0, newCurrent)) {
current = newCurrent;
currentX += offset;
} else if (valid(kick, 0, newCurrent)) {
current = newCurrent;
currentX += kick;
}
}
function clearLines(){
for (let r = 0; r < board.length; r++){
let rowFilled = true;
for (let c = 0; c < board[r].length; c++){
if (board[r][c] === 0) {
rowFilled = false;
break;
}
}
if (rowFilled) {
lines++;
score += level * 10;
for (let y = r; y > 1; y--) {
for (let c = 0; c < 10; c++) {
board[y][c] = board[y - 1][c];
}
}
for (let c = 0; c < 10; c++) {
board[0][c] = 0;
}
}
}
}
document.addEventListener('keydown', e => {
if (e.keyCode === 37 && valid(-1, 0)) {
currentX--;
} else if (e.keyCode === 38 && valid(0, 0)) {
rotate('right');
} else if (e.keyCode === 39 && valid(1, 0)) {
currentX++;
} else if (e.keyCode === 40 && valid(0, 1)) {
currentY++;
} else if (e.keyCode === 32 && valid(0, 0)) {
rotate('left');
}
});
newPiece();
setInterval(() => {
tick();
draw();
}, 1000);
</script>
</body>
</html>
原文地址: https://www.cveoy.top/t/topic/lmjL 著作权归作者所有。请勿转载和采集!