致敬经典!我用 HTML 复刻了一个霓虹版俄罗斯方块

我用纯 HTML+JS 写了个赛博朋克风俄罗斯方块

前言

俄罗斯方块,一个从 1984 年火到现在的经典游戏。最近手痒,用纯原生 HTML + Canvas + JavaScript 撸了一个科技风(赛博朋克)版本,没有用任何框架,单文件就能跑。

先上效果:

项目特点:

  • 🎨 3 套主题:科技蓝 / 纯黑 / 极简白
  • 📊 完整数据面板:分数、等级、消除行数、最高分
  • ⚡ 流畅操作:支持双方向旋转、硬降、软降、暂停
  • 🎵 科技感 UI:霓虹边框、粒子星空背景、发光特效

在线体验:TETRIS - 科技风俄罗斯方块

一、整体架构

整个游戏就是一个 index.html 文件,包含三部分:

css 复制代码
index.html
├── CSS 样式      ------ 科技风 UI、动画、主题切换
├── HTML 结构     ------ 画布、面板、各种模态框
└── JavaScript    ------ 游戏核心逻辑 + 交互

二、游戏核心实现

2.1 方块数据结构

经典的 7 种方块(I、O、T、S、Z、L),用二维数组表示形状:

javascript 复制代码
const SHAPES = {
    I: [
        [0, 0, 0, 0],
        [1, 1, 1, 1],
        [0, 0, 0, 0],
        [0, 0, 0, 0]
    ],
    O: [
        [1, 1],
        [1, 1]
    ],
    T: [
        [0, 1, 0],
        [1, 1, 1],
        [0, 0, 0]
    ],
    // S、Z、J、L 同理...
};

每种方块对应一种霓虹色,科技感拉满:

javascript 复制代码
const COLORS = {
    I: '#00dcff',   // 青色
    O: '#ffc832',   // 金色
    T: '#c800ff',   // 紫色
    S: '#00ff96',   // 绿色
    Z: '#ff3264',   // 红色
    J: '#3264ff',   // 蓝色
    L: '#ff9600',   // 橙色
};

2.2 游戏主循环

用 requestAnimationFrame 做游戏循环,根据等级控制下落速度:

javascript 复制代码
let dropCounter = 0;
let dropInterval = 1000; // 初始 1 秒下落一格
let lastTime = 0;

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

    dropCounter += deltaTime;
    if (dropCounter > dropInterval) {
        pieceDrop();  // 方块下落
        dropCounter = 0;
    }

    draw();  // 渲染画面
    requestAnimationFrame(update);
}

等级越高,dropInterval 越小,下落越快:

javascript 复制代码
// 每消除 10 行升一级,速度递增
dropInterval = Math.max(100, 1000 - (level - 1) * 80);

2.3 旋转算法

用矩阵转置 + 行反转实现顺时针旋转:

javascript 复制代码
function rotate(matrix, dir) {
    // 转置
    for (let y = 0; y < matrix.length; y++) {
        for (let x = 0; x < y; x++) {
            [matrix[x][y], matrix[y][x]] = [matrix[y][x], matrix[x][y]];
        }
    }
    // 顺时针:反转每一行;逆时针:反转整个数组
    if (dir > 0) {
        matrix.forEach(row => row.reverse());
    } else {
        matrix.reverse();
    }
}

旋转时做墙踢检测(Wall Kick),避免贴着墙转不动:

javascript 复制代码
function pieceRotate(dir) {
    const pos = piece.x;
    let offset = 1;
    rotate(piece.matrix, dir);
    
    // 如果撞墙了,一点点挪回去
    while (checkCollision(board, piece)) {
        piece.x += offset;
        offset = -(offset + (offset > 0 ? 1 : -1));
        if (offset > piece.matrix[0].length) {
            rotate(piece.matrix, -dir);  // 转不回去就复原
            piece.x = pos;
            return;
        }
    }
}

2.4 消行与评分

满行检测 + 下移 + 分数计算:

