基于Canvas和和原生JS实现俄罗斯方块小游戏

这里是一个完整的H5俄罗斯方块游戏,使用了 HTML + CSS + JavaScript (原生) 实现,支持基本的俄罗斯方块玩法,如:

✅ 方块自动下落

✅ 方向键控制移动、旋转、加速下落

✅ 方块堆叠、消行

✅ 计分系统

canvas 上绘制游戏,并使用 requestAnimationFrame 进行流畅的动画渲染。下面是完整的代码:

javascript 复制代码
const canvas = document.getElementById("tetris");
const ctx = canvas.getContext("2d");
const ROWS = 20;
const COLS = 10;
const SIZE = 30; // 每个格子的大小

// 定义俄罗斯方块的形状
const SHAPES = [
  [[1, 1, 1, 1]], // I
  [[1, 1], [1, 1]], // O
  [[0, 1, 0], [1, 1, 1]], // T
  [[1, 1, 0], [0, 1, 1]], // S
  [[0, 1, 1], [1, 1, 0]], // Z
  [[1, 0, 0], [1, 1, 1]], // J
  [[0, 0, 1], [1, 1, 1]], // L
];

// 颜色数组
const COLORS = ["cyan", "yellow", "purple", "green", "red", "blue", "orange"];

let board = Array.from({ length: ROWS }, () => Array(COLS).fill(0));
let currentPiece;
let gameOver = false;
let score = 0;

// 生成新方块
function newPiece() {
  const index = Math.floor(Math.random() * SHAPES.length);
  currentPiece = {
    shape: SHAPES[index],
    color: COLORS[index],
    row: 0,
    col: Math.floor(COLS / 2) - 1,
  };
}
newPiece();

// 画一个方块
function drawBlock(x, y, color) {
  ctx.fillStyle = color;
  ctx.fillRect(x * SIZE, y * SIZE, SIZE, SIZE);
  ctx.strokeStyle = "black";
  ctx.strokeRect(x * SIZE, y * SIZE, SIZE, SIZE);
}

// 画游戏面板
function drawBoard() {
  ctx.clearRect(0, 0, canvas.width, canvas.height);
  for (let r = 0; r < ROWS; r++) {
    for (let c = 0; c < COLS; c++) {
      if (board[r][c]) {
        drawBlock(c, r, board[r][c]);
      }
    }
  }
  drawPiece();
}

// 画当前下落的方块
function drawPiece() {
  currentPiece.shape.forEach((row, r) => {
    row.forEach((cell, c) => {
      if (cell) {
        drawBlock(currentPiece.col + c, currentPiece.row + r, currentPiece.color);
      }
    });
  });
}

// 碰撞检测
function isValidMove(offsetRow, offsetCol, shape) {
  return shape.every((row, r) =>
    row.every((cell, c) => {
      if (!cell) return true;
      let newRow = currentPiece.row + r + offsetRow;
      let newCol = currentPiece.col + c + offsetCol;
      return (
        newRow >= 0 &&
        newRow < ROWS &&
        newCol >= 0 &&
        newCol < COLS &&
        !board[newRow][newCol]
      );
    })
  );
}

// 移动方块
function movePiece(offsetRow, offsetCol) {
  if (isValidMove(offsetRow, offsetCol, currentPiece.shape)) {
    currentPiece.row += offsetRow;
    currentPiece.col += offsetCol;
  }
}

// 旋转方块
function rotatePiece() {
  const rotated = currentPiece.shape[0].map((_, c) =>
    currentPiece.shape.map(row => row[c]).reverse()
  );
  if (isValidMove(0, 0, rotated)) {
    currentPiece.shape = rotated;
  }
}

// 触底逻辑
function placePiece() {
  currentPiece.shape.forEach((row, r) => {
    row.forEach((cell, c) => {
      if (cell) {
        board[currentPiece.row + r][currentPiece.col + c] = currentPiece.color;
      }
    });
  });
  clearRows();
  newPiece();
  if (!isValidMove(0, 0, currentPiece.shape)) {
    gameOver = true;
  }
}

// 消行逻辑
function clearRows() {
  board = board.filter(row => row.some(cell => !cell));
  while (board.length < ROWS) {
    board.unshift(Array(COLS).fill(0));
    score += 10;
  }
}

// 游戏循环
function update() {
  if (!gameOver) {
    if (isValidMove(1, 0, currentPiece.shape)) {
      movePiece(1, 0);
    } else {
      placePiece();
    }
    drawBoard();
    document.getElementById("score").innerText = score;
    setTimeout(update, 500);
  } else {
    alert("游戏结束!");
  }
}
update();

// 监听键盘事件
document.addEventListener("keydown", (event) => {
  if (gameOver) return;
  if (event.key === "ArrowLeft") movePiece(0, -1);
  if (event.key === "ArrowRight") movePiece(0, 1);
  if (event.key === "ArrowDown") movePiece(1, 0);
  if (event.key === "ArrowUp") rotatePiece();
  drawBoard();
});

说明:

  • 使用 canvas 进行绘制
  • 方块随机生成并自动下落
  • 方向键:
    • 左/右键 移动
    • 下键 加速下落
    • 上键 旋转
  • 触底后自动消行并累加得分
  • 游戏结束提示 alert("游戏结束!")

你可以直接将这段代码放入 index.html 页面,并配合 <canvas> 运行。

相关推荐
Heo5 小时前
大厂前端调试不能只会debugger
前端·javascript·面试
windliang6 小时前
Claude Code 源码分析(十二):错误处理与自动恢复:让 Agent 稳定运行
前端·javascript·面试
默_笙7 小时前
🛬 前端路由的"高级玩法":懒加载、404、鉴权路由,一个都不能少(下篇)
前端·javascript
sunly_7 小时前
TypeScript:3、类型声明与类型推断
javascript·ubuntu·typescript
奥莱维8 小时前
【无标题】
java·前端·javascript
黄金决明子9 小时前
浏览器Window底层操作全解
前端·javascript
AI视觉网奇10 小时前
cannot import name ‘model_urls‘ from ‘torchvision.models.resnet‘
linux·前端·javascript
Sca_杰10 小时前
微信客服API对接速通
javascript·node.js
大家的林语冰11 小时前
👍 JS 还在进化,ES2026 正式推出,最新七大特性补全!
前端·javascript·json
铁皮饭盒11 小时前
DeepSeek V4 Pro 0813发布了, 也可以部署到 Codex 了
前端·javascript·后端