HTML Tetris Game Complete Code - Build Your Own Tetris Game
<!DOCTYPE html>
<html>
<head>
<title>Tetris</title>
<style type="text/css">
body {
margin: 0;
padding: 0;
background-color: #000;
}
canvas {
background-color: #eee;
}
</style>
<script type="text/javascript">
// the game itself
let game;
// when the window loads
window.onload = () => {
// create the game instance
game = new Tetris();
};
// Tetris class
class Tetris {
constructor() {
// game properties
this.canvas = document.createElement("canvas");
this.ctx = this.canvas.getContext("2d");
this.cols = 10;
this.rows = 20;
this.blockSize = 30;
this.width = this.blockSize * this.cols;
this.height = this.blockSize * this.rows;
// create the board
this.board = new Array(this.rows);
for (let r = 0; r < this.rows; r++) {
this.board[r] = new Array(this.cols);
}
// pieces that are used in the game
this.pieces = [
[1, 1, 1, 1],
[1, 1, 1, 0,
1],
[1, 1, 1, 0,
0, 0, 1],
[1, 1, 0, 0,
1, 1],
[1, 1, 0, 0,
0, 1, 1],
[0, 1, 1, 0,
1, 1],
[0, 1, 0, 0,
1, 1, 1]
];
// set the colors of the pieces
this.colors = ['cyan', 'blue', 'orange', 'yellow', 'green', 'purple', 'red'];
// start a new game
this.newGame();
}
// start a new game
newGame() {
// add the canvas to the body of the page
document.body.appendChild(this.canvas);
this.canvas.width = this.width;
this.canvas.height = this.height;
// add the listeners
this.ctx.canvas.addEventListener('keydown', this.keyDown.bind(this), false);
// start the game loop
this.interval = setInterval(this.update.bind(this), 1000);
// create a new piece
this.newPiece();
}
// game loop
update() {
// move the piece down
this.activePiece.y += 1;
// check if the piece hit the bottom or a block
if (this.checkCollision()) {
// if it did, add the piece to the board
this.addPiece();
// start a new piece
this.newPiece();
}
// check if there are any lines to clear
this.clearLines();
// update the board
this.updateBoard();
}
// create a new piece
newPiece() {
// random number for the pieces
let random = Math.floor(Math.random() * this.pieces.length);
// random number for the colors
let randomColor = Math.floor(Math.random() * this.colors.length);
// set the new piece
this.activePiece = {
x: 3,
y: 0,
shape: this.pieces[random],
color: this.colors[randomColor]
};
}
// update the board
updateBoard() {
// clear the board
this.ctx.clearRect(0, 0, this.width, this.height);
// draw the active piece
this.drawPiece(this.activePiece.x, this.activePiece.y, this.activePiece.shape, this.activePiece.color);
// draw the blocks in the board
for (let r = 0; r < this.rows; r++) {
for (let c = 0; c < this.cols; c++) {
// check if the block is set
if (this.board[r][c] !== 0) {
let blockX = c * this.blockSize;
let blockY = r * this.blockSize;
// draw the block
this.ctx.fillStyle = this.board[r][c];
this.ctx.fillRect(blockX, blockY, this.blockSize, this.blockSize);
this.ctx.strokeStyle = 'black';
this.ctx.strokeRect(blockX, blockY, this.blockSize, this.blockSize);
}
}
}
}
// draw a piece
drawPiece(x, y, shape, color) {
// loop through the shape
for (let r = 0; r < shape.length; r++) {
for (let c = 0; c < shape.length; c++) {
// check if the block is set
if (shape[r][c] !== 0) {
let blockX = (x + c) * this.blockSize;
let blockY = (y + r) * this.blockSize;
// draw the block
this.ctx.fillStyle = color;
this.ctx.fillRect(blockX, blockY, this.blockSize, this.blockSize);
this.ctx.strokeStyle = 'black';
this.ctx.strokeRect(blockX, blockY, this.blockSize, this.blockSize);
}
}
}
}
// move the piece left
movePieceLeft() {
this.activePiece.x -= 1;
if (this.checkCollision()) {
this.activePiece.x += 1;
}
}
// move the piece right
movePieceRight() {
this.activePiece.x += 1;
if (this.checkCollision()) {
this.activePiece.x -= 1;
}
}
// rotate the piece
rotatePiece() {
// get the next rotation
let nextRotation = this.activePiece.shape[(this.activePiece.shape.length + 1) % this.activePiece.shape.length];
// check if the rotation is valid
let valid = true;
for (let r = 0; r < nextRotation.length; r++) {
for (let c = 0; c < nextRotation.length; c++) {
// check if the block is set
if (nextRotation[r][c] !== 0) {
let x = this.activePiece.x + c;
let y = this.activePiece.y + r;
// check if it is inside the board
if (x < 0 || x >= this.cols || y >= this.rows) {
valid = false;
}
// check if it is inside a block
if (y < 0) {
continue;
}
if (this.board[y][x] !== 0) {
valid = false;
}
}
}
}
// set the new rotation
if (valid) {
this.activePiece.shape = nextRotation;
}
}
// check for collision
checkCollision() {
// loop through the piece
for (let r = 0; r < this.activePiece.shape.length; r++) {
for (let c = 0; c < this.activePiece.shape.length; c++) {
// check if the block is set
if (this.activePiece.shape[r][c] !== 0) {
let x = this.activePiece.x + c;
let y = this.activePiece.y + r;
// check if it is inside the board
if (x < 0 || x >= this.cols || y >= this.rows) {
return true;
}
// check if it is inside a block
if (y < 0) {
continue;
}
if (this.board[y][x] !== 0) {
return true;
}
}
}
}
return false;
}
// add the piece to the board
addPiece() {
// loop through the piece
for (let r = 0; r < this.activePiece.shape.length; r++) {
for (let c = 0; c < this.activePiece.shape.length; c++) {
// check if the block is set
if (this.activePiece.shape[r][c] !== 0) {
let x = this.activePiece.x + c;
let y = this.activePiece.y + r;
// check if it is inside the board
if (x < 0 || x >= this.cols || y >= this.rows) {
continue;
}
// add the block to the board
this.board[y][x] = this.activePiece.color;
}
}
}
}
// clear lines
clearLines() {
// loop through the rows
for (let r = 0; r < this.rows; r++) {
// check if the row is full
let full = true;
for (let c = 0; c < this.cols; c++) {
if (this.board[r][c] === 0) {
full = false;
break;
}
}
// clear the line
if (full) {
// shift the rows down
for (let i = r; i > 0; i--) {
this.board[i] = this.board[i - 1];
}
// reset the first row
this.board[0] = new Array(this.cols);
// increase the score
}
}
}
// key down listener
keyDown(e) {
// check which key was pressed
switch (e.keyCode) {
case 37: // left
this.movePieceLeft();
break;
case 38: // up
this.rotatePiece();
break;
case 39: // right
this.movePieceRight();
break;
case 40: // down
this.activePiece.y += 1;
if (this.checkCollision()) {
this.activePiece.y -= 1;
this.addPiece();
this.newPiece();
}
break;
}
}
}
</script>
</head>
<body>
</body>
</html>
原文地址: https://www.cveoy.top/t/topic/losE 著作权归作者所有。请勿转载和采集!