javascript 复制代码
function lineClear() {
    let lines = 0;
    
    outer: for (let y = board.length - 1; y > 0; y--) {
        for (let x = 0; x < board[y].length; x++) {
            if (board[y][x] === 0) continue outer;
        }
        
        // 这行满了,删掉并在顶部补一行空的
        const row = board.splice(y, 1)[0].fill(0);
        board.unshift(row);
        y++;  // 重新检查当前行
        lines++;
    }
    
    // 经典俄罗斯方块计分规则
    const scoreTable = [0, 100, 300, 500, 800];
    score += scoreTable[lines] * level;
    linesCleared += lines;
}

三、科技风 UI 怎么做的

3.1 霓虹发光边框

核心就是多层 box-shadow:

css 复制代码
canvas {
    border: 2px solid #00c8ff;
    box-shadow: 
        0 0 20px rgba(0, 200, 255, 0.3),
        inset 0 0 30px rgba(0, 100, 200, 0.1);
}

外发光 + 内发光,赛博朋克味儿一下就出来了。

3.2 星空粒子背景

JS 动态生成 50 颗星星,CSS 动画闪烁:

javascript 复制代码
function createStars() {
    const container = document.getElementById('stars');
    for (let i = 0; i < 50; i++) {
        const star = document.createElement('div');
        star.className = 'star';
        star.style.left = Math.random() * 100 + '%';
        star.style.top = Math.random() * 100 + '%';
        star.style.width = (Math.random() * 3 + 1) + 'px';
        star.style.height = star.style.width;
        star.style.animationDelay = Math.random() * 3 + 's';
        container.appendChild(star);
    }
}

3.3 网格背景

纯 CSS 渐变搞定:

css 复制代码
body::before {
    content: '';
    position: fixed;
    background-image: 
        linear-gradient(rgba(20, 40, 80, 0.3) 1px, transparent 1px),
        linear-gradient(90deg, rgba(20, 40, 80, 0.3) 1px, transparent 1px);
    background-size: 50px 50px;
}

3.4 主题切换

用 CSS 变量 + 类名切换,三套主题一键换:

javascript 复制代码
function setTheme(theme) {
    const themes = {
        blue: {
            bg: '#080c1c',
            text: '#dcf0ff',
            accent: '#00dcff',
            border: '#00c8ff'
        },
        dark: { /* ... */ },
        white: { /* ... */ }
    };
    
    Object.entries(themes[theme]).forEach(([key, val]) => {
        document.documentElement.style.setProperty(`--${key}`, val);
    });
}

四、操作说明

按键 功能
← → / A D 左右移动
↑ / W / X 顺时针旋转
Z / Ctrl 逆时针旋转
↓ / S 加速下落
空格 直接落底
P / ESC 暂停游戏

结语

俄罗斯方块虽然是个老游戏,但每次重写都有新的收获------从游戏循环、碰撞检测到 UI 动效,从头到尾撸一遍真的很锻炼基础。

如果你也喜欢复古游戏 + 科技风,欢迎在评论区探讨!

相关推荐
miofly3 小时前
GitHub 日榜趋势速报 | 2026-10-07
开源·github
miofly18 小时前
Reflection AI 发布 501B 参数开放权重模型 Beam
开源·github
m4Rk_20 小时前
【论文阅读】Agent 记忆机制(91):THEANINE——不删除过时记忆,让 Agent 记住事情是如何变化的
论文阅读·人工智能·学习·开源·github
高频因子挖掘机21 小时前
批量行情返回后,怎样把请求失败的股票单独挑出来?
后端·github·api
奥德元1 天前
XiaoMate功能介绍: 让桌宠帮你分析你的桌面屏幕
github
TunerT_TQ1 天前
【开源评测】dots:自带浏览器的 Web AI Agent——C++ 级反检测路径的工程取舍与争议
github
Maynor在掘金1 天前
1.9 万 Star 的 Hypit:让 AI Agent 帮你“一键复刻”爆款视频,保姆级上手教程
vue.js·github
嘎嘎风1 天前
MiniMind 学习笔记之 05 从 768 维到下一个 token
github·源码阅读
高频因子挖掘机1 天前
盘中筛选要同时看价格和盘口?按需分层比“一次全拿”更好维护
后端·github·api