当前位置: 首页 > news >正文

用Vibe Coding 13天开发怀旧挂机游戏:AI辅助编程实践

vibe coding 最近在开发圈里讨论很多,简单说就是:用自然语言描述需求,让 AI 代码助手帮你搭骨架、补模块,你再按反馈调试调整。我这次用 13 天做了一个怀旧网游主题的放置挂机小项目,名字叫“QQ华夏挂机版”,用来纪念 18 年前泡在网吧打网游的日子。整个过程基本没离开三条原则:先把场景想清楚,再让 AI 动手,最后自己验收。

先说结论:vibe coding 很适合做这种“个人怀旧项目”。它不需要一开始就把架构设计完整,也不需要专业美术资源,只要你有明确的核心玩法,AI 就能帮你把大部分重复代码生成出来。但真正决定项目能不能完成的,不是 AI 的生成速度,而是你自己的判断力——哪些功能值得做,哪些功能做到一半就该停,哪些问题必须手动修。

这篇文章就按我的实际开发顺序拆一遍。不涉及任何真实游戏账号、真实服务器或官方资源,纯属自娱自乐的独立小游戏,用 HTML5 Canvas 做一个本地运行的单机放置玩法。我会把它当成一个可以复现的开发案例来讲,包括开发前准备、13 天的节奏、核心逻辑落地、AI 代码验收和下一步扩展。

1. 先明确 vibe coding 适合解决什么

1.1 我理解的 vibe coding 是“可运行的草稿”

vibe coding 这个词火起来之后,很多人把它理解成“随便说说,AI 全自动写代码”。我的实际感受是,它更像一种高频反馈的开发方式:你把一个很小、很具体的目标丢给 AI,比如“写一个二维网格地图,地图上有树、石头和水”,AI 返回代码,你运行,看效果,发现问题再继续描述。

关键不是句子有多自然,而是你描述的需求足够小。我一开始也试过让 AI 直接生成“一个完整的放置挂机游戏”,结果它给了我一个塞满模块但完全跑不起来的项目。后来我改成一次只描述一个功能,代码质量立刻提升很多。所以我会把 vibe coding 定义成“能跑的草稿”,不是“一步到位的完整产品”。

1.2 它适合个人开发者的地方

个人开发者做小项目,最大的成本往往是时间和决策,而不是写代码本身。vibe coding 最大的价值是把“从零到能跑”的时间压缩得很短,尤其适合下面几类项目:

  • 快速验证玩法:想知道自动战斗、掉落、升级这一套循环有没有意思。
  • 怀旧向个人项目:不用在乎商业价值,关键是还原记忆里的感觉。
  • 学习性质的项目:通过 AI 生成的代码反推实现思路,边跑边理解。
  • 小工具和小游戏:结构简单、依赖少、不需要复杂服务器。

在这些场景里,AI 写的代码不需要完美,也不需要考虑团队协作、性能优化和长期维护。优先考虑的是:能不能跑通,能不能在这个基础上快速改。

1.3 不适合直接交给 AI 的地方

同时也要认清边界。如果项目涉及复杂实时同步、支付、账号体系、高并发渲染,或者对性能和安全性有严格要求的业务系统,我不建议用 vibe coding 作为主力方式。AI 能生成一段看起来合理的代码,但它可能缺少异常处理、边界校验和性能考虑。

例如我如果真要做一款面向大量玩家的多人在线游戏,需要处理角色位置同步、背包一致性和防作弊,这个阶段靠 vibe coding 撑不住。个人怀旧项目则没有这些问题,因为使用者只有我,数据也只在本地。

1.4 这个怀旧项目的目标定义

在动手前,我给这个项目定了一个很明确的目标:做一个“能玩一下午”的放置小游戏,让我找回 18 年前那种打怪、捡装备、升级、做任务的感觉,但所有内容都是自己写的,不涉及任何真实的游戏资源。

“能玩一下午”是有判断标准的:能进入地图、角色会自动寻找怪物并战斗、有掉落、有背包、有基本任务、死亡后可以复活或重开,存档不会丢。这五条做到了,项目就算达到预期。

