使用JS+CSS实现俄罗斯方块游戏

前提:

要在网页上实现一个适用于PC端和移动端的俄罗斯方块游戏,您可以使用HTML、CSS和JavaScript。HTML5的Canvas元素可以让您轻松地在网页上绘制图形。以下是一些实现该游戏的基本步骤:

设置HTML结构:

创建一个HTML文件,设置基本的HTML结构,包括<!DOCTYPE>, <html>, <head><body>标签。

<!DOCTYPE html>
<html lang="en">
<head>
 <meta charset="UTF-8">
 <meta name="viewport" content="width=device-width, initial-scale=1.0">
 <title>Tetris</title>
 <link rel="stylesheet" href="styles.css" rel="external nofollow" >
</head>
<body>
 <canvas id="gameCanvas" width="320" height="640"></canvas>
 <script src="tetris.js"></script>
</body>
</html>

创建CSS样式:

在一个名为styles.css的文件中设置基本的样式。例如,将游戏画布居中:

body {
 display: flex;
 justify-content: center;
 align-items: center;
 height: 100vh;
 margin: 0;
 background-color: #222;
}
 
canvas {
 border: 1px solid #fff;
}

编写JavaScript代码:

在一个名为tetris.js的文件中编写游戏的逻辑。实现以下功能:

  • 定义方块形状和颜色        
  • 初始化游戏变量和画布       
  • 定义游戏循环        
  • 处理用户输入        
  • 定义方块移动和旋转逻辑        
  • 检查并消除已填满的行        
  • 判断游戏结束条件        

响应式设计:

确保游戏在不同屏幕尺寸和设备上表现良好。

可通过CSS中的媒体查询实现:

@media (max-width: 600px) {
 canvas {
 width: 100%;
 height: auto;
 }
}

添加触摸事件支持:

为了使游戏在移动设备上正常运行,您需要处理触摸事件。可以使用JavaScript的touchstarttouchmovetouchend事件。根据用户的触摸行为来模拟键盘操作,如左右滑动来移动方块,向下滑动加速下落,向上滑动旋转方块。         

测试并优化:

在不同设备和浏览器上测试游戏,确保其正常运行。可根据需要进行调整和优化。

完成上述步骤后,您将成功创建一个适用于PC端和移动端的俄罗斯方块游戏。您可以根据需求调整游戏的外观和功能。

代码示例:

以下是一个使用JavaScript实现的基本俄罗斯方块游戏的示例代码。这份代码包括了第三点提到的游戏逻辑。请注意,这份代码仅为示例,您可能需要根据实际需求进行调整。

const canvas = document.getElementById("gameCanvas");
const ctx = canvas.getContext("2d");
const scale = 20;
 
const tetrominoes = [
 [
 [1, 1, 1],
 [0, 1, 0]
 ],
 [
 [1, 1],
 [1, 1]
 ],
 [
 [1, 1, 0],
 [0, 1, 1]
 ],
 [
 [0, 1, 1],
 [1, 1, 0]
 ],
 [
 [1, 1, 1, 1]
 ],
 [
 [1, 1, 1],
 [1, 0, 0]
 ],
 [
 [1, 1, 1],
 [0, 0, 1]
 ]
];
 
const colors = [
 "#00FFFF",
 "#FFFF00",
 "#FF00FF",
 "#00FF00",
 "#0000FF",
 "#FFA500",
 "#FF0000"
];
 
let board = Array.from({ length: canvas.height / scale }, () =>
 Array(canvas.width / scale).fill(0)
);
 
class Tetromino {
 constructor() {
 this.type = Math.floor(Math.random() * tetrominoes.length);
 this.shape = tetrominoes[this.type];
 this.color = colors[this.type];
 this.x = Math.floor(board[0].length / 2) - Math.ceil(this.shape[0].length / 2);
 this.y = 0;
 }
 
