我用 AI 搓了一个"比谁更持久"的微信小游戏,AI实现只用了一天,微信审核却用了一个月!!!

事情的起因很简单:我想做一个让人"浪费时间"的小游戏。结果我自己在开发过程中浪费的时间,比任何玩家都多。

🤔 起因:一个沙雕想法的诞生

某天摸鱼的时候,我突然冒出一个想法------

"有没有一种游戏,就是把手指放在屏幕上不松开,看谁能坚持更久?"

就这?对,就这。

你别笑,我认真的。想想看,这个玩法有多完美:

  • 零门槛:会用手机就会玩,不需要任何游戏经验
  • 强社交:和好友比"谁更持久",标题自带传播属性(别想歪)
  • 杀时间:用户主动把时间浪费在你的游戏上,还乐在其中

我当时就觉得这个idea成了,于是打开了 Cursor,叫上了 AI 这个 24 小时在线、不要工资、不用交社保的"同事",开整。

📋 第一步:让 AI 帮我写游戏方案

作为一个有追求的开发者,我不会上来就莽代码。我先让 AI 帮我出了一份详细的游戏策划方案。

我大概描述了一下我的想法,AI 就给我输出了一份 360 行的 Markdown 策划文档,比我上学写的毕业论文都认真。里面包含:

  • 核心玩法规则(手指触摸、泡泡击破)
  • 6 种难度递增的阶段设计(从每 3 秒 1 个泡泡到每 0.3 秒 1 个,丧心病狂)
  • 3 种正面 Buff + 2 种负面泡泡 + 里程碑彩虹泡泡
  • 好友排行榜 + 全国排行榜(日榜/周榜/总榜 × 4 个维度)
  • 防挂机验证 + 心跳反作弊
  • 分享复活机制
  • 甚至连运营推广建议都给我写了

我看完方案的第一反应:这 AI 比我还了解我想做什么。

🏗️ 第二步:从 0 开始搓代码

技术栈选择

微信小游戏,Canvas 2D,原生 JS,微信云开发。没有用任何游戏引擎。

为什么不用 Cocos / Phaser 之类的引擎?因为这游戏的画面需求就是画几个圆(泡泡),上引擎属于杀鸡用牛刀,包体还大。

整个项目的文件结构长这样:

bash 复制代码
├── game.js                    # 入口,就 3 行(初始化云开发 + new Main)
├── js/
│   ├── main.js                # 游戏主循环(1081 行)
│   ├── databus.js             # 全局状态管理(776 行)
│   ├── bubble.js              # 泡泡类
│   ├── effects.js             # 粒子特效系统
│   ├── sound.js               # 音效管理(纯代码合成)
│   ├── render.js              # 屏幕适配
│   ├── base/pool.js           # 对象池
│   └── runtime/
│       ├── background.js      # 背景渲染
│       ├── hud.js             # 游戏内 HUD
│       └── screens.js         # 各页面 UI(714 行)
├── open-data-context/         # 开放数据域(好友排行榜)
│   └── index.js
└── cloudfunctions/            # 云函数
    ├── login/
    ├── submitScore/
    ├── getRanking/
    └── heartbeat/

别看游戏简单,代码量不少。AI 跟我协作得像一对老搭档,我说需求,它写代码,我改 bug,它再改 bug,完美的死循环。

游戏入口:世界上最短的入口文件

javascript 复制代码
import Main from './js/main';

wx.cloud.init({
  env: 'cloud1-4gcmmd7he3ad2269',
  traceUser: true,
});

new Main();

没错,game.js 就这么点东西。AI 说"入口文件应该保持简洁",我深以为然。

🫧 第三步:泡泡系统 ------ 灵魂所在

泡泡是整个游戏的灵魂。不是那种实心圆形的"泡泡",我要的是那种半透明的、有光泽的、像真的肥皂泡一样的泡泡

我跟 AI 说:"泡泡要好看,要有质感,要像真的。"

然后 AI 给了我一套多层渲染方案:

  1. 径向渐变主体:从中心到边缘的透明度变化
  2. 边缘薄膜质感:额外的环形渐变,模拟泡泡膜
  3. 细描边:带透明度的颜色描边
  4. 主高光:左上角白色弧形,模拟光源反射
  5. 次高光:右下角小反光点
  6. 特殊泡泡光晕:带脉动动画的外发光