2. 开发前准备:场景、素材、边界、验收

2.1 先把游戏循环写成一段话

我建议你在让 AI 写代码之前,先用一段自然语言把游戏循环写清楚。这一步看着简单,实际上决定了整个项目的骨架。我当时写的是:

“玩家从新手村出发,地图上有若干怪物。角色会自动靠近最近的怪物并攻击。怪物死亡后会掉落金币、材料和装备。玩家拾取后放入背包,可以打开背包查看装备并穿戴。角色获得经验后升级,属性提升。每隔一段时间,NPC 发布一个简单任务,完成任务获得额外经验。玩家可以存档,重新打开项目后继续玩。”

这段话就是后续所有开发需求的出发点。AI 每次生成代码时,我都会把这一段放在需求描述里,防止它理解成“要做一个完整的 3D 大型网游”。

2.2 素材不靠画的套路

这是很多新手最担心的问题:我不会画图,怎么做游戏?我的做法很简单,就是用色块、文字和简单形状拼出视觉效果。

  • 地图:用二维数组表示,1 表示墙,0 表示可走路面,2 表示树。
  • 角色:用一个圆形或矩形方块表示,用颜色区分玩家和怪物。
  • 怪物:不同颜色、不同大小的方块区分等级。
  • 装备:不需要图片,背包里用名字加颜色字符串显示。

这样做的原因是,vibe coding 阶段的核心是验证玩法。只要地图、角色、怪物都能被清楚识别,画面的精细程度可以放到后面再补。如果有人觉得方块太粗糙,可以用像素风格素材或免费图标替换,但那是第二个阶段的事。

2.3 边界定清楚,才不会被 AI 带偏

给 AI 描述需求时,边界比功能更重要。我需要明确告诉 AI“不做”什么,避免它越加越多:

  • 不接入任何真实游戏服务器
  • 不做账号登录
  • 不做在线聊天
  • 不做商城和充值
  • 不做真实游戏品牌的美术还原
  • 不做 3D 效果
  • 不做复杂 AI 行为,怪物只要会刷新、会被攻击、会掉落就行

边界定清楚之后,AI 生成的内容会收敛很多。它不会动不动就给你加一个“登录注册页面”或者“支付回调接口”。这些功能在真实项目里很有用,但在一个怀旧小项目里只会拖慢进度。

2.4 工具和运行环境

我的项目选择是 HTML5 + JavaScript,用 Canvas 渲染画面,所有逻辑放在本地浏览器里运行。这样不需要安装复杂环境,也不需要买服务器,打开一个 HTML 文件就能测试。

类别我的选择原因
运行方式本地浏览器环境简单,调试方便
客户端语言JavaScript / HTML5 Canvas适合快速搭建小游戏
游戏类型单机放置 RPG不需要同步和服务器
存档方式localStorage 或下载存档文件本地保存,免部署
AI 工具任意 AI 代码助手关键是迭代,不是具体品牌

如果你希望以后打包成桌面应用,可以在原型完成后用 Tauri 或 Electron 包一层壳。但我的建议是:第一版不要打包,先把网页版跑稳定了再说。打包会引入新的安装依赖和跨平台问题,和游戏本身的玩法没有关系。

2.5 验收标准

验收标准要可执行,不能只说“好玩”。我给自己定的是:

  • 地图能加载,角色能移动
  • 角色会自动寻怪、攻击、获得经验
  • 背包能打开,能查看物品数量
  • 装备能穿戴,攻击力发生变化
  • 任务能接受、能完成、能领取奖励
  • 刷新页面后进度不丢失

任何一条没通过,都不算完成。有了这套验收标准,我每天结束前只需要问一个问题:“今天做出来的版本,哪几条通过了?”如果只做了一堆代码但没有通过任何验收项,那就说明走了弯路。

3. 13 天开发节奏拆解:每天只盯一件事

3.1 第 1 到 2 天:搭建够用的骨架

前两天的目标不是做玩法,而是让项目跑起来。我让 AI 生成一个最基本的 Canvas 游戏循环:有画布、有背景色、有一个可移动方块,有每秒刷新 60 次的 update/render 逻辑。

