想做微信小游戏,第一步不用接登录、排行榜、广告或支付。先让玩家能开始、能操作、能失败、能重新开始,把一个完整的小循环跑通。
这篇用本机 AI 做一款“躲陨石”:拖动飞船避开下落的陨石,存活时间就是分数。项目只用微信小游戏的 Canvas 和触摸事件,不联网、不保存用户资料。本文在微信开发者工具的本地模拟器中用“测试号”运行;没有登录账号、使用真实主体 AppID、提交审核或发布,因此本地可运行不代表已经能上架。
练习包包含完整项目、需求卡、模型原始回复和复核记录:下载微信小游戏练习包。
先把第一版缩小到能验收
“做一个小游戏”太宽,模型容易一次塞进排行榜、道具、广告和登录。先写玩家动作和结果,再把联网功能留到以后:
| 玩家操作 | 第一版要看到的结果 |
|---|---|
| 打开游戏 | 标题和开始提示可见 |
| 点一下开始 | 飞船和陨石出现,分数从 0 开始 |
| 按住并左右拖动 | 飞船跟随手指移动,不能跑出屏幕 |
| 撞到陨石 | 游戏停止,显示存活时间和重开提示 |
| 再点一下 | 新一局重新计分,陨石从头生成 |
这一轮没有账号、存档、联网、广告、付费或排行榜。功能少一些,才容易判断代码到底能不能运行。
1. 让 AI 一次只生成一个文件
把验收条件和运行环境写清楚,尤其是“微信小游戏”不是普通网页:不能把 window、document 或 DOM 组件直接搬进来。微信开放文档说明,小游戏通过 wx.createCanvas() 创建画布,首个画布是屏幕画布;触摸监听器收到 changedTouches,其中 clientX/clientY 是相对可视区域的坐标。
可以把这段需求卡交给代码助手:
只生成一份可保存为 game.js 的 JavaScript 源码,不要解释或 Markdown 围栏。
目标是微信小游戏原生环境:使用 wx.createCanvas()、Canvas 2D、wx.onTouchStart 和 wx.onTouchMove;不要使用 window、document、DOM、第三方库、网络、账号、存储、广告或付费 API。
做竖屏“躲陨石”:开始提示、底部飞船、从上方下落的圆陨石;按住拖动飞船左右躲避;存活秒数作为分数;碰撞后显示结束和得分;点击重新开始。用 requestAnimationFrame 和时间差更新,限制单帧 delta 和陨石数量,玩家不得越界;不使用图片。
本次用本机 Ollama 的 qwen3.8-27b:latest 生成首稿。回复达到输出上限,在触摸移动函数中途截断,不能直接运行;我补全了缺失的触点空值检查、边界限制、触摸结束回调和启动调用,再逐项检查后导入模拟器。练习包保留截断回复和可运行版本,方便逐处比较。
如果你使用其他代码助手,也可以复用这张需求卡;先只生成 game.js,能运行后再请求它补一项小功能。不要一开始就让它同时创建复杂素材、云函数和支付逻辑。
2. 建一个原生小游戏项目
下载并解压练习包,在微信开发者工具中选择“导入项目”,目录选到 project/。项目的 project.config.json 将 compileType 设为 game,入口代码是 game.js,竖屏方向写在 game.json。这与带页面路由的小程序工程结构不同。
导入页默认出现的 touristappid 不能用于这个小游戏工程;工具提示它是小程序 AppID,需要小游戏 AppID。点“测试号”,让开发者工具填入测试小游戏 ID,再创建项目并本地编译。本次在微信开发者工具 Stable 2.01.2510260 中验证通过,没有登录账号或使用真实主体 AppID。若你的工具没有“测试号”选项,就需要自己的小游戏 AppID 才能继续;不要把小程序游客 ID 当作小游戏 ID。
3. 读懂游戏循环
游戏每一帧都按同样顺序做三件事:算时间差、更新位置和碰撞、重新绘制画面。requestAnimationFrame 负责请求下一帧;把两帧之间的时间差限制在一个小范围,可以避免窗口卡顿后角色一下跳很远。
陨石用圆心和半径表示,飞船画成三角形,但碰撞时也用中心点和半径近似。代码比较两个中心点的距离是否小于半径之和;这是简单的圆形近似,判定范围不会贴合三角形的每条边。分数按存活秒数累加,陨石只在屏幕附近保留,避免数组越积越大。
触摸开始时,若游戏处于等待或结束状态就启动新一局;运行中则记录手指位置。触摸移动时,将 changedTouches[0].clientX 限制在左右边界内,更新飞船的中心位置。官方文档说明 macOS/Windows 开发者工具会把鼠标操作转换成触摸事件,因此可以用模拟器里的鼠标拖动做第一轮检查;真机手感仍需单独验证。
4. 在模拟器里逐条验收
导入并编译后,不要只看画面有没有打开。按表逐项操作:
| 检查 | 怎么做 | 合格结果 |
|---|---|---|
| 初始状态 | 首次编译 | 出现开始提示,没有提前计分 |
| 开始 | 点击画布 | 飞船、陨石和分数可见 |
| 左右控制 | 按住并拖动飞船 | 飞船跟手,左右不越界 |
| 碰撞结束 | 不躲避,等待碰撞 | 游戏停止并显示得分 |
| 重新开始 | 结束页点击 | 新一局分数回到 0,游戏继续 |
| 运行稳定 | 连续重开数次 | 无明显报错、画面仍可操作 |
若触摸无反应,先核对 wx.onTouchStart/Move 是否注册、读取的是 changedTouches,以及使用的坐标是否与 Canvas 逻辑尺寸一致。若只有碰撞判定看起来不自然,可以先调碰撞半径,不要同时改速度、刷新频率和坐标换算。
5. 本地预览不等于上架
本地模拟器只能证明这份工程在当前开发者工具环境里可运行。微信开发者工具命令行文档将 preview 和 upload 列为不同命令,并单列登录状态命令;本教程没有登录、预览上传或提交审核。
真正向微信平台提交前,需要项目主体自己的真实 AppID、开发者账号和相应权限,并按当时后台显示的小游戏类目、隐私、内容与审核要求逐项确认。即使上传成功,也不等于审核通过或正式上线。广告、付费、云端排行等能力各自需要额外申请、接入与测试,不能靠本地原型推断。
常见问题
为什么不能直接把网页小游戏复制过来?
网页通常从浏览器的 window、document 和 DOM 开始;小游戏工程使用微信提供的运行时与 API。让 AI 生成代码时先写清平台,再逐项核对对象和接口。
模拟器能跑,手机上就一定正常吗?
不能这样推断。模拟器验证的是当前电脑、工具版本和输入方式。不同屏幕比例、触控手感、帧率和真机性能还要在目标设备上测。
怎样增加功能?
先加入一种道具或一种陨石速度,再补对应的验收条件。排行榜、云存档和支付会引入账号、服务端或平台权限,应该在单机循环稳定后单独设计。
下一步可以把这一局改成“接到金币加分”:先明确金币的出现位置、拾取范围和得分变化,再让 AI 只修改碰撞与绘制部分,最后用相同的验收表回归。
来源与工具
- 微信小游戏 Canvas、
wx.createCanvas wx.onTouchStart、wx.onTouchMove、Touch 坐标- 微信开发者工具命令行 V2
- AI 代码助手可替换;本练习使用 Ollama 与本机 Qwen3.8-27B。游戏绘制只用 Canvas,不需要图片模型或第三方依赖。
封面背景由本机 ComfyUI 生成并由脚本排字;游戏画面由代码绘制,没有使用生成式游戏素材。