看一下渲染代码的精髓部分:

javascript 复制代码
// 泡泡主体(半透明径向渐变,更像气泡)
const gradient = ctx.createRadialGradient(
  this.x - this.radius * 0.3,  // 高光偏移
  this.y - this.radius * 0.3,
  this.radius * 0.1,
  this.x, this.y, this.radius
);
gradient.addColorStop(0, this._lightenAlpha(this.color, 80, 0.35));
gradient.addColorStop(0.6, this._colorAlpha(this.color, 0.1));  // 中间几乎透明
gradient.addColorStop(1, this._colorAlpha(this.color, 0.28));

里程碑泡泡更骚,用了 HSL 色相旋转 做彩虹渐变效果:

javascript 复制代码
const hue = (Date.now() / 20) % 360;
gradient.addColorStop(0, `hsla(${hue}, 100%, 90%, 0.35)`);
gradient.addColorStop(0.6, `hsla(${(hue + 40) % 360}, 90%, 70%, 0.15)`);
gradient.addColorStop(1, `hsla(${(hue + 60) % 360}, 80%, 55%, 0.3)`);

每 20 毫秒色相旋转一度,这泡泡在屏幕上简直是彩虹在跳舞。

泡泡类型大全

类型 颜色 效果 出场时机
普通泡泡 彩虹七色随机 +1 泡泡计数 全程
加速泡泡 🟠 橙色 10秒内泡泡生成翻倍 随时
防护泡泡 🔵 蓝色 10秒内松手1秒不会死 随时
双倍泡泡 🩷 粉色 10秒内击破泡泡计数×2 随时
炸弹泡泡 💣 黑色 扣 10 个泡泡 + 震动 30分钟后
冰冻泡泡 🧊 淡蓝 暂停计时 5 秒 30分钟后
里程碑泡泡 🌈 彩虹色 鼓励文案 + 计数 每 5 分钟
验证泡泡 ❓ 金色 防挂机验证 静止30秒后

30 分钟后出现负面泡泡,这个设计我非常满意------早期让你爽,后期让你怕。玩家的手指在屏幕上既要追泡泡,又要躲炸弹,这种纠结的快感,妙啊。

💥 第四步:粒子特效系统 ------ 让戳泡泡有仪式感

戳泡泡如果没有特效,那跟咸鱼有什么区别?

我让 AI 搞了一套完整的粒子特效系统,包含三种特效元素:

  • 爆裂粒子:向四周飞散的小圆点,带微弱重力和减速
  • 冲击波环:从中心向外扩散的圆环
  • 缩放闪光:中心区域的径向渐变闪光

不同类型的泡泡,爆破效果还不一样:

javascript 复制代码
switch (type) {
  case 'normal':    this._normalPop(x, y, radius, color);    break;  // 6~9 个粒子
  case 'bomb':      this._bombPop(x, y, radius);              break;  // 16~22 个火焰粒子
  case 'freeze':    this._freezePop(x, y, radius);            break;  // 冰晶粒子(重力极低)
  case 'milestone': this._milestonePop(x, y, radius);         break;  // 18~24 个彩虹粒子
  // ...
}

炸弹泡泡爆破是五种火焰色的粒子乱飞 + 双层冲击波 + 强闪光,配合手机震动,效果拉满。

冰冻泡泡的粒子最有意思------AI 把重力设成了 0.005(正常是 0.02~0.05),所以冰晶粒子是"轻飘飘"地飞散,视觉上确实像冰碎了的感觉。这种细节,真的是 AI 给的惊喜。

🔊 第五步:音效系统 ------ 零文件,纯代码合成

这是整个项目里我最得意的部分:所有音效和背景音乐都是用 WebAudio API 实时合成的,没有任何音频文件。

零 mp3,零 wav,零 ogg,包体直接省了一大坨。

泡泡击破音效

javascript 复制代码
// 普通泡泡 "啵" 的一声
osc.type = 'sine';
osc.frequency.setValueAtTime(800 + Math.random() * 400, now);  // 随机起始频率
osc.frequency.exponentialRampToValueAtTime(200, now + 0.08);    // 快速下滑
gain.gain.setValueAtTime(0.15, now);
gain.gain.exponentialRampToValueAtTime(0.001, now + 0.1);       // 0.1秒衰减

就是一个 0.1 秒的正弦波快速下滑音,频率从 800~1200Hz 滑到 200Hz,听起来就是 "啵" 的一声。每次频率还随机,所以每个泡泡的破裂声都微妙不同,有种 ASMR 的快感。

炸弹爆炸音效

javascript 复制代码
osc.type = 'sawtooth';                                          // 锯齿波(粗糙感)
osc.frequency.setValueAtTime(150, now);
osc.frequency.exponentialRampToValueAtTime(40, now + 0.3);      // 低频下沉
// 还叠加了一层噪声!
const buffer = ctx.createBuffer(1, bufferSize, ctx.sampleRate);
for (let i = 0; i < bufferSize; i++) {
  data[i] = (Math.random() * 2 - 1) * (1 - i / bufferSize);   // 衰减白噪声
}

锯齿波低频下沉 + 衰减白噪声 = 低沉的 "轰" 一声。AI 甚至给噪声加了衰减包络,太专业了。

背景音乐:催眠又上头

BGM 是最疯狂的部分。AI 用几个振荡器合成了一首 梦幻五声音阶琶音 + 呼吸感和弦垫 + 低音根音 的背景音乐:

r 复制代码
层次结构:
├── Sub Bass(C2 正弦波)------ 低音底座
├── Pad 和弦垫(三角波 × 3)------ 和弦 C → Am → F → G 循环
│   └── LFO 调制音量 ------ 呼吸效果
└── 琶音旋律(C5 E5 G5 A5 ↑↓)------ 每 375ms 一个音符

和弦每 3 秒切换一次(C → Am → F → G),琶音用五声音阶上下行,LFO 控制和弦垫的音量做呼吸效果。

最终效果:催眠、舒服、有点上头。你手指放在屏幕上,听着这个 BGM 戳泡泡,时间不知不觉就过去了。

这就是用代码"作曲"的魅力------不需要请音乐人,不需要版权费,wx.createWebAudioContext() 就完事了。

🛡️ 第六步:防作弊 ------ 和外挂斗智斗勇

做排行榜就意味着:一定有人想作弊。

我跟 AI 商量了半天,最终实现了三道防线:

第一道:客户端防挂机检测

javascript 复制代码
// 手指 30 秒没动超过 5px = 疑似挂机
const idleTrigger = idleTime >= 30000;

// 每 5~10 分钟随机触发验证(防止固定时间被预判)
const periodicTrigger = now - db.lastVerifyTime >= db.nextVerifyInterval;

触发后在远离手指的位置生成一个金色验证泡泡,10 秒内不去碰就 Game Over。你得在不松开手指的情况下滑过去戳它,挂机党直接 GG。

生成位置还特意避开了手指当前位置(至少 120px 距离),确保需要主动移动:

javascript 复制代码
do {
  vx = margin + Math.random() * (SCREEN_WIDTH - margin * 2);
  vy = topSafe + margin + Math.random() * (SCREEN_HEIGHT - topSafe - bottomSafe - margin * 2);
} while (Math.sqrt((vx - db.touchX) ** 2 + (vy - db.touchY) ** 2) < 120 && attempts < 20);

第二道:心跳机制

客户端每 30 秒发一次心跳到云函数,带上当前时长和泡泡数。成绩提交时服务端会校验:

javascript 复制代码
// 上报时长与最后心跳时长偏差超过 60 秒 = 异常
if (Math.abs(duration - hbDuration) > 60000) {
  isValid = false;
  anomalyReason = '时长与心跳数据偏差过大';
}

// 单局超过 4 小时 = 可疑
if (duration > 4 * 60 * 60 * 1000) {
  isValid = false;
  anomalyReason = '单局超过4小时';
}

第三道:前后台切换检测

javascript 复制代码
wx.onHide(() => {
  if (this.databus.gameState === 'playing') {
    this.databus.isTouching = false;
    this.databus.gameOver();
  }
});

切后台、息屏、接电话?直接 Game Over,没商量。所以游戏开始前我们贴心地提示用户"建议开启手机勿扰模式"。

🏆 第七步:排行榜 ------ 攀比心是最好的留存

排行榜分两种:

好友排行榜

这个是微信小游戏的特色------必须通过开放数据域实现。简单说就是微信给你一个沙箱环境,里面能拿到好友的游戏数据,但只能在这个沙箱里渲染 UI,主域看不到具体数据。

主域发消息给子域:

javascript 复制代码
openDataContext.postMessage({
  type: 'showRanking',
  dimension: 'bestDuration',
  period: 'all',
  selfOpenId: this.openid,
});

子域接收消息,调用 wx.getFriendCloudStorage 拿数据,然后在独立画布上画排名列表。主域再用 ctx.drawImage(openDataCanvas) 把子域画布贴到主画布上。

这个流程说起来简单,实际踩了不少坑------比如 getFriendCloudStorage 需要用户点击上下文才能调用(微信的安全限制),隐私授权得先过...后面讲。

全国排行榜

全国排行榜用云数据库的聚合查询实现。日榜和周榜需要从 scores 表按用户分组聚合:

javascript 复制代码
const aggRes = await db.collection('scores')
  .aggregate()
  .match({ dayKey: todayStr, isValid: true })
  .group({
    _id: '$_openid',
    aggValue: isTotal ? $.sum(`$${scoreField}`) : $.max(`$${scoreField}`),
  })
  .sort({ aggValue: -1 })
  .limit(50)
  .end();

4 个排名维度(单局最长时长、单局最多泡泡、总时长、总泡泡)× 3 个时间周期(日榜、周榜、总榜)= 12 种排名方式。攀比心直接拉满。

😤 第八步:隐私授权 ------ 微信审核の噩梦

2023 年微信搞了个"用户隐私保护指引",小游戏必须走隐私授权流程,否则很多 API 调不通。

这块逻辑是整个项目里最"不游戏"的部分,但不做不行:

javascript 复制代码
// 注册隐私授权回调
wx.onNeedPrivacyAuthorization((resolve, eventInfo) => {
  // 如果本次会话已经完成过隐私授权,直接放行
  if (this.privacyResolved) {
    resolve({ buttonId: 'agree-btn', event: 'agree' });
    return;
  }
  this.privacyResolve = resolve;
  this.showPrivacyPopup = true;  // 弹出自绘制的隐私弹窗
});

弹窗是纯 Canvas 手绘的,包括圆角白色面板、标题、正文、隐私协议链接(带下划线)、同意/拒绝按钮。按钮点击检测全靠坐标碰撞------对,就是最原始的 hitTest。

这里有个大坑:getFriendCloudStorage 不仅需要隐私授权通过,还需要在用户点击上下文中调用。也就是说:

  1. 隐私弹窗同意后不能立即调用(异步回调,没有点击上下文)
  2. 必须让用户再次点击按钮,此时隐私已生效 + 有点击上下文
  3. 所以代码里 _onPrivacyAgree 完成后直接清除 pendingAction,不执行挂起的操作

这个 bug 我调了很久才明白,AI 也是反复和我讨论了好几轮才搞定。微信的安全机制,说多了都是泪。

🎨 第九步:UI 全部手绘

整个游戏没有用一张 UI 图片(logo 和分享图除外),所有界面元素都是 Canvas 2D 绑定绘制的:

  • 圆角矩形按钮(渐变填充 / 描边两种风格)
  • 按钮按下动画(缩小 95% + 下移 2px + 颜色变暗)
  • 脉动动画的触摸引导圈
  • 半透明 HUD 信息条
  • 排行榜列表(斑马纹背景 + 前三名金银铜色)
  • 装饰性浮动泡泡(15 个半透明泡泡在背景缓慢漂移)

按钮按下动画的实现挺优雅的:

javascript 复制代码
if (pressed) {
  ctx.save();
  const cx = x + w / 2;
  const cy = y + h / 2;
  ctx.translate(cx, cy);
  ctx.scale(0.95, 0.95);       // 缩小到 95%
  ctx.translate(-cx, -cy + 2); // 下移 2px
}
// ... 绘制按钮 ...
if (pressed) ctx.restore();

以中心为锚点缩放,加一丢丢下移,再把颜色调暗一点,就有了很自然的按下反馈。不需要引入任何 UI 框架。

🎯 第十步:对象池 ------ 性能的保命符

泡泡这种高频创建、短命的对象,如果每次 new Bubble(),GC 会疯。所以用了对象池:

javascript 复制代码
// 获取泡泡:池里有就拿,没有就 new
getItemByClass(name, className) {
  const pool = this.getPoolBySign(name);
  return pool.length ? pool.shift() : new className();
}

// 回收泡泡:扔回池里
recover(name, instance) {
  this.getPoolBySign(name).push(instance);
}

泡泡消失时不销毁,而是回收到池里。下次生成新泡泡时从池里取,重新 init() 就行。整个游戏运行过程中,泡泡对象几乎不触发 GC。

这也是 AI 一开始就建议的架构------"长时间运行的游戏,对象池是必须的"。说得对。

🔢 一些有趣的数字

  • 总代码行数:约 4000+ 行(含云函数和开放数据域)
  • 游戏入口文件:3 行有效代码
  • 音频文件数量:0 个
  • UI 图片数量:0 个(logo 和分享图除外)
  • 泡泡类型:8 种
  • 排名维度:4 × 3 = 12 种
  • 特效类型:6 种(普通/Buff/炸弹/冰冻/里程碑/验证)
  • Buff 种类:3 正面 + 2 负面
  • AI 的工作时长:不可计量(它不需要睡觉)
  • 我的工作时长:不想计量(怕自己哭)

💬 和 AI 协作的一些感悟

整个项目从方案到实现,AI 承担了大概 90% 的代码量。但这不意味着我是甩手掌柜------恰恰相反,你得非常清楚你想要什么,AI 才能给你什么

几点体会:

  1. 方案先行:先让 AI 出策划方案,review 之后再动手写代码。好的方案能省掉后面 80% 的返工。

  2. 小步快跑:不要一次性让 AI 写完所有代码。一个模块一个模块来,写完测试,再写下一个。AI 写出来的代码不一定能跑,但大部分时候方向是对的。

  3. AI 很擅长"细节填充":比如泡泡的渲染层次、粒子的重力参数、音效的频率曲线这些,我只需要说"我要一个冰冻的感觉",它就能给出合理的参数。

  4. AI 不擅长"平台特性":微信小游戏的隐私授权、开放数据域、点击上下文这些平台特有的坑,AI 经常踩。需要你自己去翻文档、调试、把错误信息喂给 AI 再改。

  5. 代码合成音乐真的很酷:这是我第一次用代码"作曲",虽然曲子很简单,但整个过程非常有创造力。推荐每个开发者都试试 WebAudio API。

🎮 最终效果

游戏名:指尖持久战

核心玩法:手指放在屏幕上,别松开。滑动手指戳泡泡。看谁坚持更久。

就是这么简单,就是这么上头。

"你就说你能坚持多久吧?"


技术栈总结

  • 前端:微信小游戏 Canvas 2D + 原生 JS
  • 后端:微信云开发(云函数 + 云数据库)
  • 音效:WebAudio API 实时合成
  • UI:Canvas 手绘,零 UI 框架
  • 特效:自实现粒子系统
  • 工具:Cursor + AI

如果你觉得这篇文章有点意思,点个赞呗。毕竟我手指已经在屏幕上按了很久了(写这篇文章的时候)。

相关推荐
Ts-Drunk2 小时前
[特殊字符]深度解剖!Hermes-Agent 源码全解析(架构+核心流程+二次开发指南)
人工智能·架构·ai编程·hermes
恋猫de小郭2 小时前
AI 的公开测评得分都在作弊,就像泡面的封面,一切以实物为准
前端·人工智能·ai编程
砖厂小工2 小时前
Android 开发的 AI coding 与 AI debugging
android·ai编程
怕浪猫2 小时前
第12章 工具(Tools)与函数调用(LangChain实战)
langchain·aigc·ai编程
小程故事多_802 小时前
从Claude Code源码泄露,读懂12个可复用的Agentic Harness设计模式(生产级落地指南)
人工智能·设计模式·aigc·ai编程·harness
haibindev12 小时前
受够了Vibe Coding的失控?换个起点,让AI事半功倍
ai编程·claude·代码复用·vibe coding
虚无境13 小时前
关于10年工作经验的程序员对OpenClaw的实战经验分享以及看法
程序员·openai·ai编程
码农BookSea15 小时前
ReAct:让大模型学会边想边做
后端·ai编程
xiejava101815 小时前
写了一个WebDAV的Skill解决OpenClaw AI助手跨平台协作难题
人工智能·ai编程·智能体·openclaw