 draw() {
 this.shape.forEach((row, i) => {
 row.forEach((value, j) => {
 if (value) {
 ctx.fillStyle = this.color;
 ctx.fillRect((this.x + j) * scale, (this.y + i) * scale, scale, scale);
 ctx.strokeStyle = "#000";
 ctx.strokeRect((this.x + j) * scale, (this.y + i) * scale, scale, scale);
 }
 });
 });
 }
 
 move(dir) {
 this.x += dir;
 if (this.collides()) {
 this.x -= dir;
 return;
 }
 this.draw();
 }
 
 rotate() {
 const temp = this.shape;
 this.shape = this.transpose(this.shape);
 if (this.collides()) {
 this.shape = temp;
 return;
 }
 this.draw();
 }
 
 drop() {
 this.y += 1;
 if (this.collides()) {
 this.y -= 1;
 this.lock();
 this.checkLines();
 return new Tetromino();
 }
 this.draw();
 return this;
 }
 
 collides() {
 for (let y = 0; y < this.shape.length; y++) {
 for (let x = 0; x < this.shape[y].length; x++) {
 if (
 this.shape[y][x] &&
 (board[y + this.y] && board[y + this.y][x + this.x]) !== undefined
 ) {
 if (board[y + this.y][x + this.x]) {
 return true;
 }
 } else {
 return true;
 }
 }
 }
 return false;
}
 
lock() {
 this.shape.forEach((row, i) => {
 row.forEach((value, j) => {
 if (value) {
 board[this.y + i][this.x + j] = this.color;
 }
 });
 });
}
 
checkLines() {
 outer: for (let y = board.length - 1; y >= 0; ) {
 for (let x = 0; x < board[y].length; x++) {
 if (!board[y][x]) {
 y--;
 continue outer;
 }
 }
 board.splice(y, 1);
 board.unshift(Array(board[0].length).fill(0));
 }
}
 
transpose(matrix) {
 const rows = matrix.length;
 const cols = matrix[0].length;
 const result = Array.from({ length: cols }, () => Array(rows).fill(0));
 
 for (let y = 0; y < rows; y++) {
 for (let x = 0; x < cols; x++) {
 result[x][y] = matrix[y][x];
 }
 }
 
 return result.reverse();
}
}

function drawBoard() { ctx.fillStyle = "#000"; ctx.fillRect(0, 0, canvas.width, canvas.height);

board.forEach((row, y) => {
 row.forEach((value, x) => {
 if (value) {
 ctx.fillStyle = value;
 ctx.fillRect(x * scale, y * scale, scale, scale);
 ctx.strokeStyle = "#000";
 ctx.strokeRect(x * scale, y * scale, scale, scale);
 }
 });
});

let piece = new Tetromino(); let dropCounter = 0; let dropInterval = 1000; let lastTime = 0;

function update(time = 0) { const deltaTime = time - lastTime; lastTime = time;

dropCounter += deltaTime;
if (dropCounter > dropInterval) {
 piece = piece.drop();
 dropCounter = 0;
}
 
drawBoard();
piece.draw();
requestAnimationFrame(update);
}

update();

document.addEventListener("keydown", (event) => { if (event.key === "ArrowLeft") { piece.move(-1); } else if (event.key === "ArrowRight") { piece.move(1); } else if (event.key === "ArrowDown") { dropInterval = 50; } else if (event.key === "ArrowUp") { piece.rotate(); } });

document.addEventListener("keyup", (event) => { if (event.key === "ArrowDown") { dropInterval = 1000; } });

这段代码实现了一个简单的俄罗斯方块游戏,包括绘制游戏画布、方块的移动、旋转和下落、消除已填满的行等功能。为了使游戏更加完整和易于操作,您还需要根据第五点的指示为游戏添加触摸事件支持。

同时,也建议您根据自己的需求和喜好优化游戏的功能、外观和性能。

作者:A等天晴原文地址:https://blog.csdn.net/a871923942/article/details/129910359

%s 个评论

要回复文章请先登录注册