这个阶段最容易出现的错误是“脑子里想得太大,手上一行代码还没写”。我建议把它压到最小:一个页面,一个游戏循环,一个方块。检验标准只有一个:浏览器打开,方块能随着键盘移动。

第 2 天我补了两个基础模块:地图数据和碰撞检测。地图用二维数组表示,角色移动时判断目标格子是不是墙。这个模块后面所有玩法都依赖它,值得先做。

3.2 第 3 到 5 天:地图、移动和碰撞

第 3 天,我开始让 AI 生成一张 20x15 的小地图。地图四周是墙,中间有若干障碍物和空地,角色从左上角出生。这里不需要复杂寻路,只需要“按方向键移动”。

第 4 天处理碰撞。最简单的做法是:每次移动前计算目标位置,如果目标位置的格子是墙,就停在原地。这个逻辑即使通过 AI 生成,也要自己理解,否则后续怪物碰撞会出问题。

第 5 天我把地图可视化了。用不同颜色区分草地、道路、墙、树,这样看起来才像一个“小世界”。到这里,核心框架已经成立,剩下的事情可以放心交给后续迭代。

3.3 第 6 到 9 天:战斗、怪物和掉落

第 6 天到第 9 天是最核心的玩法阶段。我把功能拆成四个小批次:

  • 第一批:场景里生成 5 个怪物,角色靠近后按空格攻击。
  • 第二批:怪物被攻击后血量下降,血量为 0 时消失,角色获得经验。
  • 第三批:怪物死亡后掉落随机物品,物品掉在地图上可以被拾取。
  • 第四批:角色属性面板显示生命、攻击、等级、经验条。

每次只让 AI 做一个批次。需要特别注意的是,不要让怪物同时在多个逻辑里被处理。如果刷怪、攻击、掉落都堆在一个函数里,后面会很难排查。我通常会让 AI 拆成独立的函数,并在函数名上体现职责,例如spawnMonsterattackTargetgenerateDrop

3.4 第 10 到 12 天:挂机循环、背包和任务

第 10 天把“手动攻击”改成“自动攻击”。角色只要在怪物附近,就会根据自己的攻击速度自动攻击。这就是题目里说的“挂机版”的核心玩法:角色能自己打怪、自己升级,玩家只需要偶尔打开背包整理装备。

第 11 天做背包。背包数据是一个数组,每个物品有名称、类型、数量、属性。界面放在画布右侧,按 B 键打开。这个部分代码量不大,但比较繁琐,AI 很适合处理这种表单类逻辑。

第 12 天做任务系统。我只能提醒:不要一开始就设计十个任务。做两个通用任务就够了,比如“击败 5 只野狼”和“拾取 3 个材料”。任务系统其实是状态机:未接受、进行中、可提交、已完成。只要把这个状态流转做好,后面加任务只是加数据。

3.5 第 13 天:体验问题清理和打包

最后一天我没有加新功能,只做三件事:

  • 修复已知的诡异 bug,比如怪物重叠、攻击距离过大、物品拾取不到。
  • 清理控制台报错,保证浏览器打开只有 0 个错误。
  • 把保存功能调到“刷新页面后自动恢复”的状态。

这里有个经验:新功能永远做不完,体验问题和关键 bug 才决定项目能不能真正玩起来。第 13 天看起来没有“新产出”,但它决定了这个项目是一个能玩的游戏,还是一个半成品代码库。

4. 核心逻辑怎么落地:地图、战斗和自动挂机

4.1 地图:先用二维数组,再做可见地图

我用二维数组做地图,每一格代表一个地块类型。示例:

const map = [ [1, 1, 1, 1, 1, 1, 1], [1, 0, 0, 2, 0, 0, 1], [1, 0, 1, 1, 0, 0, 1], [1, 0, 0, 0, 0, 2, 1], [1, 1, 1, 1, 1, 1, 1] ];

这里1是墙,0是可行走区域,2是装饰物。角色移动时,只要目标位置不是1就可以走过去。

