基于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> 运行。

相关推荐
学渣y34 分钟前
React状态管理-对state进行保留和重置
javascript·react.js·ecmascript
_龙衣1 小时前
将 swagger 接口导入 apifox 查看及调试
前端·javascript·css·vue.js·css3
struggle20252 小时前
continue通过我们的开源 IDE 扩展和模型、规则、提示、文档和其他构建块中心,创建、共享和使用自定义 AI 代码助手
javascript·ide·python·typescript·开源
x-cmd2 小时前
[250512] Node.js 24 发布:ClangCL 构建,升级 V8 引擎、集成 npm 11
前端·javascript·windows·npm·node.js
夏之小星星3 小时前
el-tree结合checkbox实现数据回显
前端·javascript·vue.js
为美好的生活献上中指4 小时前
java每日精进 5.11【WebSocket】
java·javascript·css·网络·sql·websocket·网络协议
拖孩6 小时前
【Nova UI】十五、打造组件库之滚动条组件(上):滚动条组件的起步与进阶
前端·javascript·css·vue.js·ui组件库
苹果电脑的鑫鑫6 小时前
element中表格文字剧中可以使用的属性
javascript·vue.js·elementui
一丝晨光7 小时前
数值溢出保护?数值溢出应该是多少?Swift如何让整数计算溢出不抛出异常?类型最大值和最小值?
java·javascript·c++·rust·go·c·swift
Wannaer7 小时前
从 Vue3 回望 Vue2:响应式的内核革命
前端·javascript·vue.js