当前位置: 首页 > news >正文

【HTML】俄罗斯方块(精美版)

目录

一、页面效果

1.1 开始界面

1.2 游戏界面

1.3 游戏结束界面 

二、怎么运行

三、执行代码

四、游戏主要功能

4.1 开始游戏前设置

4.2 游戏界面与内容

4.3 操作方式

4.4 游戏结束

五、操作说明表


摘要:俄罗斯方块网页版游戏

本项目是一款使用 p5.js 开发的俄罗斯方块网页版小游戏,提供完整的游戏功能与良好用户体验。玩家可通过浏览器直接运行游戏,无需安装插件。

主要特性包括:

  • 🕹️ 经典操作:支持方向键移动、旋转、快速下落

  • 🧭 菜单系统:带有开始菜单与暂停菜单,支持调整游戏速度

  • 💡 得分统计:游戏过程中实时显示得分

  • 🎨 炫酷视觉:渐变背景+高亮方块+阴影效果

  • 💻 跨平台支持:HTML + JS 实现,可直接在浏览器中运行

适合用于娱乐、教学演示或 Web 游戏开发学习项目。


一、页面效果

1.1 开始界面

滑竿:调节下落速度

开始游戏按钮:弹窗隐藏,游戏开始


1.2 游戏界面

“←”键:向左移动;

“→”键:向右移动;

“↑”键:旋转方块;

“↓”:方块直接下落到最底部;

“空格”键:暂停弹窗(继续,重新开始,退出)

 


1.3 游戏结束界面 

重新开始:回到游戏开始页面

退出:关闭窗口


二、怎么运行

1、新建一个txt文本;

2、代码复制进文本; 

 

3、txt文件 重命名为html格式即可,如index.html

4、点击即可在浏览器中开始游戏。


三、执行代码

