基于 HTML5 Canvas 制作一个精美的 2048 小游戏--day2
为了使 2048 游戏的设计更加美观和用户友好,我们可以进行以下几项优化:
- 改善颜色方案:使用更温馨的颜色组合。
- 添加动画效果:为方块的移动和合并添加渐变效果。
- 优化分数显示:在分数增加时使用动画效果。
以下是改进后的代码示例:

1. CSS 样式(style.css)
body {display: flex;justify-content: center;align-items: center;height: 100vh;background-color: #faf8ef;font-family: 'Arial', sans-serif;
}.container {position: relative;width: 420px; /* 自适应游戏板的总宽度 */
}canvas {border: 2px solid #bbada0;background-color: #eee4da;transition: background-color 0.3s ease; /* 过渡效果 */
}.score {position: absolute;top: -40px; /* 根据需要调整分数的位置 */right: 10px;font-size: 24px;color: #776e65;font-weight: bold;
}
2. 更新 HTML(index.html)
<!DOCTYPE html>
<html lang="zh-CN">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>2048 游戏</title><link rel="stylesheet" href="style.css">
</head>
<body><div class="container"><canvas id="gameCanvas"></canvas><div class="score" id="scoreDisplay">Score: 0</div> <!-- 分数显示 --></div><script src="script.js"></script>
</body>
</html>
3. JavaScript 动画和动态效果(script.js)
在 JavaScript 中,我们将实现方块的移动和合并时的动画效果。我们也会在分数更新时添加动画效果。
const canvas = document.getElementById("gameCanvas");
const ctx = canvas.getContext("2d");const gridSize = 4;
const tileSize = 100;
canvas.width = gridSize * tileSize;
canvas.height = gridSize * tileSize;let board = Array.from({ length: gridSize }, () => Array(gridSize).fill(0));
let score = 0;initBoard();function initBoard() {addRandomTile();addRandomTile();drawBoard();
}function drawBoard() {ctx.clearRect(0, 0, canvas.width, canvas.height);for (let r = 0; r < gridSize; r++) {for (let c = 0; c < gridSize; c++) {drawTile(r, c);}}updateScoreDisplay();
}function drawTile(r, c) {const value = board[r][c];ctx.fillStyle = value !== 0 ? getTileColor(value) : "#ccc0b3";ctx.fillRect(c * tileSize + 5,r * tileSize + 5,tileSize - 10,tileSize - 10); // 为方块添加间距if (value !== 0) {ctx.fillStyle = getTextColor(value);ctx.font = "bold 35px Arial";ctx.textAlign = "center";ctx.textBaseline = "middle";ctx.fillText(value,c * tileSize + tileSize / 2,r * tileSize + tileSize / 2);}
}function getTileColor(value) {switch (value) {case 2:return "#eee4da";case 4:return "#ede0c8";case 8:return "#f2b179";case 16:return "#f59563";case 32:return "#f67c5f";case 64:return "#f67c5f";case 128:return "#edcf72";case 256:return "#edcc61";case 512:return "#edc850";case 1024:return "#edc53f";case 2048:return "#edc22e";default:return "#ccc0b3";}
}function getTextColor(value) {return value <= 4 ? "#776e65" : "#ffffff"; // 小于等于4的数字使用深色,大于4的使用白色
}function addRandomTile() {let emptyCells = [];for (let r = 0; r < gridSize; r++) {for (let c = 0; c < gridSize; c++) {if (board[r][c] === 0) {emptyCells.push({ r, c });}}}if (emptyCells.length) {const { r, c } = emptyCells[Math.floor(Math.random() * emptyCells.length)];board[r][c] = Math.random() < 0.9 ? 2 : 4;}
}document.addEventListener("keydown", (event) => {let moved = false;switch (event.key) {case "ArrowUp":moved = moveUp();break;case "ArrowDown":moved = moveDown();break;case "ArrowLeft":moved = moveLeft();break;case "ArrowRight":moved = moveRight();break;}if (moved) {addRandomTile();drawBoard();if (checkGameOver()) {showGameOver();}}
});function canMergeTiles(r1, c1, r2, c2) {return board[r1][c1] !== 0 && board[r1][c1] === board[r2][c2];
}function moveUp() {let moved = false;for (let c = 0; c < gridSize; c++) {for (let r = 1; r < gridSize; r++) {if (board[r][c] !== 0) {let targetRow = r;while (targetRow > 0 && board[targetRow - 1][c] === 0) {board[targetRow - 1][c] = board[targetRow][c];board[targetRow][c] = 0;targetRow--;moved = true;}if (targetRow > 0 && canMergeTiles(targetRow - 1, c, targetRow, c)) {board[targetRow - 1][c] *= 2;score += board[targetRow - 1][c];board[targetRow][c] = 0;moved = true;}}}}return moved;
}function moveDown() {let moved = false;for (let c = 0; c < gridSize; c++) {for (let r = gridSize - 2; r >= 0; r--) {if (board[r][c] !== 0) {let targetRow = r;while (targetRow < gridSize - 1 && board[targetRow + 1][c] === 0) {board[targetRow + 1][c] = board[targetRow][c];board[targetRow][c] = 0;targetRow++;moved = true;}if (targetRow < gridSize - 1 &&canMergeTiles(targetRow + 1, c, targetRow, c)) {board[targetRow + 1][c] *= 2;score += board[targetRow + 1][c];board[targetRow][c] = 0;moved = true;}}}}return moved;
}function moveLeft() {let moved = false;for (let r = 0; r < gridSize; r++) {for (let c = 1; c < gridSize; c++) {if (board[r][c] !== 0) {let targetCol = c;while (targetCol > 0 && board[r][targetCol - 1] === 0) {board[r][targetCol - 1] = board[r][targetCol];board[r][targetCol] = 0;targetCol--;moved = true;}if (targetCol > 0 && canMergeTiles(r, targetCol - 1, r, targetCol)) {board[r][targetCol - 1] *= 2;score += board[r][targetCol - 1];board[r][targetCol] = 0;moved = true;}}}}return moved;
}function moveRight() {let moved = false;for (let r = 0; r < gridSize; r++) {for (let c = gridSize - 2; c >= 0; c--) {if (board[r][c] !== 0) {let targetCol = c;while (targetCol < gridSize - 1 && board[r][targetCol + 1] === 0) {board[r][targetCol + 1] = board[r][targetCol];board[r][targetCol] = 0;targetCol++;moved = true;}if (targetCol < gridSize - 1 &&canMergeTiles(r, targetCol + 1, r, targetCol)) {board[r][targetCol + 1] *= 2;score += board[r][targetCol + 1];board[r][targetCol] = 0;moved = true;}}}}return moved;
}function checkGameOver() {for (let r = 0; r < gridSize; r++) {for (let c = 0; c < gridSize; c++) {if (board[r][c] === 0) {return false; // 还有空格}if (c < gridSize - 1 && canMergeTiles(r, c, r, c + 1)) {return false; // 可以合并}if (r < gridSize - 1 && canMergeTiles(r, c, r + 1, c)) {return false; // 可以合并}}}return true; // 游戏结束
}function updateScoreDisplay() {const scoreDisplay = document.getElementById("scoreDisplay");scoreDisplay.innerText = "Score: " + score;
}function showGameOver() {alert("游戏结束!您的得分是:" + score);
}
动画效果
- 移动与合并动画:我们可以使用 CSS 的
transition属性来增加方块变化过程中的平滑感。这种效果可以在drawTile函数中体现,例如更改方块的背景色时使用过渡效果。 - 分数动画:我们可以在分数增加时使用淡入或渐变效果,以增加分数的视觉吸引力。这可以通过添加相关的 CSS 来实现,例如淡入特效,可以通过 JavaScript 调整
scoreDisplay的样式。
相关文章:
基于 HTML5 Canvas 制作一个精美的 2048 小游戏--day2
为了使 2048 游戏的设计更加美观和用户友好,我们可以进行以下几项优化: 改善颜色方案:使用更温馨的颜色组合。添加动画效果:为方块的移动和合并添加渐变效果。优化分数显示:在分数增加时使用动画效果。 以下是改进后…...
Django框架:python web开发
1.环境搭建: (a)开发环境:pycharm (b)虚拟环境(可有可无,优点:使用虚拟环境可以把使用的包自动生成一个文件,其他人需要使用时可以直接选择导入包ÿ…...
MySQL、HBase、ES的特点和区别
MySQL:关系型数据库,主要面向OLTP,支持事务,支持二级索引,支持sql,支持主从、Group Replication架构模型(本文全部以Innodb为例,不涉及别的存储引擎)。 HBase࿱…...
联发科MTK6762/MT6762安卓核心板_4G智能模块应用
MT6762安卓核心板是一款工业级高性能、可运行 android9.0 操作系统的 4G智能模块。MT6762平台打造具备 AI 体验、先进双摄像头拍摄效果且具备丰富连接功能的智能手机主板。 MT6762安卓核心板 是一款髙性能低功耗的 4G 全网通安卓智能模块。此模块支持 2G/3G/4G 移动,…...
Windows7系统下载安装Source Code Pro字库
Source Code Pro字库介绍 Source Code Pro是由Adobe推出的一款专为代码展示和编写设计的开源等宽字体。它不仅在编程社区中广受好评,还被广泛应用于各种编辑器环境中,以提升代码的可读性和编程体验。 Source Code Pro的设计充分考虑了编程符号的呈…...
Navicat 17 功能简介 | 商业智能 BI
Navicat 17 功能简介 | 商业智能BI 随着 17 版本的发布,Navicat 也带来了众多的新特性,包括兼容更多数据库、全新的模型设计、可视化智能 BI、智能数据分析、可视化查询解释、高质量数据字典、增强用户体验、扩展 MongoDB 功能、轻松固定查询结果、便捷U…...
C# winodw TableLayoutPanel 料盒生产状态UI自动生成
料盒生产状态UI自动生成,效果如下 以前公司项目的这些都是手动拖控件做的。每个设备的料盒数量不一样,层数不一样时都要发好几个小时去改相关细节和代码。上次改了一次。这个又来了。上次就有想法做成根据参数自动生成。但项目时间有限有没有去深入思路和…...
提示词的艺术----AI Prompt撰写指南(个人用)
提示词的艺术 写在前面 制定提示词就像是和朋友聊天一样,要求我们能够清楚地表达问题。通过这个过程,一方面要不断练习提高自己地表达能力,另一方面还要锻炼自己使用更准确精炼的语言提出问题的能力。 什么样的提示词有用? 有…...
哪些前端打印插件可以实现监听用户选择了打印还是取消
在前端实现监听用户是否选择了打印还是取消的功能,确实是一个挑战,因为浏览器的打印行为是通过原生对话框处理的,而这些对话框的行为无法直接被 JavaScript 控制或监听。不过,有一些插件和方法可以帮助你更接近这个目标࿱…...
【PyCharm】连接Jupyter Notebook
【PyCharm】相关链接 【PyCharm】连接 Git【PyCharm】连接Jupyter Notebook【PyCharm】快捷键使用【PyCharm】远程连接Linux服务器【PyCharm】设置为中文界面 【PyCharm】连接Jupyter Notebook PyCharm连接Jupyter Notebook的过程可以根据不同的需求分为 本地连接 和 远程连…...
【Linux系统编程】—— 深入理解Linux中的环境变量与程序地址空间
文章目录 环境变量常见的环境变量查看环境变量环境变量的修改与使用环境变量的组织⽅式环境变量的命令通过代码如何获取环境变量环境变量的继承 前言:在Linux系统中,环境变量和程序地址空间是系统管理和进程运行的重要组成部分。本文将详细探讨环境变量的…...
Spark常见面试题-部分待更新
1. 简述hadoop 和 spark 的不同点(为什么spark更快) Hadoop是一个分布式管理、存储、计算的生态系统,包括HDFS(分布式文件系统)、MapReduce(计算引擎)和YARN(资源调度器)…...
Android BitmapShader实现狙击瞄具十字交叉线准星,Kotlin
Android BitmapShader实现狙击瞄具十字交叉线准星,Kotlin <?xml version"1.0" encoding"utf-8"?> <RelativeLayout xmlns:android"http://schemas.android.com/apk/res/android"xmlns:tools"http://schemas.android.…...
linux通过web向mac远程传输字符串,mac收到后在终端中直接打印。
要通过Web从Linux向Mac远程传输字符串,并在Mac的终端中直接打印,可以使用以下方法。这里假设Linux作为服务器,Mac作为客户端。 方法 1:使用Python的HTTP服务器 在Linux上启动一个简单的HTTP服务器,Mac通过curl获取字符…...
海云安开发者安全智能助手D10荣膺 “ AI标杆产品 ” 称号,首席科学家齐大伟博士入选2024年度 “ 十大杰出青年 ”
2024年12月27日,粤港澳大湾区AI领袖峰会在深圳成功举办,大会表彰了在人工智能技术创新、应用实践和产业发展等方面取得优异成绩的企业和个人,深圳海云安网络安全技术有限公司开发者安全智能助手D10荣膺“AI标杆产品”称号。同时,公…...
Spring Boot + Apache POI 实现 Excel 导出:BOM物料清单生成器(支持中文文件名、样式美化、数据合并)
目录 引言 Apache POI操作Excel的实用技巧 1.合并单元格操作 2.设置单元格样式 1. 创建样式对象 2. 设置边框 3. 设置底色 4. 设置对齐方式 5. 设置字体样式 6.设置自动换行 7. 应用样式到单元格 3. 定位和操作指定单元格 4.实现标签-值的形式 5.列宽设置 1. 设…...
ReactiveSwift 简单使用
记录 ReactiveSwift 简单使用 导入 ReactiveSwift 库创建 TestViewModel 文件 enum JKTypeType: Int {case cloudcase devicecase weater }// 通过监听属性变化 class TestViewModel: NSObject {lazy var recordType: Property<JKTypeType> {return Property(recordTy…...
CSS 的基础知识及应用
前言 CSS(层叠样式表)是网页设计和开发中不可或缺的一部分。它用于描述网页的视觉表现,使页面不仅实现功能,还能提供吸引人的用户体验。本文将介绍 CSS 的基本概念、语法、选择器及其在提升网页美观性方面的重要性。 什么是 CSS&…...
【Web】2025西湖论剑·中国杭州网络安全安全技能大赛题解(全)
目录 Rank-l Rank-U sqli or not Rank-l username存在报错回显,发现可以打SSTI 本地起一个服务,折半查找fuzz黑名单,不断扔给fenjing去迭代改payload from flask import Flask, request, render_template_stringapp Flask(__name__)app…...
能源物联网数据采集设备 串口服务器功能参数介绍
摘要 随着物联网技术的快速发展,各种传统设备的联网需求愈发迫切。串口服务器作为一种桥接传统串口设备与现代网络的关键设备,在工业控制、智能电网、交通运输等域发挥了重要作用。本文以APort100串口服务器为例,探讨串口服务器在现代物联…...
2026奇点智能技术大会文本生成白皮书首发(仅限前500名技术决策者获取)
第一章:2026奇点智能技术大会:大模型文本生成 2026奇点智能技术大会(https://ml-summit.org) 核心突破:上下文感知生成架构 本届大会首次公开展示了Context-Aware Generation Engine(CAGE),一种支持动态长…...
DS1202示波器核心功能解析与实战操作指南
1. DS1202示波器核心功能模块解析 第一次拿到DS1202示波器时,面对面板上密密麻麻的按键和接口,很多新手都会感到无从下手。其实只要掌握了几个核心功能区的操作逻辑,就能快速上手这台仪器。我刚开始用示波器时也踩过不少坑,比如不…...
三菱 FX5U/Q 系列 PLC 以太网通讯中间件功能说明书
C#与三菱PLC以太网通讯程序上位机源码 通过3E帧SLMP /MC协议与三菱FX5U/Q系列PLC通讯 1.该程序可以与FX5U/Q系列PLC以太网通讯,根据3E帧报文写了一个类库,可以读写各种类型和区域变量。 2.支持单个变量读写和数组类型批量读写。 3.可以实时检测网络通断…...
从MobileViT到BERT:结构化剪枝如何帮你打造“小钢炮”模型?实战案例与调参避坑指南
从MobileViT到BERT:结构化剪枝实战与调参避坑指南 在移动端和边缘计算场景中,模型小型化已成为AI落地的关键瓶颈。当我们将参数量超过1亿的ViT或BERT部署到手机、嵌入式设备甚至普通GPU服务器时,内存占用大、推理延迟高、能耗超标等问题会集中…...
别再数据线了!用FastAPI 分钟搭个局域网文件+剪贴板神器茄
为 HagiCode 添加 GitHub Pages 自动部署支持 本项目早期代号为 PCode,现已正式更名为 HagiCode。本文记录了如何为项目引入自动化静态站点部署能力,让内容发布像喝水一样简单。 背景/引言 在 HagiCode 的开发过程中,我们遇到了一个很现实的问…...
3倍极速突破:Gofile多线程下载器实战指南
3倍极速突破:Gofile多线程下载器实战指南 【免费下载链接】gofile-downloader Download files from https://gofile.io 项目地址: https://gitcode.com/gh_mirrors/go/gofile-downloader 在文件传输成为日常刚需的数字时代,你是否曾因Gofile大文件…...
Simcenter 3D声学仿真避坑指南:直接法vs模态法,响应计算到底选哪个?(基于SOL 108和SOL 111)
Simcenter 3D声学仿真方法论抉择:直接法与模态法的深度技术解析 当面对一个声学仿真项目时,工程师们常常站在十字路口犹豫不决——是选择直接频率响应法(SOL 108)还是基于模态的频率响应法(SOL 111)&#x…...
终极指南:3分钟学会Charticulator免费图表设计工具
终极指南:3分钟学会Charticulator免费图表设计工具 【免费下载链接】charticulator Interactive Layout-Aware Construction of Bespoke Charts 项目地址: https://gitcode.com/gh_mirrors/ch/charticulator 想要快速创建专业级数据可视化图表却不会编程&…...
3个关键步骤:如何用XXMI启动器统一管理多款热门游戏模组
3个关键步骤:如何用XXMI启动器统一管理多款热门游戏模组 【免费下载链接】XXMI-Launcher Modding platform for GI, HSR, WW and ZZZ 项目地址: https://gitcode.com/gh_mirrors/xx/XXMI-Launcher 你是否曾经为不同游戏的模组管理感到头疼?每个游…...
QQ音乐解码神器qmcdump:5分钟快速解锁加密音乐文件的完整指南
QQ音乐解码神器qmcdump:5分钟快速解锁加密音乐文件的完整指南 【免费下载链接】qmcdump 一个简单的QQ音乐解码(qmcflac/qmc0/qmc3 转 flac/mp3),仅为个人学习参考用。 项目地址: https://gitcode.com/gh_mirrors/qm/qmcdump …...