这个方案的好处是调试非常直观。你想知道某个地方能不能走,直接看数组就行。等玩法稳定后,如果想换成图片风格,再做一个“地图块到图片”的映射即可。

4.2 角色属性:成长感靠数值曲线

角色属性通常包括:生命值、攻击力、防御力、移动速度、攻击速度、经验值、等级。数值不用复杂,但曲线要有感觉。

我用的公式类似:下一级所需经验 = 当前等级 * 80 + 上一级经验。这样前期升级快,后期升级慢。攻击力和生命值则用“基础值 + 等级 * 成长值”计算。

如果你不确定数值怎么调,可以先给 AI 一个粗略参数,再自己跑一遍感觉。实测时最容易发现的问题是:前期太容易死,或者后期打一个怪要打一分钟。遇到这种问题,优先调攻击速度和攻击力,不要调地图和怪物数量。

4.3 自动战斗循环:核心循环怎么写

自动战斗是挂机玩法的关键。它不需要很复杂,核心就是:找最近的敌人,移动到攻击距离内,然后攻击。示例代码只表达思路:

function updateAutoBattle(game, dt) { if (!game.player.alive) return; const target = game.findNearestEnemy(game.player.x, game.player.y, 200); if (!target) return; if (game.distance(game.player, target) > target.attackRange) { game.moveToward(game.player, target, game.player.moveSpeed * dt); } else { game.player.attackTimer -= dt; if (game.player.attackTimer <= 0) { target.hp -= game.player.attackPower; game.player.attackTimer = game.player.attackSpeed; if (target.hp <= 0) { game.generateDrop(target); game.removeEntity(target); game.player.exp += target.exp; game.checkLevelUp(game.player); } } } }

这段代码不是完整版本,但它体现了挂机循环的关键点:角色不需要玩家操作,系统每帧判断一次状态并执行“寻找目标、移动、攻击、结算”四个步骤。

实现时容易忽略的是攻击计时器。每个角色得有独立的attackTimer,不然多个角色会共享同一个攻击冷却,导致攻击频率完全错乱。

4.4 掉落、背包和装备

怪物死亡后,我让系统生成一个掉落物对象,包含物品 ID、名称、类型、数量、地图坐标和拾取范围。玩家走过去碰到掉落物,掉落物从地图上移除并加入背包。

背包数据建议用数组,不要用对象。因为玩家可能会捡到多个相同物品,用数组配合数量字段比较直观。每件物品的信息都来自一个物品配置表,示例:

{ "id": "sword_02", "name": "铁剑", "type": "weapon", "attack": 12, "desc": "比木剑结实一点" }

装备系统可以做得更简单:玩家打开背包,选择武器或防具,点击穿戴,角色攻击或防御属性即时更新。这里不需要做复杂的装备槽位计算,一个“武器”和“防具”槽位就够了。

4.5 任务、NPC 和存档

任务系统要独立于战斗逻辑。状态机是任务最稳定的实现方式:任务状态分为idleactivecan_completecompleted。每次击杀怪物或拾取物品时,通知任务系统更新进度。

存档方面,最简单的方式是把关键数据转成 JSON 存入 localStorage。存档内容包括角色位置、等级、经验、生命、背包列表、任务进度和地图上的掉落物。刷新页面时读取存档并恢复。

但要注意:localStorage 是本地存储,换浏览器、清缓存都会丢。如果你要长期使用或分享给别人,最好再做一个“导出存档文本”的功能。

5. AI 代码的验收与排错:不能只看“能跑”

5.1 先把问题分成四类

AI 生成的代码第一次往往能跑,但跑起来不一定正确。我把问题分成四类,每类处理方式不一样:

问题类型表现处理方式
语法错误报错、页面白屏直接让 AI 修复,通常很快
逻辑错误不报错但行为不对看具体场景,给 AI 复述“预期行为”
边界问题怪物死亡后掉落消失、攻击距离异常自己补全条件判断
设计问题数值崩坏、流程太绕需要自己决定怎么改,不能全靠 AI

排错时最忌讳的是直接说“你写的代码有 bug”。AI 知道代码有 bug,但它不知道你的预期是什么。正确做法是描述场景和预期:当怪物血量小于等于 0 时,应该生成掉落物并移除怪物,但当前怪物消失了没有生成物品。这样 AI 才有修的方向。

5.2 我踩过的五个典型坑

第一个坑:地图坐标和画布坐标混淆。地图是二维数组,角色移动走的是行列坐标,但画布渲染需要像素坐标。AI 经常在这两种坐标间来回混用,结果角色走到墙里或飞出地图。解决办法是统一约定:逻辑坐标用地图格子坐标,渲染时乘以格子大小。

第二个坑:怪物重叠。刷怪时没有检查位置,多个怪物生成在同一个点。攻击目标计算时,角色会一直追到最近的怪物,看起来像在打空气。解决办法是刷怪时检测目标位置是否已有怪物,如果有就换一格。

第三个坑:攻击距离过远。AI 默认生成的角色攻击距离可能覆盖半个屏幕,角色还在地图另一头就能打到怪。后来我统一给每个怪物设了攻击范围,角色也要走进这个范围才能攻击。

第四个坑:存档恢复后位置错误。存档存的是地图坐标,恢复时没有判断该位置是否是墙,结果角色复活到墙里面。解决办法是读取存档后先做一次碰撞检查,如果目标位置是墙,就移动到最近的空地。

第五个坑:AI 不断往代码里加功能。我让它优化背包显示,它顺手加了一个“商店系统”,还加了几个没用的接口。后来我严格限制每次需求范围,并明确说“不要增加需求外的新功能”。

5.3 固定排查顺序

遇到问题时,我建议按这个顺序排查,不要一开始就改代码。

  1. 先看现象:是白屏、报错、卡住、没反应,还是行为怪。
  2. 再看控制台:有没有红色报错,报错信息指向哪个文件和哪一行。
  3. 再看输入状态:地图数据、角色位置、怪物列表是否正常。
  4. 再看参数:攻击距离、攻击速度、移动速度是否有明显异常值。
  5. 再改代码:尽量一次只改一个变量或一个条件,然后重新运行。

很多看起来像 AI 笨的问题,最后发现是我自己没有把输入描述清楚。例如我没说“角色的出生点不能是墙”,AI 生成随机坐标时就完全有可能生成到墙里。这类问题不是 AI 能力不足,而是需求边界缺失。

5.4 防止需求漂移

vibe coding 很容易让人“先做做看”,结果做着做着就偏离原目标。我在项目中期就有一次想加“宠物跟随”系统,后来一想,这跟怀旧初体验没有任何关系,果断砍掉。

防止需求漂移的办法是:每次增加功能前,问自己三个问题。

  • 这个功能是不是核心游戏循环的一部分?
  • 不加它,玩家会不会觉得这个游戏不完整?
  • 如果加它,需要多久,会不会拖慢已有功能?

如果三问里有两个是“否”,就不加。这样我才能把 13 天的时间真正花在核心体验上。

6. 从 13 天原型继续深化:性能、玩法和发布

6.1 性能检查别凭感觉

14 天之后,如果还想继续做,我建议先做一次性能检查,不要凭“感觉还行”来判断。重点看三类指标:

  • 帧率:浏览器里能不能稳定在 50 到 60 帧。
  • 实体数量:地图里同时存在多少个怪物和掉落物时开始卡顿。
  • 逻辑耗时:自动战斗循环里的距离计算和对象遍历是否每帧都在做。

实测方法很简单:把怪物数量从 10 调到 50,再调到 100,观察帧率变化。如果明显掉帧,优先优化的是“每帧遍历全体怪物”的逻辑。可以改用空间分块,或者减少掉落物消失时间。对于个人项目,能保证 30 个到 50 个怪物同时在场不掉帧,基本就够用了。

6.2 可玩性改进方向

如果只追求可玩性,我建议优先改进三个方面,而不是加系统。

  • 成长反馈:每升一级弹出属性变化,让玩家有明确“变强了”的感觉。
  • 选择空间:多设置几种武器或技能,让不同玩家有不同路线。
  • 任务引导:前期任务要告诉玩家“下一步做什么”,避免挂机后没有目标。