<!DOCTYPE html>
<html>
<head><title>俄罗斯方块</title><script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.2/p5.min.js"></script><style>body {display: flex;flex-direction: column;justify-content: center;align-items: center;height: 100vh;margin: 0;background: linear-gradient(135deg, #1e3c72, #2a5298);font-family: Arial, sans-serif;}canvas {border: 3px solid #fff;border-radius: 10px;box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);display: none;}#scoreDisplay {margin-top: 20px;background: rgba(255, 255, 255, 0.1);padding: 15px;border-radius: 10px;color: white;font-size: 1.2em;font-weight: bold;}#startModal, #pauseModal {position: fixed;top: 0;left: 0;width: 100%;height: 100%;background: rgba(0, 0, 0, 0.7);display: flex;justify-content: center;align-items: center;}.modal-content {background: #fff;padding: 20px;border-radius: 10px;text-align: center;box-shadow: 0 0 10px rgba(0, 0, 0, 0.5);}.modal-content h2 {margin: 0 0 20px;color: #333;}.modal-content button {margin: 10px;padding: 10px 20px;font-size: 1em;cursor: pointer;border: none;border-radius: 5px;background: #ff6b6b;color: white;transition: background 0.3s;}.modal-content button:hover {background: #ff8787;}.modal-content input[type="range"] {width: 200px;margin: 20px 0;accent-color: #ff6b6b;}</style>
</head>
<body><div id="startModal"><div class="modal-content"><h2>俄罗斯方块</h2><p>调整速度:</p><input type="range" id="startSpeedSlider" min="5" max="30" value="10"><button id="startButton">开始游戏</button></div></div><div id="pauseModal" style="display: none;"><div class="modal-content"><h2 id="pauseModalTitle">暂停</h2><p>调整速度:</p><input type="range" id="pauseSpeedSlider" min="5" max="30" value="10"><button id="resumeButton">继续</button><button id="restartButton">重新开始</button><button id="exitButton">退出</button></div></div><div id="scoreDisplay" style="display: none;">得分:0</div>
<script>
let board;
let currentPiece;
let score = 0;
let gameOver = false;
let paused = false;
let frameRateValue = 10;
let gameStarted = false;function setup() {let canvas = createCanvas(300, 600);canvas.elt.style.display = 'none';board = new Board(10, 20);currentPiece = new Piece();frameRate(frameRateValue);document.getElementById('startButton').addEventListener('click', () => {document.getElementById('startModal').style.display = 'none';canvas.elt.style.display = 'block';document.getElementById('scoreDisplay').style.display = 'block';gameStarted = true;frameRateValue = parseInt(document.getElementById('startSpeedSlider').value);});document.getElementById('resumeButton').addEventListener('click', () => {if (!gameOver) {document.getElementById('pauseModal').style.display = 'none';paused = false;frameRateValue = parseInt(document.getElementById('pauseSpeedSlider').value);}});document.getElementById('restartButton').addEventListener('click', () => {window.location.reload();});document.getElementById('exitButton').addEventListener('click', () => {window.close();});document.getElementById('startSpeedSlider').addEventListener('input', () => {frameRateValue = parseInt(document.getElementById('startSpeedSlider').value);document.getElementById('pauseSpeedSlider').value = frameRateValue;});document.getElementById('pauseSpeedSlider').addEventListener('input', () => {frameRateValue = parseInt(document.getElementById('pauseSpeedSlider').value);document.getElementById('startSpeedSlider').value = frameRateValue;});
}function draw() {let gradient = drawingContext.createLinearGradient(0, 0, 0, height);gradient.addColorStop(0, '#4facfe');gradient.addColorStop(1, '#00f2fe');drawingContext.fillStyle = gradient;rect(0, 0, width, height);if (gameStarted && !paused && !gameOver) {frameRate(frameRateValue);board.show();currentPiece.show();currentPiece.update();} else if (gameStarted) {board.show();currentPiece.show();}document.getElementById('scoreDisplay').innerText = `得分:${score}`;if (gameOver) {textSize(32);textAlign(CENTER);fill(255, 50, 50);text("游戏结束", width/2, height/2);drawingContext.shadowBlur = 20;drawingContext.shadowColor = 'rgba(255, 0, 0, 0.5)';} else {drawingContext.shadowBlur = 0;}
}function keyPressed() {if (keyCode === 32) {if (gameStarted && !gameOver) {paused = !paused;document.getElementById('pauseModal').style.display = paused ? 'flex' : 'none';document.getElementById('pauseModalTitle').innerText = '暂停';document.getElementById('resumeButton').style.display = 'inline-block';}return;}if (gameOver || paused || !gameStarted) return;if (keyCode === LEFT_ARROW) {currentPiece.move(-1);} else if (keyCode === RIGHT_ARROW) {currentPiece.move(1);} else if (keyCode === DOWN_ARROW) {currentPiece.dropToBottom();} else if (keyCode === UP_ARROW) {currentPiece.rotate();}
}class Board {constructor(w, h) {this.width = w;this.height = h;this.grid = [];for (let i = 0; i < h; i++) {this.grid[i] = [];for (let j = 0; j < w; j++) {this.grid[i][j] = 0;}}}show() {let cellWidth = width / this.width;let cellHeight = height / this.height;for (let i = 0; i < this.height; i++) {for (let j = 0; j < this.width; j++) {if (this.grid[i][j] === 1) {fill(0, 128, 255);stroke(255);strokeWeight(2);drawingContext.shadowBlur = 10;drawingContext.shadowColor = 'rgba(0, 128, 255, 0.5)';rect(j * cellWidth, i * cellHeight, cellWidth, cellHeight, 5);drawingContext.shadowBlur = 0;}}}}addPiece(piece) {for (let i = 0; i < piece.shape.length; i++) {for (let j = 0; j < piece.shape[i].length; j++) {if (piece.shape[i][j] === 1) {let boardX = piece.x + j;let boardY = piece.y + i;if (boardY >= 0 && boardY < this.height && boardX >= 0 && boardX < this.width) {this.grid[boardY][boardX] = 1;}}}}this.clearLines();}checkCollision(piece) {for (let i = 0; i < piece.shape.length; i++) {for (let j = 0; j < piece.shape[i].length; j++) {if (piece.shape[i][j] === 1) {let boardX = piece.x + j;let boardY = piece.y + i;if (boardY >= this.height) return true;if (boardX < 0 || boardX >= this.width) return true;if (boardY >= 0 && this.grid[boardY][boardX] === 1) return true;}}}return false;}clearLines() {let linesCleared = 0;for (let i = this.height - 1; i >= 0; i--) {let full = true;for (let j = 0; j < this.width; j++) {if (this.grid[i][j] === 0) {full = false;break;}}if (full) {this.grid.splice(i, 1);this.grid.unshift(new Array(this.width).fill(0));linesCleared++;i++;}}score += linesCleared * 100;}
}class Piece {constructor() {this.shapes = [[[1, 1, 1, 1]], // I[[1, 1], [1, 1]], // O[[1, 1, 1], [0, 1, 0]], // T[[1, 1, 1], [1, 0, 0]], // L[[1, 1, 1], [0, 0, 1]], // J[[1, 1, 0], [0, 1, 1]], // S[[0, 1, 1], [1, 1, 0]] // Z];this.shape = random(this.shapes);this.x = floor(board.width / 2) - floor(this.shape[0].length / 2);this.y = -this.shape.length;this.colors = [[0, 255, 255], // I: 青色[255, 255, 0], // O: 黄色[128, 0, 128], // T: 紫色[255, 165, 0], // L: 橙色[0, 0, 255],   // J: 蓝色[0, 255, 0],   // S: 绿色[255, 0, 0]    // Z: 红色];this.color = this.colors[this.shapes.indexOf(this.shape)];}show() {let cellWidth = width / board.width;let cellHeight = height / board.height;for (let i = 0; i < this.shape.length; i++) {for (let j = 0; j < this.shape[i].length; j++) {if (this.shape[i][j] === 1) {fill(this.color[0], this.color[1], this.color[2]);stroke(255);strokeWeight(2);drawingContext.shadowBlur = 10;drawingContext.shadowColor = `rgba(${this.color[0]}, ${this.color[1]}, ${this.color[2]}, 0.5)`;rect((this.x + j) * cellWidth, (this.y + i) * cellHeight, cellWidth, cellHeight, 5);drawingContext.shadowBlur = 0;}}}}update() {let nextPiece = new Piece();Object.assign(nextPiece, this);nextPiece.y++;if (board.checkCollision(nextPiece)) {if (this.y < 0) {gameOver = true;document.getElementById('pauseModal').style.display = 'flex';document.getElementById('pauseModalTitle').innerText = '游戏结束';document.getElementById('resumeButton').style.display = 'none';} else {board.addPiece(this);currentPiece = new Piece();}} else {this.y++;}}move(dir) {let nextPiece = new Piece();Object.assign(nextPiece, this);nextPiece.x += dir;if (!board.checkCollision(nextPiece)) {this.x = nextPiece.x;}}rotate() {let nextPiece = new Piece();Object.assign(nextPiece, this);let newShape = [];for (let i = 0; i < this.shape[0].length; i++) {newShape[i] = [];for (let j = 0; j < this.shape.length; j++) {newShape[i][j] = this.shape[this.shape.length - 1 - j][i];}}nextPiece.shape = newShape;if (!board.checkCollision(nextPiece)) {this.shape = newShape;}}dropToBottom() {let nextPiece = new Piece();Object.assign(nextPiece, this);while (!board.checkCollision(nextPiece)) {this.y = nextPiece.y;nextPiece.y++;}if (this.y < 0 && board.checkCollision(nextPiece)) {gameOver = true;document.getElementById('pauseModal').style.display = 'flex';document.getElementById('pauseModalTitle').innerText = '游戏结束';document.getElementById('resumeButton').style.display = 'none';} else {board.addPiece(this);currentPiece = new Piece();}}
}
</script>
</body>
</html>

四、游戏主要功能

4.1 开始游戏前设置

  • 初始弹出「开始菜单」,可通过滑块选择游戏速度(帧率 5~30)。

  • 点击 “开始游戏” 按钮进入游戏界面。

4.2 游戏界面与内容

  • 主界面居中展示游戏区域(10 列 × 20 行)。

  • 每个方块都有高亮颜色 + 阴影效果,视觉体验良好。

  • 屏幕上方显示当前 得分

4.3 操作方式

  • ⬅️ 左方向键:方块左移

  • ➡️ 右方向键:方块右移

  • ⬆️ 上方向键:旋转当前方块

  • ⬇️ 下方向键:直接下落到底部

  • 空格键(Space):暂停/恢复游戏

    • 暂停时弹出「暂停菜单」,可继续游戏、调整速度、重新开始、退出窗口

4.4 游戏结束

  • 当新方块生成时碰到已有方块(顶部被填满)→ 游戏结束

  • 弹出“游戏结束”提示框,提供:

    • 🔄 重新开始

    • 退出页面


五、操作说明表

功能操作方式
移动方块(左右)← → 键盘方向键
旋转方块↑ 键盘方向键
快速下落到底↓ 键盘方向键
暂停 / 恢复游戏空格键(Space)
调整游戏速度菜单滑块
重新开始游戏暂停菜单 → 重新开始按钮
退出游戏暂停菜单 → 退出按钮

 六、技术栈

  • 🔸 HTML + CSS + JavaScript

  • 🔸 p5.js 图形库:用于渲染游戏画面

  • 🔸 DOM 控制:实现游戏菜单交互与速度控制


📌 附加建议

若你希望继续扩展功能,可以考虑加入:

  • ⏱️ 倒计时模式 / 挑战模式

  • 🌐 排行榜或最高分记录

  • 🔊 音效与背景音乐

  • 🖱️ 支持鼠标 / 触控操作(移动端支持)

http://www.xdnf.cn/news/1101331.html

相关文章:

  • AI产品经理面试宝典第7天:核心算法面试题-上
  • GPT3/chatGPT/T5/PaLM/LLaMA/GLM主流大语言模型的原理和差异
  • flutter redux状态管理
  • 文章发布易优CMS(Eyoucms)网站技巧
  • oracle
  • 【InnoDB存储引擎4】行结构
  • PDF转图片
  • 2025 年第十五届 APMCM 亚太地区大学生数学建模竞赛-B题 疾病的预测与大数据分析
  • 滑动窗口-3.无重复字符的最长子串-力扣(LeetCode)
  • 使用Python和AkShare轻松获取新闻联播文字稿:从数据获取到文本挖掘
  • vue3+ts div自由拖拽改变元素宽度
  • C++——构造函数的补充:初始化列表
  • UML 与 SysML 图表对比全解析:软件工程 vs 系统工程建模语言
  • ContextMenu的Item如何绑定命令
  • “28项评测23项SOTA——GLM-4.1V-9B-Thinking本地部署教程:10B级视觉语言模型的性能天花板!
  • 【AI大模型】BERT微调文本分类任务实战
  • 拼数(字符串排序)
  • 力扣面试150(29/100)
  • 问题 C: 为美好的世界献上爆炎(博弈论)
  • 如何在 Windows 10 上安装设置 Apache Kafka
  • 聊聊AI大模型的上下文工程(Context Engineering)
  • 你见过的最差的程序员是怎样的?
  • Redis底层数据结构
  • CSS3的核心功能介绍及实战使用示例
  • 提示工程:解锁大模型潜力的核心密码
  • 库存订单管理系统:3月份开源项目汇总
  • linux中cmake编译项目
  • Django母婴商城项目实践(二)
  • 1.1.2 运算符与表达式——AI教你学Django
  • 3.检查函数 if (!CheckStart()) return 的妙用 C#例子