前言
继上一篇文章介绍贪吃蛇小游戏的实现方案后,本文继续讲解俄罗斯方块游戏的开发。相比贪吃蛇,俄罗斯方块的实现更加复杂,涉及方块旋转、多行消除、速度递增等机制。
通过这个案例,可以学习到如何用原生 JavaScript 实现经典的方块下落消除游戏。
项目结构
游戏放置在 source/ai-games/tetris/ 目录下,文件结构如下:
1 | source/ai-games/tetris/ |
与贪吃蛇相同的独立目录结构,便于管理和扩展更多游戏。
游戏页面实现
Canvas 画布
1 | <canvas id="game-canvas" width="240" height="400"></canvas> |
俄罗斯方块采用 12×20 网格,每个格子 20px,宽度较窄以适应竖屏布局。
样式设计
1 | canvas { |
使用蓝色主题(#2196F3)与贪吃蛇的绿色区分开。
核心逻辑实现
方块形状定义
游戏包含 7 种经典方块形状,用矩阵和颜色表示:
1 | const SHAPES = { |
每种方块用 0/1 矩阵表示形状,1 表示方块存在的位置。
游戏状态管理
1 | let board = []; // 12×20 游戏板,存储已落方块颜色 |
board 是二维数组,存储已固定在底部的方块颜色,空位为 0。
随机生成方块
1 | function randomPiece() { |
使用 map(row => [...row]) 实现矩阵的深拷贝,避免修改原始形状定义。
碰撞检测
1 | function checkCollision(matrix, x, y) { |
遍历方块的每个单元格,检查是否越界或与已落方块重叠。
方块旋转算法
1 | function rotate(matrix) { |
旋转原理:将矩阵的列变为行,实现 90 度顺时针旋转。例如:
1 | [[0,1,0], [[1,1,1], |
消除行逻辑
1 | function clearLines() { |
消除算法:
- 从底部向上扫描每一行
- 如果某行全满,移除该行
- 顶部插入新空行
- 上方行自动下移
- 计分:单行100分,双行400分,三行900分(平方递增)
固定方块
1 | function lockPiece() { |
将当前方块的每个单元格颜色写入游戏板,然后检查消除,最后生成新方块。
控制方式
键盘控制
1 | function handleKeydown(e) { |
按↓键时使用循环实现快速下落,直到无法继续为止。
触摸滑动控制
1 | canvas.addEventListener('touchend', function(e) { |
触摸控制逻辑:
- 水平滑动 → 左右移动
- 向上滑动 → 旋转
- 向下滑动 → 快速下落
速度递增机制
1 | function updateSpeed() { |
速度计算公式:dropInterval = Math.max(100, 800 - score / 500 * 80)
| 分数区间 | 下落间隔 |
|---|---|
| 0-499 | 800ms |
| 500-999 | 720ms |
| 1000-1499 | 640ms |
| … | … |
| 3500+ | 100ms(最快) |
绘制系统
1 | function draw() { |
总结
俄罗斯方块相比贪吃蛇增加了更多复杂性,核心要点总结:
| 功能 | 实现方式 |
|---|---|
| 方块形状 | 7 种形状 + 颜色定义 |
| 旋转 | 矩阵转置算法 |
| 碰撞检测 | 边界 + 已落方块检测 |
| 消除 | 行满检测 + 数组操作 |
| 速度 | 分数关联动态调整 |
| 控制 | 键盘 + 触摸滑动 |
游戏已集成到博客的小游戏栏目中,可以直接访问体验。
相关链接: