logo

用AI做网页小游戏:结构化需求与调试闭环

作者:很酷cat2026.11.14 09:22浏览量:1

简介:本文讲清如何用 ERNIE 5.5 Flash Preview 生成单文件网页小游戏。先把玩法拆成规则、界面、交互、数值、胜负五项需求,再通过运行、贴报错、分批修改的循环打磨可玩性,并附可直接复制的提示词、修正后的核心代码与发布检查清单。

一句话能出游戏,前提是需求说得清

很多人用一句话让模型做《羊了个羊》,拿到的版本却和脑子里的不一样。原因通常有两个。第一,需求缺细节,模型只能自由发挥。只说“做个羊了个羊”,它不知道卡牌有几层、槽位有几格、输了能不能重开。第二,没有调试闭环。第一版几乎一定有问题,比如点击穿透、卡牌重叠、计分错乱。如果只是重新生成一遍,问题大概率还会出现。

更稳的流程是:结构化需求,生成单文件代码,本地运行,描述现象并迭代修改,最后发布分享。本文按这个顺序展开,并给出可复制的提示词和修正后的关键代码。

传统做法与 AI 辅助的差别

环节 传统自研 AI 辅助(ERNIE 5.5 Flash Preview)
玩法设计 写策划案、画原型 用自然语言描述规则,模型补全数值与边界
界面搭建 手写 HTML/CSS、切图 直接产出单文件页面,可加入响应式布局
核心逻辑 自己实现状态机、碰撞、计分 生成可运行逻辑,并解释关键函数
调试 断点、日志、反复尝试 贴报错与现象,定位到具体函数修改
素材 找美术、做音效 用 CSS 或 Canvas 绘制,用 Web Audio 合成音效,或接入 CC0 素材
发布 配服务器、打包 静态文件上传到对象存储或 GitHub Pages

AI 主要缩短的是“从 0 到能跑”的时间。数值平衡和手感调优仍然要自己玩上几十局。

为什么选 ERNIE 5.5 Flash Preview

ERNIE 5.5 Flash Preview 是文心系列基础模型 ERNIE 5.5 Flash 的预览版本。官方介绍中,它重点强化了编程开发、智能体、知识工作与深度研究能力,并支持长上下文输入,可结合代码编写、工具调用与 Agent 工作流完成多步骤任务。对做游戏来说,有三个直接价值。

第一,长上下文能装下整个文件。做到第三轮迭代时,可以把完整的 index.html 连同修改要求一起提交,模型更不容易忘记前面定义过的变量和函数名。具体上下文窗口长度以千帆模型详情页为准。

第二,单文件输出能力强。游戏类需求很适合一个 HTML 文件完成,双击即可运行,发给朋友也能直接打开,不需要构建工具。

第三,擅长按指令约束输出。你可以要求“只用原生 JS,不引入第三方库”或“必须支持手机触屏”,模型会按要求执行。这对后续维护很关键。

模型的详细信息、版本与接入方式可以在 百度智能云千帆模型详情页 查看。想先体验效果,可以打开 ERNIE 5.5 Flash Preview 在线体验 输入游戏需求试一轮。

注意:模型本身是文本模型,产出的是代码和设计。图片、音效、3D 模型等二进制素材需要用外部工具生成,或从素材站获取,再由代码引用。游戏实际运行在浏览器中。

准备工作

准备工作很少,几分钟就能完成。

  • 现代浏览器:Chrome、Edge 或 Safari 的最新版本
  • 文本编辑器:VS Code 最顺手,记事本也能用
  • 新建一个 game.html 文件,所有代码都写在这里
  • 可选:Node.js,仅当你想用 npx serve 启动本地服务时需要。serve 默认监听 3000 端口,实际地址以终端输出为准

不需要安装 Unity,不需要游戏引擎,也不需要注册任何 SDK。

五步实操流程

第 1 步:把玩法写成结构化需求

只写“做个炸金花”,模型会自己补全大部分细节。应补齐五项:玩法规则、界面元素、交互方式、数值设定、胜负条件。缺哪一项,模型就会自行补充,补出来的内容往往不合你的意。

第 2 步:要求输出单文件代码

明确写出“单个 HTML 文件,原生 JS,内联 CSS,不引用外部资源”。这样生成的文件可以直接双击运行。

第 3 步:本地运行,收集第一手问题

打开页面,按 F12 进入控制台(Console)。把报错原文完整复制下来,连同你观察到的现象一起回贴给模型。这一步比重新生成更有效。

第 4 步:迭代修改,一次只改一类问题

如果同时提五个修改点,模型容易顾此失彼。建议按“致命 Bug、交互手感、数值平衡、视觉细节”的顺序推进,每轮只聚焦一类。

第 5 步:发布与分享

  • 最快的方式:把 HTML 文件直接发给朋友,通过微信或 QQ 传输后用浏览器打开。
  • 需要链接的场景:使用 GitHub Pages、Cloudflare Pages,或百度智能云对象存储 BOS 的静态网站托管,上传后即可获得公网地址。
  • 手机游玩:静态托管后用手机浏览器打开,再添加到主屏幕,体验接近原生 App。

发布前请确认文件中没有密钥、个人信息或未授权的素材。静态文件任何人都能打开,不要把敏感内容放进去。

可直接复制的 Prompt(游戏生成主模板)

把方括号内的内容换成你的需求即可:

  1. # 任务目标
  2. 生成一个可直接运行的单文件网页小游戏:[羊了个羊 / 炸金花 / 狙击射击]
  3. # 输入信息(玩法规则)
  4. - 游戏类型:[三消卡牌 / 扑克牌型比大小 / 定点射击]
  5. - 核心规则:[例如:卡牌共 3 层,点击卡牌进入底部 7 格槽位,槽内集齐 3 张相同即消除;槽位满 7 格且无可消除则失败]
  6. - 操作方式:[鼠标点击 / 手机触屏点击 / 鼠标移动瞄准加点击射击]
  7. - 数值设定:[关卡卡牌总数 90 张、槽位 7 格、倒计时 120 秒、弹匣 8 发]
  8. - 胜负条件:[清空全部卡牌为胜;槽位爆满为败]
  9. - 特殊规则(如有):[例如:同牌型比点数,点数相同判平局;A-2-3 为最小顺子,Q-K-A 为最大顺子]
  10. # 执行要求
  11. 1. 输出单个 HTML 文件,CSS 与 JS 全部内联,禁止引用任何外部文件、CDN 或图片链接。
  12. 2. 仅使用原生 HTML、CSS 和 JavaScript,不使用任何框架或第三方库。
  13. 3. 视觉素材用 CSS 渐变、Unicode 符号或 Canvas 绘制实现;音效用 Web Audio API 程序化合成。
  14. 4. 必须响应式适配:桌面端与手机竖屏均可正常游玩,触屏事件需与鼠标事件同时生效。
  15. 5. 手机端需包含 viewport meta 标签,并用 env(safe-area-inset-*) 处理刘海屏安全区。
  16. 6. 代码需分区注释:状态管理 / 渲染 / 交互 / 计分 / 主循环。
  17. 7. 关键逻辑(如牌型判定、消除检测、命中判定)请写成独立纯函数,便于后续单点修改。
  18. 8. 包含开始界面、游戏中 HUD(分数、剩余、倒计时)、胜利与失败弹窗、重新开始按钮。
  19. 9. 输出前自检语法,确保没有未定义的变量、函数名拼写错误或明显的类型错误。
  20. # 预期输出
  21. 1. 一个完整可运行的 HTML 文件代码块。
  22. 2. 代码后附一段简要说明:核心数据结构是什么、主循环在哪里、如需调整难度应修改哪几个常量。

三个案例的关键实现

案例一:羊了个羊(消除类)

这类游戏的难点在卡牌的层叠遮挡与可点击判定,消除本身并不复杂。下面的数据结构以卡牌左上角坐标 x、y 记录位置。

  1. // 每张牌记录层级与左上角坐标,层级高的覆盖层级低的
  2. const CARD_W = 60, CARD_H = 80;
  3. const state = {
  4. cards: [/* { id, type, layer, x, y, alive, el } */],
  5. slots: [], // 底部槽位,最多 7 个
  6. SLOT_MAX: 7,
  7. remain: 90
  8. };
  9. // 计算两张牌的重叠面积占单张牌面积的比例
  10. function overlapRatio(a, b) {
  11. const ox = Math.max(0, Math.min(a.x + CARD_W, b.x + CARD_W) - Math.max(a.x, b.x));
  12. const oy = Math.max(0, Math.min(a.y + CARD_H, b.y + CARD_H) - Math.max(a.y, b.y));
  13. return (ox * oy) / (CARD_W * CARD_H);
  14. }
  15. // 上层牌覆盖面积超过 60% 时,下层牌不可点击
  16. function isCovered(card) {
  17. return state.cards.some(c =>
  18. c.layer > card.layer && c.alive && overlapRatio(c, card) > 0.6
  19. );
  20. }
  21. // 入槽后检查是否有三张同类,有则消除
  22. function tryMatch(type) {
  23. const same = state.slots.filter(s => s.type === type);
  24. if (same.length === 3) {
  25. same.forEach(s => removeCard(s));
  26. return true;
  27. }
  28. return false;
  29. }

