用GPT-6.1协作开发一个红警Like RTS游戏:大模型赋能前端游戏实践

发布时间:2026/10/6 14:51:47
用GPT-6.1协作开发一个红警Like RTS游戏:大模型赋能前端游戏实践 1. 项目起缘为什么用大模型做游戏1.1 从「红警」到「红警Like」先说清楚我用 GPT 6.1 做的不是 EA 那款《红色警戒》的复刻版而是一个借鉴它核心玩法的「红警Like」即时战略小游戏。经典红警的乐趣在于采矿积累资源、建造基地、生产坦克和士兵、推平对手基地。这套循环放到今天依然有很强的游戏性但完整复刻它的体量非常大单人开发基本不现实。我的目标很明确用最少的代码还原这套循环的骨架。地图做成俯视 2D 网格基地可以造建筑建筑可以出兵士兵和坦克会自己找路、自己索敌、自己开火玩家要做的就是把资源管好、把兵造出来、把阵型拉好。至于阵营故事、兵种克制表、战役关卡全部砍掉——不是偷懒而是为了在可控的时间内把能玩这件事做实。这正是我觉得 GPT 6.1 这类大模型最适合的切入点一个边界清晰、规则明确、验证成本低的游戏项目。1.2 为什么选浏览器技术栈技术选型我几乎没有犹豫直接定了浏览器端纯前端方案核心原因有三个。第一免安装、免环境。任何有浏览器的设备打开网页就能玩对开源项目来说这降低了所有人体验的门槛。别人不用拉代码、不用装引擎点开线上 Demo 就能试玩。第二和 GPT 6.1 协作的效率高。现代浏览器里 Canvas 2D 的性能足够支撑上千个单位绘制而 JavaScript 生态里现成的算法库、寻路库、状态机库非常多模型对这些公开知识的熟悉程度远高于小众引擎。让它写出来的代码我审查起来也快。第三开源的传播成本低。仓库里一份 HTML、一份 JS 就能跑连构建工具都可以省掉这非常符合开源项目的分享属性。最终我采用了 Vite TypeScript Canvas 2D 的结构。为什么不直接用 PixiJS 这类渲染引擎因为项目的单位数量预计在几百个量级Canvas 2D 加简单的裁剪优化完全够用少一层依赖就少一层维护成本。这个判断后来在实际试玩中得到了验证。1.3 GPT 6.1 在项目里的定位再说 GPT 6.1 到底扮演什么角色。我的体感是它更像一个「24 小时在线、基础知识极其扎实、但需要你严格验收的结对程序员」。在这个项目里我用它做了四类事情生成骨架代码比如寻路、建造队列、单位状态机这类模式成熟的模块描述清楚需求后它能生成可运行的初版。解疑答惑遇到 Canvas 绘制顺序问题、requestAnimationFrame 掉帧问题直接贴代码问它回答的准确率相当高。批量重构比如把散落在各处的单位逻辑收敛到一个状态机里这类机械但费时的活儿交给它很省心。code review让它对照我列出的功能清单检查有没有遗漏的边界情况虽然不能全信但确实能帮我发现一些盲区。但这不代表它能独立写出整个游戏。真正让项目能玩的是后面每一步的验收、调试和设计权衡。这个项目最大的收获不是用 AI 写了个游戏而是摸索出了一套人和大模型分工协作的方式。后面第三章我会把完整的实操过程展开讲。2. 整体架构与核心系统拆解2.1 项目目录与模块划分项目整体规模控制在约 4000 行 TypeScript没有用重型框架核心逻辑全部自己实现。目录结构是这样的rts-playground/ ├── index.html ├── src/ │ ├── main.ts // 入口启动游戏主循环 │ ├── config.ts // 所有数值配置费用、血量、速度等 │ ├── map.ts // 地图、资源点、网格 │ ├── pathfinding.ts // A* 寻路 │ ├── unit.ts // 单位实体与状态机 │ ├── building.ts // 建筑实体 │ ├── ai.ts // 对手 AI │ ├── render.ts // Canvas 渲染 │ ├── input.ts // 鼠标框选、右键移动、指令发送 │ └── ui.ts // 建造面板、血量条、小地图 └── README.md这个划分是 GPT 6.1 建议的我 review 时调整了两处把配置单独抽出来因为游戏平衡性的调整实在太频繁集中修改数值比在业务逻辑里到处找要高效得多把输入单独拆出来因为鼠标交互的状态空闲、框选、正在下达移动指令本身就很有意思独立成模块后不容易和游戏逻辑纠缠。实际开发时我强烈建议任何人做游戏原型都先把 config 抽出来。红警Like 游戏的乐趣本质是数值博弈矿车采一次矿给 25 块钱动员兵造价 50坦克造价 200这个你出多少兵我能出多少兵的换算关系决定了一切。后来我在调平衡性时90% 的时间都在改 config.ts 里的数字基本不动逻辑代码。2.2 地图与格子系统地图设计成 64×64 的网格每个格子 16 像素。格子的作用有三个限制建筑摆放、做地形阻挡、给寻路提供基础数据。这里有一个很多新手容易忽略的点RTS 的地图不能只做视觉层必须做数据层。我用了一个二维数组Grid来存储每个格子的状态0 表示可通行1 表示障碍物岩石2 表示矿区。渲染时根据数组内容画颜色逻辑判断时也直接查数组两边完全一致。如果只画图片而没有数据层后面做寻路和单位碰撞时会处处碰壁。矿区的设计是全局游戏的经济命脉。每片矿区有若干个矿点矿车开到矿点附近会自动减速并执行采矿动画每隔一段时间给玩家增加资金。矿采完之后矿点会进入一段较长的枯竭期促使玩家去开辟新矿区。这套机制完全脱胎于经典 RTS 的资源循环风险决策、地图控制、经济运营全都在里面。2.3 单位行为与寻路A*单位行为我用了一个非常简单的状态机空闲、移动中、攻击中、采集。每个状态有进入条件、每帧处理和退出条件。这个状态机的代码结构长这样type UnitState idle | moving | attacking | collecting; class Unit { state: UnitState idle; target: Point | null null; enemy: Unit | null null; update(dt: number) { switch (this.state) { case idle: this.findEnemy(); break; case moving: this.moveTowards(this.target!); this.checkArrived(); break; case attacking: this.attackCycle(dt); break; case collecting: this.collectCycle(dt); break; } } }寻路部分用的是 A*。A* 本身是教科书级算法但实际用在游戏里有两个坑。第一个坑是格子地图上的路径平滑。A* 找出来的路径是一格一格的折线单位走起来会显得非常僵硬。我的解决方法是加一个简单的路径后处理如果路径上两个非相邻节点之间没有障碍物就把中间的节点全部删掉。一句话实现但单位走起来的观感立刻顺滑很多。第二个坑是大量单位同时寻路的性能。在游戏里选中 30 个坦克右键点到地图另一端如果给每个坦克都跑一次 A*虽然 64×64 的地图不算大但配合每帧实时更新依然会有明显的掉帧。这里我用的是最朴素的方案相同起点和终点的单位共享路径只在接近目标或者遇到障碍变化时重新寻路。后来实测 200 个单位同时移动时帧率依然稳定在 60 帧左右。2.4 战斗系统与投射物战斗系统我刻意保持简单单位发现射程内敌人后停下来开火投射物以直线飞向目标命中后造成固定伤害。开火有冷却时间投射物有飞行速度。这套逻辑不复杂但要让手感舒服关键参数是命中率、开火前摇和投射物速度。打几局之后会发现一个很典型的 RTS 问题大量单位集火同一个目标时溢出伤害巨大。30 辆坦克打一个士兵绝大多数炮弹浪费了。我参考了 RTS 通用的做法同组单位自动分散目标根据单位的 ID 对敌人列表做偏移取模让伤害尽量均匀分布const targetIndex this.unitId % enemies.length; const target enemies[targetIndex];这一行代码就解决了一队坦克被敌方一个动员兵拖住半天的尴尬局面。每次写到这里我都想感慨很多游戏手感问题不是大系统的问题就是这种小细节的累积。投射物的实现还有另一个细节它在飞行过程中是纯逻辑对象不参与单位状态机但如果发射者在投射物落地前就死了投射物依然要飞完并造成伤害。这就带来了一个有趣的战术空间坦克远程齐射后可以马上撤退炮弹仍然会命中目标嫖对方血量。红警玩家对这种操作应该很熟悉。2.5 AI 对手与难度控制既然标题说居然真能玩那一定得有对手。AI 的设计我走了渐进路线从一开始的只会发呆到后面能主动进攻中间经历了三个迭代。第一版 AI 只会被动防御自己有资金就造兵造出来的兵全部蹲家里。玩家只要攒够一波坦克过去就能赢毫无挑战性。第二版 AI 加了一个简单的策略当兵力数量超过玩家一定比例时全军出击。这个设计让 AI 有了最基本的进攻性但依然很蠢因为它不会补兵一波打完之后就再无还手之力。第三版 AI 终于像样了每帧检查自己的资金低于某个阈值时把兵营的生产队列排满每隔一段时间评估一次兵力对比根据兵力优势主动发起进攻进攻时不是无脑冲而是会在兵力达到阈值后等待几秒钟集合再一起走。为了让不同玩家都能找到适合自己的难度我还把进攻阈值做成了配置项。低难度下 AI 的进攻阈值是玩家的两倍兵力才出击高难度下只要兵力均势就压过来。AI 的实现理念我其实是从早期游戏设计书里学到的AI 不需要真的聪明只需要看起来有意图。玩家感知到的智能更多来自于有规律的行为模式和合理的反应速度而不是背后复杂的决策树。现实也是这么运作的这部分后面还有细节。3. 实操过程GPT 6.1 与人协作写游戏3.1 提示词怎么给这可能是读者最关心的部分。GPT 6.1 确实能生成代码但能生成和能生成能用的代码之间隔着一条巨大的鸿沟。我总结出一条核心经验提示词要像需求文档但不能像论文。每次让它干活我都会刻意描述输入是什么、输出是什么、边界情况没法接受的而不是丢一句帮我写个寻路。举个具体例子。刚开始我只需要地图上两个点之间的路径但我不希望单位贴脸走格子线所以我给它的提示词长这样在一个 64x64 的网格地图上0 表示平地1 表示障碍物。请实现一个 A* 寻路函数输入起点 (startX, startY) 和终点 (endX, endY)返回一组经过的节点坐标数组。要求如果终点不可达返回空数组不要包含起点自身障碍物 4 连通上下左右不允许斜穿墙角。请用 TypeScript 实现并导出类型声明。这个提示词包含五个要素数据结构、函数签名、返回格式、边界情况、语言约束。GPT 6.1 生成的初版基本能跑只有一个问题它默认允许了 8 连通。斜穿墙角会让单位在一个拐角处穿墙半格我的单位是坦克这观感我不能接受。后来我在提示词里加了不允许斜穿墙角它立刻调整了邻接判断。另一个重要原则是一次只让它做一件小任务。从前我就是祈祷它一口气生成整个游戏结果代码超过 200 行之后必然出现变量名冲突、逻辑遗漏、函数引用错位。后来我改变策略先把整个项目拆成十几个能独立验证的小任务比如生成 A*、生成巡逻逻辑、生成 UI 血量条每个任务 10-30 分钟之内做完。这样一来每次 wait 它的输出我都能快速验证问题定位也快。3.2 关键代码段落地实录这里挑两个最有代表性的协作片段展示。它们都不是 GPT 6.1 第一次就给对但经过几轮 review 后稳定可用的版本。片段一基于格子地图的 A寻路实现*type Grid number[][]; type Node { x: number; y: number; f: number; g: number; parent: Node | null }; function astar(grid: Grid, start: [number, number], end: [number, number]): [number, number][] { const rows grid.length; const cols grid[0].length; const open: Node[] []; const closed new Setstring(); const key (x: number, y: number) ${x},${y}; const root: Node { x: start[0], y: start[1], g: 0, f: heuristic(start, end), parent: null }; open.push(root); while (open.length 0) { open.sort((a, b) a.f - b.f); const cur open.shift()!; const curKey key(cur.x, cur.y); if (curKey key(end[0], end[1])) { const path: [number, number][] []; let n: Node | null cur; while (n n.parent) { path.push([n.x, n.y]); n n.parent; } return path.reverse(); } closed.add(curKey); for (const [dx, dy] of [[0,1],[0,-1],[1,0],[-1,0]]) { const nx cur.x dx; const ny cur.y dy; if (nx 0 || ny 0 || nx cols || ny rows) continue; if (grid[ny][nx] ! 0 || closed.has(key(nx, ny))) continue; const ng cur.g 1; const nf ng heuristic([nx, ny], end); const existing open.find(n n.x nx n.y ny); if (existing existing.f nf) continue; open.push({ x: nx, y: ny, g: ng, f: nf, parent: cur }); } } return []; } function heuristic(a: [number, number], b: [number, number]): number { return Math.abs(a[0] - b[0]) Math.abs(a[1] - b[1]); }这个版本用的是 Manhattan 距离因为地图不允许斜走。open 列表每帧 sort 显然不是最高效的但 64×64 且共享路径后完全够用。我 review 时加的关键优化是把 closed 从数组改成 Set这个改动让寻路在大地图上快了 3 倍左右。片段二建造队列建造队列是 RTS 基地体验的核心。我是这样让它实现的每种建筑和单位配置了建造时间、费用、前置条件。基地会维护一个 FIFO 队列每帧处理队列首项把建造进度累加完成后自动生成单位或建筑并扣费。这个逻辑本身不复杂但状态管理容易出错尤其是队列里有多个项目时取消其中一个的边界场景GPT 6.1 第一版的写法会串号我 debug 后加了一个独立的队列编号才解决type BuildItem { id: number; type: string; progress: number; totalTime: number }; class BuildQueue { queue: BuildItem[] []; private nextId 1; enqueue(type: string, cost: number, totalTime: number): boolean { if (this.resources cost) return false; this.resources - cost; this.queue.push({ id: this.nextId, type, progress: 0, totalTime }); return true; } update(dt: number) { if (this.queue.length 0) return; const item this.queue[0]; item.progress dt; if (item.progress item.totalTime) { this.spawn(item.type); this.queue.shift(); } } cancel(id: number) { const idx this.queue.findIndex(q q.id id); if (idx 0) { this.queue.splice(idx, 1); // 退钱规则已开始超过一半不退全款防止刷兵 } } }退钱规则这里我故意做了限制如果建造进度超过一半再取消只退款 50%。这个设计后来让我在调平衡性时省了很多力气。如果没有这个规则玩家完全可以无限排队刷退款经济系统就崩了。这是纯粹的 game design 决策GPT 6.1 不会替你想到但它是游戏能玩的必要条件。3.3 反复迭代的验收清单每次 GPT 6.1 生成一段代码我都会跑一套固定验收流程这比直接用要稳妥得多。我的检查清单如下功能验收按需求文档逐条过尤其是边界情况。它生成 A* 时常漏掉斜穿墙角的约束生成建造队列时常漏掉资源不足时不能入队这类问题必须在验收时抓出来。安全验收不能让它生成的代码里出现任何系统命令、不规则的外部网络请求也不能包含任何有敏感联想的内容。我会逐行 review 它生成的代码确保没有任何灰色区域。毕竟我是要开源的代码会被很多人看到安全审查不能省。性能验收跑一遍游戏打开浏览器 Performance 面板如果帧率低于 50就让它做性能剖析并优化。共享路径、减少 map 遍历次数、合并绘制批次这类优化它做得都不错。代码风格验收项目虽然是开源玩票但命名规范、类型声明、注释级别都要一致。杂乱无章的代码会直接影响别人 review 项目的意愿。这些验收迭代平均每段代码要走三轮才稳定。但如果让我一行行全自己写周期会长得多。我粗略估算这个项目的净开发时间大约 60 小时而我自己从零敲到同样程度至少要 120 小时这还不算走弯路。4. 开源发布与项目维护4.1 仓库结构与 README 怎么写做开源最重要的不是把代码 push 上去而是让别人在 5 分钟内看懂你的项目并跑起来。这个项目的 README 我前后改了四版最终结构是项目名与一句话介绍RTS Playground用 TypeScript 实现的即时战略小游戏原型。在线试玩按钮部署到了免费的静态托管平台点开即玩。快速启动命令clone 后npm install npm run dev。玩法说明三句话讲清楚资源、建造、战斗附 Gif 动图。键盘操作与开发快捷键。项目架构图我用文字列表而不是流程图标注每个模块的职责。后续开发计划列了 4 个我正在做或想做但还没做的功能点。这里面我最想说的是动图。一个开源游戏项目如果你让访客第一眼只看到一张静态仓库截图那大多数人都不会点进去读你的代码。但如果你放一张 10 秒的试玩 Gif展示矿车采矿、建造坦克、部队推进三大核心玩法访客几乎立刻就能理解这个项目能干什么。这比任何 README 文字都直观。4.2 开源源码与许可证这次开源我选的是 MIT 许可证。理由很简单这个项目是教学相长性质的我希望更多人修改、分发、甚至拿去制作商业游戏MIT 能最大程度减少法律摩擦。如果你自己准备开源我会建议以下几种选择MIT许可证要求宽松别人可以自由使用修改甚至闭源商用只要保留原版权声明。Apache 2.0相比 MIT 多了专利授权条款和明确的贡献者条款适合项目里涉及复杂依赖的情况。GPL 3.0强制要求基于它修改的项目也必须开源适合想反哺社区、拒绝他人闭源商用的情况。AGPL针对网络服务场景即使你只是部署成网页服务让用户访问代码也必须开源。这个项目是一次纯前端游戏源码不动基础设施也不依赖任何专利技术MIT 是最合适的。如果你不知道选什么默认 MIT 就好先开源再纠结。4.3 二次开发与扩展思路开源之后收到最多的提问是我可以用这个项目做什么。我在 README 里写了三条明确的使用路径第一拿来当 RTS 教学项目。代码量不大模块划分清楚寻路、状态机、资源管理、AI 都是经典范式。很多学游戏开发的人一开始无从下手这个项目提供了一个完整的、能跑的最小闭环。第二换皮做自己的游戏。引擎和核心玩法都已经搭好换一套主题、加几个新单位、改一些数值就能变成完全不同的游戏。比如把军事题材改成农场经营把矿车改成拖拉机把坦克改成收割机把敌人改成杂草和害虫这套资源循环的骨架依然成立。第三做算法实验平台。这个项目天然适合测试寻路算法变体、AI 决策树、群体行为模拟。我有几个朋友就用它来做对比实验比如 A* 和 JPS 在相同地图下的性能差异改一个函数就能出结果。另外补充一个实用经验开源项目的 issue 区和讨论区本身就是最好的需求池。发布后收到的 issue 里有提性能问题的有要求加单位类型的有反馈平衡性怪异的。这些反馈直接决定了第二个迭代版本的方向。5. 常见问题与排查技巧实录5.1 寻路与单位拥堵这是本项目遇到的最典型问题。当玩家框选 30 个坦克同时移动时所有单位都挤向同一个路径节点导致大量单位在墙角原地打转。排查思路如下先在每个单位身上叠加一个局部偏移让它们的目标点不是同一个精确坐标而是一个小范围随机点。这个方法立竿见影单位开始散兵线推进。再优化寻路调用同一帧多个单位目标点相近时结果直接缓存复用。最后给单位增加碰撞半径运动时检测前方是否有其他单位并等待或绕行。这套机制组合下来虽然不完美但在 200 单位规模内表现足够自然。如果你在自己的游戏里也遇到单位打转问题先不要怀疑寻路算法本身大概率是目标点重合和碰撞处理的问题。A* 永远是正确的但它只会按照规则找路单位之间互相挤住属于物理模拟的范畴。5.2 性能坑大量单位同屏卡顿第一次试玩时我同样遇到了性能问题。地图上 300 辆坦克开火帧率直接掉到 20FPS。用 Performance 面板定位后瓶颈在 Canvas 绘制高分辨率贴图时频繁重绘。我的优化顺序是减少 Canvas 的绘图指令数合并在同一个区域的单位用单条指令绘制相邻单位的简化图形小方框代替贴图。关闭过于频繁的重绘距离屏幕超过一定像素的单位不绘制。控制投射物数量对远处集中战斗每 3 个投射物合并为一个淡色弹幕效果视觉上几乎没有区别。最终每帧绘制单位数量从峰值 500 降到 150 左右帧率回到 60。如果你也有类似 Canvas 游戏记住一个原则先想怎么做减法再做优化而不是盲目升级渲染库。5.3 游戏平衡与手感调整游戏能玩和好玩之间最大的坎就是平衡性。我总结了三个要思考的核心问题经济曲线是否平滑如果采矿太慢玩家会长时间无聊如果太快会早早就出兵碾压AI。我最后调成每片矿区 10 个矿点每个矿点采完到枯竭需要 2 分钟同时全图安排了 5 片矿区这就给了玩家不断扩展地图控制权的动机。兵种克制关系是否与成本匹配坦克贵但能抗能打士兵便宜但数量多能攒出规模。如果某个兵种在同成本下优势太明显就会变成无脑出该兵种的局面。AI 的进攻节奏是否合适AI 在玩家兵力优势时缩在家里劣势时才主动出击这样会给玩家一个我打出了优势的错觉。这个错觉至关重要——玩家觉得是自己运营得好就会继续玩下去。每次调整这些数值时我都会改了配置立刻开一局试玩观察 5 分钟内的节奏变化。这是最笨也最有效的方法只有真实对局才能暴露设计问题。5.4 GPT 6.1 生成代码的常见问题自查用大模型生成代码时有几个反复出现的问题值得注意变量作用域错乱它喜欢把临时变量放在全局位置导致多个单位共享同一状态表现为A 单位动了 B 单位也跟着动。review 时优先检查构造函数里所有属性的初始化。性能优化过度它会主动引入缓存、位运算、对象池等高级技巧但用在 64×64 网格上纯属画蛇添足徒增维护难度。可以先让它用最简单的写法实现跑出结果再做性能分析。对浏览器 API 的假设过时它偶尔会生成已经不存在的 API 用法。遇到这种情况直接把报错信息贴回去让它修正不要自己动手搜。安全边界生成代码时它偶尔会引入一些不必要的外部函数我会在合并进主分支前逐行检查凡是有不确定来源的调用一律删掉重写。如果你决定用 GPT 6.1 或同类型工具做自己的项目我的建议是把它当做能力很强但需要你最终负责的协作伙伴永远不要盲信它给的代码能直接上线。你自己对项目的理解、对代码的掌握、对安全边界的审查才是项目能否走完的关键。6. 一些个人体会游戏开源之后我把代码挂在仓库里的那几天最大的感受不是我做出了一个被认可的东西而是我终于弄清楚人和大模型协作的健康边界在哪里。这个项目从头到尾没有使用任何现成游戏引擎所有代码都是 GPT 6.1 生成初版我审核修改后落地的。这个过程让我反复体会到一个道理大模型真正的价值不在于替你做出创意决策而在于帮你把已经想清楚的方案低成本地变成代码。比如用 A* 做寻路是我做的决策生成一个带障碍物避让的 A* 实现是它做的事。设计意图从始至终都在我手里它的产出只是加速了我验证想法的过程。如果你也想用大模型做点自己的项目我能给的最直接建议就是挑一个你有强烈兴趣、边界清晰、可以快速验证的小项目把它拆成十几个独立任务逐个交给模型生成然后像审阅同事代码一样严格验收。你会发现这种工作方式的效率远超想象。最后分享一个小技巧这个项目至今保留着单行开关的调试模式。按下波浪线键可以打开调试面板直接看到所有寻路路径、单位状态和 AI 决策日志。开发时它救了我无数次开源后也成了新贡献者入门的最佳路径。如果你也要做游戏原型尽早把调试可视化做进去这比任何文档都管用。