注意,这些改进要基于现有数据做。你可以先记录每局游戏的平均时间、角色平均等级、掉落物拾取率,再决定改哪里。

6.3 从本地原型到对外展示

如果你想把这个项目分享出去,除了贴代码,最好做一个可以访问的静态页面。构建和部署这一步不算复杂,但要注意:

  • 路径要写相对路径,不要用本地绝对路径。
  • 资源文件要压缩,地图数据可以换成 JSON 文件。
  • 存档用 localStorage 时,换浏览器会丢,建议导出存档。

如果要用桌面应用形式发布,再考虑用 Tauri 或 Electron 打包。但对一个 13 天完成的怀旧小游戏来说,跑在浏览器里已经足够。过度封装反而会消耗很多时间。

6.4 是否要继续投入的判断

项目做完后,我冷静想了一下:它值不值得继续做?判断标准不是“代码好不好”,而是“我还想不想玩”。

如果我自己玩了两天还有兴趣,说明它具备继续打磨的基础。如果我自己都不想打开,就没有必要继续堆功能。怀旧项目最重要的是表达情感和验证想法,它不需要变成一个复杂产品。

所以我最后给出的建议是:13 天版本的目的是让你确认“用 vibe coding 做一个小游戏”这条路走不走得通。走通之后,你可以选择继续优化,也可以把它当作一个里程碑,然后开始下一个更有挑战的项目。

如果你也想做类似的项目,我建议从更小的范围开始,例如“一个角色、一张地图、一种怪物、一次掉落”,跑通后再逐步扩展。不要给自己设太高的上线标准,毕竟做出来的本身就是对当年那段时光的一种纪念。

http://www.cnnetsun.cn/news/4298747.html

相关文章:

  • WinForm自定义打印设计工具:从可视化设计到动态数据打印的完整实现
  • JavaScript基础快速入门:2小时从核心语法到交互实战
  • DGX Spark机器学习环境配置实战:从驱动到多机推理全指南
  • AI编程辅助Cheat Engine Lua脚本开发实战指南
  • 指人游戏搬到网页:实现线上聚会互动玩法的技术指南
  • WASI 0.3.1:WebAssembly系统接口能力模型与工程实践
  • AI时代产品经理核心壁垒:从问题定义到结果验证
  • opencode无法使用GPT模型?从报错分类到环境配置的完整排查思路
  • Windows系统盘爆满?用PowerShell深度清理C盘垃圾文件
  • 大型国际会议口译服务标准流程:从会前准备到现场执行全指南
  • Codex 零基础完全上手:安装配置、接入 DeepSeek 与常见报错排查
  • MATLAB实现接触角自动测量:图像处理与轮廓拟合实战
  • Python零基础入门路线:环境配置、核心语法与实战脚本全解析
  • GT911驱动开发实战:I2C电容触摸从裸机到Linux完整实践
  • 树莓派+传感器:列车靶场自动音乐播放系统设计与实现
  • C盘爆红不用慌:从休眠文件到分区扩容,榨干每一GB空间
  • 条件工作流避免烂尾:用类型系统建模分支判断
  • 自托管AI代码审查Agent Proval:打通GitLab、Forgejo、GitHub
  • 技术选型评估:把“多系统验证”和“即时回报”翻译成可验证的尽调指标
  • Spring Boot 集成 Apollo 配置中心实战
  • 灰度·未尽态数学:从无穷时空到生命逻辑的统一框架
  • 从砷超标133倍事件看水质检测与数据处理全流程
  • DevOps面试指南:如何从背题到讲透原理?
  • 专升本计算机基础:二、八、十六进制互转方法详解
  • Cube生态实践:从架构到部署,语义层统一指标的踩坑与取舍
  • Vibe Coding 上下文管理:Context 来源、超限排查与工程化实践
  • 从词向量到Transformer再到AI大模型:原理与PyTorch实战
  • Cloudflare Kitesurf:AI Agent浏览器的工作原理与实战指南
  • 游戏公会招募解析:50级门槛与“等级接近我带你”的真实含义
  • Python实现人生模拟器:属性建模与事件驱动机制详解