判定基于面积重叠,因此注释与代码一致。removeCard 需要同时把牌标记为不存活,并从 DOM 中移除。否则会出现牌已经消失却仍能点击的情况。

迭代时最常提的修改有两类:卡牌间距太小导致误触,以及槽位满 7 格后应立即判定失败并弹窗。

案例二:炸金花(规则判定类)

这类游戏的核心是牌型识别与比大小。逻辑密集,但规则边界清楚,很适合交给模型。下面的代码把牌面 r 取值为 1 到 13,其中 1 表示 A,花色 s 单独记录。

  1. // 判定三张牌的牌型,rank 越大越强:豹子 6 > 顺金 5 > 金花 4 > 顺子 3 > 对子 2 > 单牌 1
  2. function evaluate(cards) {
  3. const rs = cards.map(c => c.r).sort((a, b) => a - b);
  4. const suited = cards.every(c => c.s === cards[0].s);
  5. const isTrip = rs[0] === rs[1] && rs[1] === rs[2];
  6. const isPair = !isTrip && (rs[0] === rs[1] || rs[1] === rs[2]);
  7. const normalRun = rs[1] - rs[0] === 1 && rs[2] - rs[1] === 1; // 含 A-2-3
  8. const highRun = rs[0] === 1 && rs[1] === 12 && rs[2] === 13; // Q-K-A
  9. const isRun = normalRun || highRun;
  10. if (isTrip) return { rank: 6, name: '豹子' };
  11. if (isRun && suited) return { rank: 5, name: '顺金' };
  12. if (suited) return { rank: 4, name: '金花' };
  13. if (isRun) return { rank: 3, name: '顺子' };
  14. if (isPair) return { rank: 2, name: '对子' };
  15. return { rank: 1, name: '单牌' };
  16. }
  17. // 同牌型时的比较键,按位逐一比较,数值越大越强
  18. function tieKey(cards) {
  19. const { rank } = evaluate(cards);
  20. const rs = cards.map(c => c.r).sort((a, b) => a - b);
  21. // 顺子与顺金只比最大牌:A-2-3 最小(按 3 计),Q-K-A 最大(按 14 计)
  22. if (rank === 3 || rank === 5) {
  23. if (rs[0] === 1 && rs[1] === 2 && rs[2] === 3) return [3];
  24. if (rs[0] === 1 && rs[1] === 12 && rs[2] === 13) return [14];
  25. return [rs[2]];
  26. }
  27. // 其余牌型:先按出现次数降序(对子、豹子的牌面优先),再按点数降序
  28. const vals = cards.map(c => (c.r === 1 ? 14 : c.r));
  29. const count = {};
  30. vals.forEach(v => { count[v] = (count[v] || 0) + 1; });
  31. return vals.sort((a, b) => count[b] - count[a] || b - a);
  32. }
  33. // 返回正数表示 a 大于 b,0 表示平局
  34. function compareHands(a, b) {
  35. const ra = evaluate(a).rank, rb = evaluate(b).rank;
  36. if (ra !== rb) return ra - rb;
  37. const ka = tieKey(a), kb = tieKey(b);
  38. for (let i = 0; i < ka.length; i++) {
  39. if (ka[i] !== kb[i]) return ka[i] - kb[i];
  40. }
  41. return 0;
  42. }

这段代码有三处容易出错,需要特别留意。

第一,数组要用下标取值。rs 是三张牌点数组成的数组,比较首张牌时要写 rs[0],不能直接写 rs。cards[0].s 同理。

第二,顺子判断必须在排序之后进行。排序后的 [1, 2, 3] 同时满足普通顺子条件,所以 A-2-3 无需单独写一条分支。[1, 2, 13] 不构成顺子,因此 K-A-2 不成顺。

第三,同牌型比大小的规则要写进 Prompt。本文约定先比牌型,牌型相同再比牌面,牌面完全相同则平局,花色不参与比较。你可以改成自己的规则,但要把规则写死,否则模型每次生成的版本可能不一样。

