简介:面向软件工程或计算机相关专业毕业设计,这份基于微信小程序开发的休闲小游戏设计与实现资料包,覆盖项目构思、玩法设计、小程序前端实现、测试部署以及毕业论文撰写等完整链路。资源打包为RAR格式,共491个文件,压缩体积12.02MB:包含208个JSON界面与关卡配置、106个JS逻辑脚本、85个PNG美术资源、15个MP3音频,以及Meta、Map、Prefab、Fire等Cocos Creator工程文件,并提供wechatgame等不同版本源码包,可直接导入微信开发者工具观察整体结构。已有173人学习下载。对于准备从事小程序游戏方向毕业设计的学生,可借助该案例学习休闲游戏的功能拆解、资源管理方式和readme中记录的开发注意事项;同时Java标签暗示可能涉及后端服务,适合需要理解前后端配合的读者拓展研究。总体而言,这是一套兼具学习与参考价值的毕业设计完整资料。
1. 微信小程序休闲小游戏:一条能同时拿下开发与论文的路径
毕业设计选“基于微信小程序休闲小游戏”是个很聪明的主意,它拿得出手的地方不只是代码量适中,更在于这个题目天然带有一套完整的软件工程叙事:需求分析、技术选型、模块设计、性能调优、测试发布,每一环都能写进毕业论文,不用刻意编造素材。但聪明归聪明,实际开工后你会发现,小游戏和普通小程序根本不是一回事——没有 WXML 和 WXSS,页面渲染靠 Canvas,逻辑更新靠帧循环,分包体积还卡着 4MB 的上限,稍不注意就给你弹一个“代码包超过限制”。所以这篇东西打算从技术选型讲到代码骨架,再讲到性能优化和论文写作映射,帮你把整条路走通。如果你已经在开发者工具里建过项目,可以直接跳到第 3 章;完全零基础也能按章节顺序跟上。
2. 技术选型和开发环境:用 Canvas 还是用游戏引擎
2.1 原生小游戏、Laya 和 Cocos Creator 怎么选
微信小游戏的运行环境本质上是一个去掉了浏览器 DOM 的 Canvas 运行环境,JavaScript 仍然是主要开发语言。你面临的第一道选择题是:直接用原生 Canvas API 写,还是引入 Laya、Cocos Creator 这类游戏引擎。
| 方案 | 包体积 | 上手难度 | 对论文的帮助 | 适用场景 |
|---|---|---|---|---|
| 原生 Canvas | 最小,几十 KB | 中,需要自己写循环和碰撞 | 高,所有代码都可控,方便画架构图 | 玩法简单的休闲游戏、毕业设计 |
| Cocos Creator | 通常 1-3MB | 中低,编辑器可视化 | 中,部分代码由引擎生成,写论文要额外解释引擎逻辑 | 需要复杂动画、物理效果的 2D/3D 游戏 |
| LayaAir 3.x | 中等 | 中 | 中 | 偏 H5 小游戏、需要 Web 端同构的项目 |
对“休闲小游戏 + 毕业论文”这个组合,我更推荐原生 Canvas。原因很简单:答辩时老师大概率会问“这个碰撞检测是怎么实现的”,如果你用引擎,只能回答“调了引擎的物理组件”;但用原生 Canvas,你可以把矩形碰撞、圆形碰撞的公式推给老师看,代码几十行,清清楚楚。微信小游戏也提供了 Globals 上的wx.createCanvas()接口,原生写法不会被任何中间层挡住。
2.2 搭建最小开发环境:注册账号与创建小游戏项目
在微信公众平台注册小程序账号时,服务类目选“小游戏”,个人主体也可以注册,这比很多人想象中更友好。注册完成后下载微信开发者工具,新建项目时选择“小游戏”模板。
一个刚创建的小游戏项目目录大致长这样:
project.config.json # 项目配置文件 game.js # 入口文件 game.json # 小游戏配置,页面方向、设备尺寸等 js/ main.js # 主循环 player.js # 玩家对象把入口文件指向game.js,并在game.json中做最小的配置:
{ "deviceOrientation": "portrait", "showStatusBar": false, "networkTimeout": { "request": 5000 } }deviceOrientation控制游戏横竖屏,休闲小游戏通常竖屏;showStatusBar设为false可以去掉顶部状态栏,让游戏画面全屏。网络超时配置对小游戏不是必需的,但保留这个字段可以避免后续接入排行榜时请求无响应导致的白屏。
2.3 用 wx.createCanvas 跑通第一帧
进入game.js,第一步是创建画布并获取绘图上下文:
const canvas = wx.createCanvas() const ctx = canvas.getContext('2d')这个wx.createCanvas()在普通小程序里是不存在的,它是小游戏环境专属接口。调用它之后不需要把 canvas 节点挂到任何 DOM 上,因为它已经是屏幕上的画布。拿到 ctx 后,往上面画一个矩形,模拟最简单的游戏对象:
// 玩家对象:一个 100x100 的蓝色方块 const player = { x: canvas.width / 2 - 50, y: canvas.height - 120, width: 100, height: 100, color: '#4A90E2' } function drawPlayer() { ctx.clearRect(0, 0, canvas.width, canvas.height) // 清空上一帧 ctx.fillStyle = player.color ctx.fillRect(player.x, player.y, player.width, player.height) } drawPlayer()这里clearRect是每一帧渲染前必须做的清理,不清空的后果是上一帧的画面残留,产生拖影。fillRect接受四个参数:x、y、宽、高。到这一步,你已经能在模拟器上看到一个静止的蓝色方块,但这个方块不会动,因为没有帧循环。
3. 核心玩法拆解:帧循环、碰撞与手势交互
3.1 用 requestAnimationFrame 构建帧循环
休闲小游戏的核心驱动力是帧循环,每一帧内完成三件事:处理输入、更新逻辑、渲染画面。微信小游戏环境提供了requestAnimationFrame全局函数,它会在下一次屏幕刷新时调用你的函数。
let lastTime = 0 function gameLoop(timestamp) { const deltaTime = (timestamp - lastTime) / 1000 // 转成秒 lastTime = timestamp updatePlayer(deltaTime) render() requestAnimationFrame(gameLoop) } requestAnimationFrame(gameLoop)deltaTime是相邻两帧的时间差,用来让位移速度不依赖设备帧率。假如一个物体移动速度是每秒 200 像素,那么它在每帧的位移是200 * deltaTime,在 60Hz 屏幕上约等于 3.3 像素,在 30Hz 屏幕上约等于 6.6 像素,最终一秒移动的距离都是 200 像素。如果没有 deltaTime,直接用固定步长,低帧率设备上的游戏速度会明显偏慢。
3.2 休闲游戏最常用的两种碰撞检测
休闲小游戏里最常见的检测需求是:手指是否点到了目标、两个物体是否碰到。前者的本质是点与矩形的包含关系,后者的本质是矩形与矩形的相交判定。在这里我给你两个工程上够用的函数:
function isPointInRect(px, py, rect) { return px >= rect.x && px <= rect.x + rect.width && py >= rect.y && py <= rect.y + rect.height } function isRectIntersect(r1, r2) { return r1.x < r2.x + r2.width && r1.x + r1.width > r2.x && r1.y < r2.y + r2.height && r1.y + r1.height > r2.y }isPointInRect用于判断手指坐标是否落在按钮或某个物体上,四个条件分别检查 x 和 y 是否同时满足左右上下边界。isRectIntersect是 AABB(轴对齐包围盒)碰撞检测,两个矩形只要在 x 轴和 y 轴投影都重叠,就判定碰撞。这两个函数加在一起不超过十行,但足以覆盖绝大多数休闲游戏的需求。如果你的游戏里有圆形物体,将矩形替换为圆心距离和半径之和的比较即可。
3.3 手势控制与点击反馈
微信小游戏监听触摸事件时不走 DOM 的addEventListener,要用wx.onTouchStart和wx.onTouchMove。这两个接口挂载的是全局回调,你需要在回调里判断触摸点落在哪个游戏对象上。
wx.onTouchStart((e) => { const touch = e.touches[0] if (isPointInRect(touch.clientX, touch.clientY, startBtn)) { isGameStart = true wx.vibrateShort({ type: 'light' }) // 轻震动反馈 } }) wx.onTouchMove((e) => { const touch = e.touches[0] player.x = touch.clientX - player.width / 2 // 玩家方块跟随手指 })clientX和clientY是触摸点在屏幕上的坐标,对 Canvas 游戏来说直接用于逻辑坐标即可,因为主 Canvas 默认铺满全屏。wx.vibrateShort是很多休闲游戏会加的细节,点击后有个轻微震动,手感会明显提升,而且这个接口不需要申请权限。注意这里直接修改了player.x,如果后续想加“平滑跟随”效果,可以在updatePlayer里做插值,而不是直接把方块瞬移到手指位置。
3.4 完整的最小可玩版本需要的模块划分
从工程整洁度考虑,把一个游戏拆成最少四个模块:main.js管帧循环,player.js管玩家对象,enemy.js管敌人生成和移动,collision.js放碰撞函数。以接水滴为例,玩家是一个承接水杯,水滴从顶部掉落,每接到一滴加分,漏掉则扣生命值。这类玩法的逻辑就是定时生成 Enemy、每一帧修改 Enemy 的 y 坐标、检测到 Enemy 与 Player 相交则销毁该对象并加一分。这套模块划分直接可以在论文里作为“系统功能模块设计”部分的结构图,不需要额外编造。
4. 性能优化与适配:别让新手玩家卡在第一关
4.1 对象池:解决频繁创建和销毁对象的卡顿
休闲小游戏比如接水滴、打地鼠,会不停创建敌人又销毁敌人。如果只用new和数组splice,每帧都会产生大量内存垃圾,触发 JavaScript 垃圾回收时游戏会出现肉眼可见的帧率抖动。对象池是标准解法:
class ObjectPool { constructor(createFn, size = 20) { this.createFn = createFn this.pool = [] for (let i = 0; i < size; i++) { this.pool.push(createFn()) } } get() { return this.pool.pop() || this.createFn() } put(obj) { this.pool.push(obj) } }使用方式:敌人被回收时不是splice掉,而是调用pool.put(enemy),需要生成新敌人时调用pool.get(),然后重置该对象的坐标和状态。这样内存中的对象数量始终保持在一个稳定水位,避免了频繁触发 GC。对象池的初始大小可以根据游戏需要调整,接水滴类游戏 20 到 30 个足够,贪吃蛇这种食物数量极少的游戏 10 个以下就行。
4.2 渲染优化:离屏 Canvas 与绘制裁剪
如果你的游戏背景是一个复杂的静态场景,每一帧都重画整张背景会导致大量无效绘制。常见的做法是把背景先画到一个离屏 Canvas 上,然后每帧用drawImage把离屏内容贴到主画布。
// 创建离屏画布,宽高与主画布一致 const offscreen = wx.createCanvas() offscreen.width = canvas.width offscreen.height = canvas.height const offCtx = offscreen.getContext('2d') // 只做一次:绘制静态背景 offCtx.fillStyle = '#1A1A2E' offCtx.fillRect(0, 0, offscreen.width, offscreen.height) // 每帧绘制 ctx.drawImage(offscreen, 0, 0)比离屏 Canvas 更进一步的做法是“脏矩形”,也就是只重绘制发生变化的那一小块区域。但由于微信小游戏的 Canvas API 并没有浏览器里的损坏区域机制,实际做脏矩形的复杂度比较高,休闲小游戏很少用到,这里点到为止。如果你的游戏元素数量特别多,牺牲背景直接每帧全量重绘,再用ctx.save()和ctx.restore()控制坐标系变换,已经是绝大多数休闲游戏的性能天花板了。
4.3 安全区适配:iPhone 刘海屏与 Android 全面屏
小游戏拿到全屏后,设备的安全区差异会直接暴露。屏幕顶部的刘海和底部的横条会挡住 UI 按钮,按不下去。
微信提供了wx.getWindowInfo()获取安全区信息(基础库 2.20.1 以上可用,旧版本用wx.getSystemInfoSync):
const windowInfo = wx.getWindowInfo() const safeArea = windowInfo.safeArea ctx.fillStyle = '#FF0000' ctx.fillRect(safeArea.left, safeArea.top, safeArea.width, safeArea.height)在布局关键按钮时,把 y 坐标设置为safeArea.top + offset,而不是从屏幕顶部 0 开始算。还有一个容易忽略的点:Android 全面屏底部有手势横条,如果在屏幕底部放计分板或操作按钮,要保留safeArea.bottom到屏幕底部的间距。用safeArea对象后,主 Canvas 是逻辑分辨率坐标还是物理像素坐标通常不是问题,因为微信小游戏默认把逻辑分辨率设置为屏幕物理分辨率,没有 DP 缩放的问题。
5. 毕业论文怎么写:把工程代码映射为学术内容
5.1 论文结构:六章对应开发流程
毕业论文和项目代码不是一一照搬,但开发过程本身足够撑起一篇完整的本科论文。常见的章节映射关系如下,字段上直接对应软件开发的标准流程。
| 论文章节 | 对应工程内容 | 写作要点 |
|---|---|---|
| 绪论 | 项目背景、国内外研究现状 | 引数据说明休闲小游戏市场增长,不要写成产品宣传 |
| 相关技术介绍 | 微信小游戏平台、Canvas、JavaScript | 重点是微信小游戏与普通小程序的差异 |
| 系统设计 | 总体架构图、模块拆分、数据库/本地存储 | 画帧循环流程图,标注模块间调用关系 |
| 系统实现 | 核心代码片段 | 贴的不是完整源码,而是帧循环、碰撞、对象池三段 |
| 系统测试 | 兼容性测试与性能测试 | 用表格列出机型、帧率、内存占用 |
| 总结 | 不足与展望 | 控制在一页以内,不要写“该系统非常完善” |
5.2 系统设计图怎么画
导师最看重的是“系统设计”这一章有没有画清楚。对纯前端小游戏来说,总体架构图可以分两层:表现层(Canvas 渲染、触摸事件、音频播放)和逻辑层(状态管理、碰撞检测、对象池管理)。逻辑层和数据层之间用本地存储接口wx.setStorageSync作为边界。模块图用 Visio 或 draw.io 画清楚后截图插入论文即可,不要用代码去生成图,答辩老师更习惯看静态图。
需要额外注意的是需求分析阶段。小游戏的“用户需求”不能只写“让玩家放松”,至少要拆出功能需求(开始游戏、暂停、计分、重新开始)和非功能需求(在低端 Android 机上帧率不低于 30FPS、首屏加载时间不超过 3 秒)。非功能需求会成为后续测试章节里的验收指标。
5.3 性能测试结果表:给答辩老师的实打实数据
论文的测试章节不要只写“运行正常”,要给出可量化的结果。把你手头的测试设备跑一下,记录帧率和内存占用,用表格呈现:
| 测试机型 | 系统版本 | 平均帧率(fps) | 最低帧率(fps) | 内存占用(MB) | 是否通过 |
|---|---|---|---|---|---|
| iPhone 13 | iOS 17 | 59.6 | 55 | 89 | 通过 |
| Redmi K50 | Android 13 | 58.2 | 47 | 112 | 通过 |
| 华为 nova 9 | HarmonyOS 3 | 57.4 | 41 | 105 | 通过 |
采集帧率数据可以在游戏里临时加一段统计代码:
let frameCount = 0 let lastStatTime = 0 let currentFPS = 0 function updateFPS(timestamp) { frameCount++ if (timestamp - lastStatTime >= 1000) { currentFPS = frameCount frameCount = 0 lastStatTime = timestamp } }在帧循环里调用updateFPS(timestamp),每一秒刷新一次currentFPS,导出到悬浮文本里展示。测试时用系统录屏功能记录 1 分钟,取平均值和最低值。如果最低帧率低于 45,说明游戏逻辑需要优化,首选检查循环内是否有其它计算任务挤占了渲染时间。
6. 构建发布与验证:从开发者工具到上线的最后一公里
真机调试和开发者工具模拟器的差异比想象中大。模拟器上的帧率通常在 60fps 左右,但真机上因为系统 UI、省电策略等原因会明显下降。在开发者工具中点击“预览”会生成一个二维码,用微信扫码后可以在真机上以开发版运行。此时打开微信开发者工具的“真机调试”面板,能看到当前页面的层级结构和 console 日志,和普通小程序的调试流程完全一致。
小游戏包体有 4MB 主包上限的限制,一个休闲小游戏如果把图片和音频资源全部打入包内,很容易超限。常规做法是把背景图、音效放到云开发存储或自己的 CDN 上,代码里用wx.createImage()加载网络图片,用wx.createInnerAudioContext()播放网络音频。图片用 TinyPNG 压缩,音频转成 64kbps 的 AAC 格式,通常能把包体压在 1MB 以内。
提交审核前要做两类检查:一是隐私协议,小游戏若涉及用户头像昵称获取,必须在代码中明确调用微信提供的授权接口,并在后台配置隐私保护指引;二是内容安全,游戏内不能出现诱导分享按钮,不能有积分兑换现金等字样。审核周期一般 1 到 3 天,如果被驳回,看驳回理由,大部分原因是类目选择不对或截图不清晰。
正式发布前还有一件值得做的事:开启微信小游戏数据助手,看次日留存和人均时长。这两个数据指标会反过来帮你决定下一版改什么。人均时长如果只有几十秒,往往是难度曲线不对;如果留存低,可能是开局让玩家等太久。到这一步,选题、开发、测试、发布和数据分析全部走完,毕业论文最后的“总结与展望”里,你也真的有东西可以展望了。
本文还有配套的精品资源,点击获取