下面是一个验证例子。Q-K-A 应当大于 A-2-3:

  1. const qka = [{ r: 12, s: '♠' }, { r: 13, s: '♥' }, { r: 1, s: '♦' }];
  2. const a23 = [{ r: 1, s: '♣' }, { r: 2, s: '♥' }, { r: 3, s: '♦' }];
  3. console.log(compareHands(qka, a23) > 0); // true

案例三:狙击游戏(实时交互类)

实时类游戏应当使用 requestAnimationFrame 作为主循环,而不是 setInterval。后者的帧率不稳定,命中判定也容易漂移。

  1. let last = performance.now();
  2. function loop(now) {
  3. const dt = Math.min((now - last) / 1000, 0.05); // 限制单帧步长,防止切到后台再回来时大幅跳帧
  4. last = now;
  5. update(dt); // 更新靶子位置、倒计时等状态
  6. render(); // 绘制画面
  7. requestAnimationFrame(loop);
  8. }
  9. requestAnimationFrame(loop);
  10. // 命中判定:用圆形靶心做距离检测,比矩形碰撞更贴合视觉
  11. function onShoot(mx, my) {
  12. if (state.ammo <= 0) return;
  13. state.ammo--;
  14. const hit = state.targets.find(t =>
  15. Math.hypot(t.x - mx, t.y - my) <= t.r
  16. );
  17. if (hit) {
  18. state.score += hit.score;
  19. state.targets = state.targets.filter(t => t !== hit);
  20. }
  21. }

上面的代码只包含主循环和命中判定。update 与 render 需要在 Prompt 中要求模型补全,或自行实现。复制代码前请确认这两个函数已经存在,否则页面会报错。

常见问题排查表

现象 大概率原因 回贴给模型的描述
页面空白,控制台报 xxx is not defined 函数定义晚于调用,或变量作用域错误 贴报错原文,并说明是第几步操作触发
手机点击没有反应 只绑定了 click,没有处理 touchstart “请同时支持触屏,并阻止 300ms 延迟与双击缩放”
卡牌点击穿透到下层 遮挡判定阈值不合理 “上层牌与当前牌的重叠面积超过 60% 时,下层牌不可点击”
游戏越快越卡 每帧都在创建和删除 DOM 节点 “改为 Canvas 渲染,或复用节点池,避免逐帧增删 DOM”
手机端布局错乱 缺少 viewport 设置,或没有处理安全区 “补充 viewport meta 标签,并用 env(safe-area-inset-*) 适配刘海屏”
音效不响 浏览器要求用户操作后才能播放音频 “首次点击时初始化 AudioContext 并调用 resume”
切到后台回来直接失败 倒计时用真实时间差计算 “倒计时按累计 dt 递减,页面隐藏时暂停”

检查清单:发布前逐项确认

  • 桌面端与手机端都能完整通关一次
  • 失败后可以一键重开,分数、倒计时、剩余牌数全部重置
  • 控制台没有报错
  • 没有外部资源依赖,断网也能玩
  • 难度、时长、弹药等关键数值集中定义为常量,方便自行调整
  • 页面标题与图标已改成你的游戏名
  • 文件中没有密钥、个人信息或未授权的素材

agent-">进阶:从生成代码到 Agent 工作流

批量制作游戏,或者要做包含关卡数据、排行榜、素材管理的完整项目时,可以借助 ERNIE 5.5 Flash Preview 的 Agent 与工具调用能力,把流程拆成多个步骤:需求拆解、生成关卡 JSON 配置、生成游戏代码、调用本地命令做语法检查、读取报错并自动修正、输出构建产物。这类多步骤任务正是模型重点优化的方向。

其中的“执行命令”“生成图片素材”“渲染视频”等步骤,必须在具备相应工具和运行环境的 Agent 框架中完成。模型负责规划、生成代码和判断结果。

小结

  1. 把玩法写成结构化需求,规则、界面、交互、数值、胜负条件五项齐全。
  2. 要求单文件原生实现,双击即可运行,方便分享。
  3. 建立调试闭环,贴报错原文并描述现象,每轮只改一类问题。
  4. 发布走静态托管,拿到链接就能分享。
  5. 手感需要自己调。AI 给出的是可运行的版本,好不好玩取决于你玩了多少局。

现在就选一个你小时候玩过的小游戏,把上面的 Prompt 填好,在 ERNIE 5.5 Flash Preview 在线体验 中跑出第一版。想接入自己的应用或做批量生成,可以到 百度智能云千帆模型详情页 了解模型能力与接入方式。先做出一个能玩的版本,剩下的都是迭代问题。

发表评论

活动