戰(zhàn):13天從零開(kāi)發(fā)致敬QQ華夏的掛機(jī)網(wǎng)頁(yè)游戲)
這次我們來(lái)看的不是一個(gè)新模型也不是一個(gè)開(kāi)源框架而是一個(gè)用 vibe coding 方式完成的紀(jì)念項(xiàng)目13 天從零搓了一個(gè)致敬經(jīng)典網(wǎng)游《QQ華夏》的“掛機(jī)版”網(wǎng)頁(yè) Demo。先說(shuō)清楚“掛機(jī)版”三個(gè)字的邊界本文講的是放置類玩法的本地單機(jī)小游戲角色自動(dòng)打怪、自動(dòng)升級(jí)、自動(dòng)掉裝備數(shù)據(jù)存本地和真實(shí)網(wǎng)游服務(wù)器沒(méi)有任何連接。它不是外掛不讀取真實(shí)游戲客戶端也不碰任何在線游戲賬號(hào)。想做這種類型練手的同學(xué)可以放心往下看。項(xiàng)目核心就一個(gè)詞vibe coding。也就是用自然語(yǔ)言向 AI 編程助手描述需求讓 AI 持續(xù)生成、修改、重構(gòu)代碼開(kāi)發(fā)者在旁邊做設(shè)計(jì)、審查、驗(yàn)證。整個(gè)項(xiàng)目不追求工程復(fù)雜度重點(diǎn)是快速把“懷念老網(wǎng)游”的需求變成可運(yùn)行的網(wǎng)頁(yè)應(yīng)用。最終交付是一個(gè)純前端為主的掛機(jī)游戲頁(yè)面配合一套簡(jiǎn)單接口服務(wù)做存檔和日志瀏覽器打開(kāi)就能玩。這個(gè)項(xiàng)目的核心特點(diǎn)可以歸納為幾條開(kāi)發(fā)周期極短、對(duì)話式開(kāi)發(fā)驅(qū)動(dòng)、玩法即代碼、數(shù)據(jù)和配置全部可見(jiàn)、不需要高配顯卡。它對(duì)硬件幾乎沒(méi)有要求普通筆記本就能跑部署方式以本地 Node 服務(wù)和靜態(tài)頁(yè)面為主。下面我會(huì)把整個(gè) vibe coding 工作流拆開(kāi)項(xiàng)目怎么拆、AI 怎么用、代碼怎么組織、上線前要檢查哪些合規(guī)點(diǎn)、踩坑怎么排查。如果你最近關(guān)注 vibe coding 這個(gè)概念想找一個(gè)“非圖像生成”方向的完整案例這篇文章可以直接收藏。我們會(huì)從項(xiàng)目設(shè)計(jì)一路聊到本地啟動(dòng)、功能驗(yàn)證、迭代調(diào)試和常見(jiàn)問(wèn)題內(nèi)容偏實(shí)戰(zhàn)不堆概念。1. 核心能力速覽能力項(xiàng)說(shuō)明項(xiàng)目類型vibe coding 開(kāi)發(fā)的放置類網(wǎng)頁(yè)小游戲 Demo開(kāi)發(fā)方式自然語(yǔ)言對(duì)話驅(qū)動(dòng)AI 編程助手輔助生成與迭代運(yùn)行方式本地靜態(tài)頁(yè)面 輕量 Node/Flask 服務(wù)瀏覽器訪問(wèn)核心玩法自動(dòng)戰(zhàn)斗、自動(dòng)升級(jí)、裝備掉落、背包管理、離線收益數(shù)據(jù)存儲(chǔ)瀏覽器 LocalStorage 或本地 JSON 文件硬件門檻無(wú) GPU 要求普通筆記本即可運(yùn)行啟動(dòng)方式命令行啟動(dòng)本地服務(wù)或直接打開(kāi)靜態(tài)頁(yè)面是否支持 API支持本地接口用于存檔、日志、任務(wù)查詢是否支持批量任務(wù)不支持批量任務(wù)適合單人單頁(yè)交互適合讀者想了解 vibe coding 實(shí)戰(zhàn)流程、做游戲原型、練手全棧開(kāi)發(fā)的同學(xué)注意表里的參數(shù)是通用描述不是某一套固定代碼的規(guī)格。具體功能邊界取決于你給 AI 的提示詞和項(xiàng)目裁剪方式后面會(huì)講怎么控制范圍。2. 適用場(chǎng)景與使用邊界先聊清楚這個(gè)項(xiàng)目適合誰(shuí)不適合誰(shuí)。適合的場(chǎng)景有三類。第一類想在短時(shí)間跑通一個(gè)完整交互應(yīng)用驗(yàn)證“把想法變成產(chǎn)品”的流程vibe coding 是很好的練習(xí)載體。第二類對(duì)老網(wǎng)游有情懷想低成本做一個(gè)致敬玩法的小 Demo而不是去玩真實(shí)服務(wù)器。第三類想把 AI 編程助手用于個(gè)人項(xiàng)目但平時(shí)只寫 CRUD 或腳本想找一個(gè)帶游戲邏輯、帶界面、帶存檔的相對(duì)復(fù)雜例子練手。不適合的場(chǎng)景也要說(shuō)清楚。如果你追求生產(chǎn)級(jí)架構(gòu)、需要多人協(xié)作、要上線上運(yùn)營(yíng)這類項(xiàng)目不能直接當(dāng)成正式產(chǎn)品如果項(xiàng)目要長(zhǎng)期維護(hù)AI 生成的代碼會(huì)出現(xiàn)大量不一致人手重構(gòu)的成本并不低如果涉及真實(shí)網(wǎng)游的自動(dòng)化、數(shù)據(jù)修改、協(xié)議模擬那就不是 vibe coding 的問(wèn)題而是合規(guī)和賬號(hào)安全問(wèn)題本文不討論也不建議做。合規(guī)方面有兩條硬要求。第一素材版權(quán)。致敬老網(wǎng)游不等于搬運(yùn)原版素材角色、地圖、音樂(lè)盡量用原創(chuàng)或可商用資源不要直接把原游戲美術(shù)資源打包進(jìn)個(gè)人項(xiàng)目避免侵權(quán)。第二如果后續(xù)想公開(kāi)發(fā)布演示建議注明非官方、非商業(yè)、僅供學(xué)習(xí)不得讓用戶產(chǎn)生“這是正版游戲模擬器”的誤解。涉及“掛機(jī)”玩法時(shí)還要在項(xiàng)目說(shuō)明里講清楚這是單機(jī) Demo請(qǐng)勿用于破壞任何在線游戲公平性或繞過(guò)反作弊機(jī)制。3. vibe coding 工具鏈與開(kāi)發(fā)準(zhǔn)備vibe coding 不是一個(gè)工具而是開(kāi)發(fā)模式。這里給出我梳理的完整工具鏈和前置準(zhǔn)備。3.1 核心工具組合AI 編程助手主流的選擇包括 Cursor、Windsurf、Copilot 或國(guó)內(nèi)模型的代碼對(duì)話能力。這里不推薦某一個(gè)重點(diǎn)是你用它來(lái)生成代碼、解釋報(bào)錯(cuò)、重構(gòu)邏輯。瀏覽器現(xiàn)代瀏覽器運(yùn)行頁(yè)面調(diào)試推薦 Chrome / Edge。本地服務(wù)Node.js 環(huán)境或者 Python 環(huán)境二選一即可。編輯器如果你用的 AI 助手是基于 VS Code 的需要先裝 VS Code如果是獨(dú)立 IDE按官方文檔準(zhǔn)備。代碼托管本地 Git 足夠遠(yuǎn)程倉(cāng)庫(kù)看個(gè)人習(xí)慣。3.2 環(huán)境檢查清單啟動(dòng)項(xiàng)目前先把基礎(chǔ)環(huán)境檢查一遍# Node.js 版本檢查 node -v npm -v # Python 環(huán)境檢查如果選擇 Flask 做接口 python --version # 如果項(xiàng)目需要 Git 管理 git --version如果你的機(jī)器已經(jīng)有成熟的 Node 或 Python 環(huán)境可以直接跳過(guò)如果都沒(méi)有建議先裝 Node.js LTS 版本。整個(gè)項(xiàng)目對(duì) CUDA、顯卡驅(qū)動(dòng)、深度學(xué)習(xí)框架沒(méi)有依賴不用裝任何 GPU 方案。3.3 如何給 AI 描述需求這是 vibe coding 的核心技能。第一把需求拆成最小可運(yùn)行版本例如“先做一個(gè)網(wǎng)頁(yè)顯示角色等級(jí)、血量、攻擊力每秒自動(dòng)攻擊一只怪”。第二要求 AI 一次只實(shí)現(xiàn)一個(gè)功能閉環(huán)不要一次性讓它生成三五個(gè)模塊。第三給 AI 描述數(shù)據(jù)結(jié)構(gòu)例如“角色對(duì)象包含 name, level, exp, hp, attack, defense”它可以順著數(shù)據(jù)結(jié)構(gòu)生成邏輯。第四遇到問(wèn)題把報(bào)錯(cuò)信息原文復(fù)制給 AI不要自己描述為“頁(yè)面壞了”。下面是一個(gè)最小提示詞模板請(qǐng)用 HTML CSS JavaScript 寫一個(gè)放置掛機(jī)游戲的最小頁(yè)面 1. 頁(yè)面中央顯示角色信息包括名稱、等級(jí)、經(jīng)驗(yàn)值、血量、攻擊力、防御力。 2. 每秒鐘自動(dòng)攻擊一只怪物怪物血量為角色的3倍攻擊力固定。 3. 擊敗怪物后獲得經(jīng)驗(yàn)值和隨機(jī)金幣。 4. 升級(jí)后攻擊力和防御力有成長(zhǎng)。 5. 界面要干凈使用單文件 index.html不要依賴外部庫(kù)。這樣的提示詞足夠具體AI 可以直接生成可運(yùn)行代碼。后續(xù)迭代時(shí)再把新增需求追加為新的提示詞例如“在角色信息下方顯示背包擊敗怪物時(shí) 30% 概率掉落裝備”。4. 項(xiàng)目設(shè)計(jì)與模塊拆解vibe coding 容易失控尤其是一個(gè)項(xiàng)目寫到后面AI 會(huì)不斷疊加功能代碼越來(lái)越亂。所以動(dòng)手前先做模塊設(shè)計(jì)哪怕是很粗的模塊劃分也能讓 AI 生成時(shí)少走彎路。4.1 功能模塊劃分一個(gè)放置掛機(jī) Demo 可以拆成下面這些模塊模塊作用負(fù)責(zé)人角色系統(tǒng)屬性、經(jīng)驗(yàn)、升級(jí)AI 生成 手動(dòng)校驗(yàn)戰(zhàn)斗系統(tǒng)自動(dòng)攻擊、怪物生成、戰(zhàn)斗結(jié)算AI 生成 手動(dòng)校驗(yàn)裝備系統(tǒng)掉落、背包、屬性加成AI 生成 手動(dòng)校驗(yàn)存檔系統(tǒng)本地保存、讀取、重置AI 生成 手動(dòng)校驗(yàn)前端界面頁(yè)面布局、數(shù)據(jù)展示、按鈕交互AI 生成 手動(dòng)調(diào)整樣式日志系統(tǒng)戰(zhàn)斗日志、掉落日志AI 生成 手動(dòng)校驗(yàn)4.2 數(shù)據(jù)結(jié)構(gòu)設(shè)計(jì)在給 AI 寫提示詞之前先把核心數(shù)據(jù)定義好。這樣每個(gè)模塊生成時(shí)AI 會(huì)沿用同一套結(jié)構(gòu)避免變量名來(lái)回變。我這里提供一套示例// 角色數(shù)據(jù)模型 const player { name: 懷念者, level: 1, exp: 0, expToNext: 100, hp: 100, maxHp: 100, attack: 10, defense: 3 }; // 怪物數(shù)據(jù)模型 const monster { name: 試煉獸, hp: 30, maxHp: 30, attack: 5, rewardExp: 10, rewardGold: 5 }; // 背包數(shù)據(jù) const backpack { items: [], capacity: 20 };這套數(shù)據(jù)模型足夠支持早期版本。后續(xù)要加離線收益就再擴(kuò)展一個(gè)離線收益字段例如offlineSeconds和offlineRewardMultiplier。4.3 玩法閉環(huán)設(shè)計(jì)放置游戲的核心是“閉環(huán)”角色自動(dòng)打怪 → 獲得經(jīng)驗(yàn)金幣 → 升級(jí)變強(qiáng) → 打更強(qiáng)的怪。把這個(gè)閉環(huán)寫清楚AI 生成時(shí)就不會(huì)出現(xiàn)邏輯斷裂。我建議在項(xiàng)目根目錄放一個(gè)README.md把玩法規(guī)格寫清楚AI 編程助手在理解需求時(shí)可以直接讀取這個(gè)文件比每次對(duì)話里解釋更高效。README 內(nèi)容可以參考# HometownAFK暫定名 一個(gè)致敬經(jīng)典 MMORPG 風(fēng)格的放置掛機(jī)網(wǎng)頁(yè) Demo。 玩法閉環(huán) 1. 角色自動(dòng)攻擊場(chǎng)景中的怪物戰(zhàn)斗間隔為 1 秒。 2. 擊殺怪物后獲得經(jīng)驗(yàn)值和金幣。 3. 經(jīng)驗(yàn)值滿后角色升級(jí)攻擊力、防御力、最大血量提升。 4. 怪物擊殺時(shí)有 20% 概率掉落裝備裝備可裝備到角色身上。 5. 裝備影響角色屬性屬性面板實(shí)時(shí)更新。 技術(shù)說(shuō)明 - 前端HTML CSS JavaScript使用一個(gè)單頁(yè)應(yīng)用。 - 存檔使用 localStorage。 - 離線收益暫不做后續(xù)迭代。這份 README 是整個(gè) vibe coding 項(xiàng)目的“需求錨點(diǎn)”每次 AI 跑偏就把 README 丟回去讓它糾正。5. 本地部署與啟動(dòng)方式這個(gè) Demo 啟動(dòng)方式非常簡(jiǎn)單本質(zhì)是兩類文件靜態(tài)頁(yè)面和可選的后端服務(wù)。5.1 純靜態(tài)頁(yè)面啟動(dòng)如果項(xiàng)目只包含index.html、style.css、app.js可以直接雙擊index.html打開(kāi)。不過(guò)這樣做有一個(gè)缺點(diǎn)瀏覽器讀寫 localStorage 沒(méi)問(wèn)題但如果后續(xù)要加日志導(dǎo)出、接口服務(wù)還是會(huì)有限制。更穩(wěn)妥的方式是用本地靜態(tài)服務(wù)器。# 進(jìn)入項(xiàng)目目錄 cd hometown-afk # 用 npx 啟動(dòng)靜態(tài)服務(wù)器端口可改 npx serve . -l 3000啟動(dòng)后訪問(wèn)http://localhost:3000在界面上能看到角色信息面板每秒有戰(zhàn)斗日志輸出說(shuō)明游戲循環(huán)已經(jīng)跑起來(lái)了。5.2 Node 服務(wù)啟動(dòng)如果項(xiàng)目包含存檔接口和日志接口可以用一個(gè)簡(jiǎn)單的 Express 服務(wù)。這里給出一個(gè)通用模板實(shí)際端口和路由需要按你自己的項(xiàng)目調(diào)整// server.js // 這是一個(gè)最小可運(yùn)行的本地服務(wù)示例 const express require(express); const app express(); const PORT 3001; app.use(express.json()); // 存檔接口 app.post(/api/save, (req, res) { const saveData req.body; // 項(xiàng)目里可將數(shù)據(jù)寫入 JSON 文件或內(nèi)存 console.log(保存存檔, saveData); res.json({ code: 0, message: saved }); }); // 讀取存檔接口 app.get(/api/load, (req, res) { res.json({ code: 0, data: null }); }); // 日志接口 app.post(/api/log, (req, res) { const log req.body; console.log(收到日志, log); res.json({ code: 0 }); }); app.listen(PORT, () { console.log(服務(wù)已啟動(dòng)http://localhost:${PORT}); });啟動(dòng)命令npm init -y npm install express node server.js這樣頁(yè)面前端和接口服務(wù)就打通了。前端代碼里用fetch(/api/save)調(diào)用即可開(kāi)發(fā)階段建議打開(kāi)瀏覽器控制臺(tái)查看網(wǎng)絡(luò)請(qǐng)求狀態(tài)。5.3 Flask 服務(wù)啟動(dòng)如果你更熟悉 Python也可以用 Flask 做同樣的接口。這里給一個(gè)通用模板from flask import Flask, request, jsonify app Flask(__name__) app.route(/api/save, methods[POST]) def save(): data request.get_json() print(保存存檔, data) return jsonify({code: 0, message: saved}) app.route(/api/load, methods[GET]) def load(): return jsonify({code: 0, data: None}) app.route(/api/log, methods[POST]) def log(): data request.get_json() print(收到日志, data) return jsonify({code: 0}) if __name__ __main__: app.run(host127.0.0.1, port5000, debugTrue)啟動(dòng)命令pip install flask python app.py注意這里只是通用模板不是某個(gè)具體項(xiàng)目的真實(shí)接口代碼實(shí)際字段名要以你自己的項(xiàng)目數(shù)據(jù)結(jié)構(gòu)為準(zhǔn)。如果你不需要接口直接跑靜態(tài)頁(yè)面也完全沒(méi)問(wèn)題。6. 功能測(cè)試與效果驗(yàn)證vibe coding 最容易出現(xiàn)的問(wèn)題是“頁(yè)面能開(kāi)但邏輯不對(duì)”。所以每完成一個(gè)功能模塊就要做一輪功能驗(yàn)證。下面列出核心測(cè)試用例。6.1 自動(dòng)戰(zhàn)斗測(cè)試測(cè)試目的確認(rèn)戰(zhàn)斗循環(huán)是否能每秒觸發(fā)一次并正確結(jié)算。輸入打開(kāi)頁(yè)面等待 5 到 10 秒。操作打開(kāi)瀏覽器開(kāi)發(fā)者工具F12切換到 Console 面板。觀察是否有monster defeated或戰(zhàn)斗日志輸出。查看角色經(jīng)驗(yàn)值是否隨時(shí)間增加。預(yù)期結(jié)果角色經(jīng)驗(yàn)值在 5 秒內(nèi)至少增加一次Console 沒(méi)有報(bào)錯(cuò)。判斷標(biāo)準(zhǔn)戰(zhàn)斗日志穩(wěn)定輸出經(jīng)驗(yàn)值持續(xù)增長(zhǎng)。失敗排查Console 報(bào)錯(cuò)player is not defined說(shuō)明變量作用域有問(wèn)題提示 AI 把 player 改為全局對(duì)象或 window 上下文。沒(méi)有日志輸出說(shuō)明setInterval沒(méi)有啟動(dòng)檢查定時(shí)器代碼是否在頁(yè)面加載后執(zhí)行。6.2 升級(jí)屬性成長(zhǎng)測(cè)試測(cè)試目的確認(rèn)經(jīng)驗(yàn)值滿后能觸發(fā)升級(jí)并重新計(jì)算攻擊力、防御力、最大血量。輸入手動(dòng)調(diào)整角色經(jīng)驗(yàn)值或降低升級(jí)所需經(jīng)驗(yàn)。操作在 Console 執(zhí)行player.exp 90; player.expToNext 100;。等待戰(zhàn)斗結(jié)算讓經(jīng)驗(yàn)值超過(guò)升級(jí)閾值。預(yù)期結(jié)果角色等級(jí)從 1 升到 2攻擊力、防御力按成長(zhǎng)公式增加。判斷標(biāo)準(zhǔn)升級(jí)日志出現(xiàn)屬性面板數(shù)值同步變化。失敗排查升級(jí)后屬性沒(méi)變說(shuō)明成長(zhǎng)公式?jīng)]有放到levelUp函數(shù)里檢查升級(jí)邏輯。經(jīng)驗(yàn)值超過(guò)閾值但沒(méi)升級(jí)說(shuō)明觸發(fā)條件寫成了exp expToNext應(yīng)改為exp expToNext。6.3 裝備掉落與背包測(cè)試測(cè)試目的確認(rèn)擊殺怪物后有概率掉落裝備裝備進(jìn)入背包并可以裝備。輸入將掉落概率臨時(shí)調(diào)高到 0.9。操作在源碼中把dropRate 0.2臨時(shí)改為dropRate 0.9。等待若干次戰(zhàn)斗觀察背包容器是否出現(xiàn)新裝備。點(diǎn)擊裝備確認(rèn)角色屬性面板變化。預(yù)期結(jié)果多次戰(zhàn)斗后至少掉落一件裝備點(diǎn)擊裝備后屬性生效。判斷標(biāo)準(zhǔn)背包有新增 item裝備后攻擊力或防御力發(fā)生變化。失敗排查有掉落日志但沒(méi)有出現(xiàn)在背包說(shuō)明掉落寫入邏輯和背包渲染邏輯斷開(kāi)檢查backpack.items.push()和renderBackpack()調(diào)用關(guān)系。點(diǎn)擊裝備沒(méi)反應(yīng)可能是事件綁定落在了動(dòng)態(tài)生成的 DOM 上改用事件委托。6.4 存檔讀取測(cè)試測(cè)試目的確認(rèn)關(guān)閉瀏覽器后重新打開(kāi)角色數(shù)據(jù)能恢復(fù)。輸入先讓角色升級(jí)到 2 級(jí)等待幾秒再關(guān)閉頁(yè)面。操作Console 執(zhí)行saveGame()。確認(rèn) localStorage 有saveData字段。刷新頁(yè)面觀察角色等級(jí)和背包是否恢復(fù)。預(yù)期結(jié)果刷新后角色等級(jí)、經(jīng)驗(yàn)、背包物品不變。判斷標(biāo)準(zhǔn)localStorage 中有存檔數(shù)據(jù)頁(yè)面加載時(shí)讀取并重建角色狀態(tài)。失敗排查刷新后數(shù)據(jù)丟失說(shuō)明沒(méi)有在window.onload里調(diào)用loadGame()。localStorage 寫入時(shí)報(bào)錯(cuò)可能是數(shù)據(jù)量超過(guò)限制或?yàn)g覽器禁用了本地存儲(chǔ)。6.5 長(zhǎng)掛穩(wěn)定性測(cè)試測(cè)試目的確認(rèn)長(zhǎng)時(shí)間運(yùn)行沒(méi)有內(nèi)存泄漏或卡頓。輸入保持頁(yè)面運(yùn)行 1 小時(shí)以上或至少 30 分鐘。操作打開(kāi) Chrome 任務(wù)管理器Shift Esc。觀察頁(yè)面內(nèi)存占用是否有持續(xù)增長(zhǎng)。觀察 Console 是否出現(xiàn)頻繁報(bào)錯(cuò)。預(yù)期結(jié)果頁(yè)面內(nèi)存穩(wěn)定在合理范圍Console 沒(méi)有錯(cuò)誤刷屏。判斷標(biāo)準(zhǔn)運(yùn)行一段時(shí)間后界面仍能每秒正常刷新戰(zhàn)斗日志沒(méi)有中斷。失敗排查內(nèi)存持續(xù)增長(zhǎng)通常是戰(zhàn)斗日志沒(méi)做截?cái)嘈枰拗迫罩緱l數(shù)例如只保留最近 50 條。頁(yè)面越來(lái)越卡可能是 DOM 節(jié)點(diǎn)累積檢查渲染函數(shù)是否每次做全量更新改成增量更新。7. vibe coding 迭代與調(diào)試技巧vibe coding 和傳統(tǒng)開(kāi)發(fā)的差異在哪里就是“需求變更由對(duì)話驅(qū)動(dòng)代碼由 AI 生成人類做驗(yàn)收和維護(hù)上下文”。所以迭代調(diào)試的核心是讓 AI 始終掌握全局上下文。7.1 保持對(duì)話上下文不要每加一個(gè)功能就新開(kāi)一個(gè)對(duì)話。如果 AI 編程助手支持會(huì)話持久化盡量在同一會(huì)話里持續(xù)描述需求。這樣 AI 記得之前的代碼約定不會(huì)重復(fù)生成同名函數(shù)或改變數(shù)據(jù)結(jié)構(gòu)。7.2 用報(bào)錯(cuò)信息喂 AI遇到 bug最有效的做法是復(fù)制完整報(bào)錯(cuò)堆棧。比如Uncaught TypeError: Cannot read properties of undefined (reading hp) at fightLoop (game.js:45:20)把這段直接發(fā)給 AI并附加當(dāng)前代碼片段AI 通常能定位到是monster.hp依賴了未初始化的monster對(duì)象然后給出修復(fù)建議。7.3 小步提交隨時(shí)回滾vibe coding 項(xiàng)目會(huì)經(jīng)常出現(xiàn)“AI 改了 A 功能結(jié)果 B 功能崩了”。為了能快速回退推薦每完成一個(gè)完整功能就做一次 Git 提交git add . git commit -m feat: 完成自動(dòng)戰(zhàn)斗閉環(huán)如果 AI 改亂了直接回滾到上一個(gè)可用版本git reset --hard HEAD注意git reset --hard HEAD會(huì)丟棄當(dāng)前所有未提交修改執(zhí)行前確認(rèn)沒(méi)有需要保留的代碼。7.4 限制單次改動(dòng)范圍給 AI 的提示詞里面盡量用“在現(xiàn)有代碼基礎(chǔ)上增加……”而不是“重構(gòu)整個(gè)項(xiàng)目”。比如“在現(xiàn)有 game.js 基礎(chǔ)上增加一個(gè)離線收益函數(shù)讀取 saveData.lastSaveTime 和當(dāng)前時(shí)間差按分鐘計(jì)算獎(jiǎng)勵(lì)經(jīng)驗(yàn)?!边@樣 AI 知道是增量修改不會(huì)推倒重來(lái)。8. 資源占用與性能觀察這個(gè)項(xiàng)目屬于輕量網(wǎng)頁(yè)應(yīng)用資源占用不高但仍有兩個(gè)觀察點(diǎn)瀏覽器 CPU 占用和本地服務(wù)的進(jìn)程資源。8.1 瀏覽器資源占用放置游戲每秒執(zhí)行一次戰(zhàn)斗循環(huán)正常情況下 CPU 占用很低。如果打開(kāi)頁(yè)面后風(fēng)扇狂轉(zhuǎn)、CPU 占用超過(guò) 30%大概率是渲染寫得太粗。常見(jiàn)問(wèn)題包括每秒全量重繪整個(gè) DOM、大量 console.log、無(wú)限循環(huán)。觀察方法打開(kāi)開(kāi)發(fā)者工具 Performance 面板。點(diǎn)擊 Record記錄 10 秒運(yùn)行情況。查看 long task 和 JS 執(zhí)行耗時(shí)。如果確實(shí)存在渲染瓶頸優(yōu)先讓 AI 做一個(gè)優(yōu)化將戰(zhàn)斗日志限制為最近 30 條角色面板和背包面板的數(shù)據(jù)更新按模塊拆開(kāi)而不是每次全部重繪。8.2 本地服務(wù)資源占用啟動(dòng) Node 或 Flask 服務(wù)后可以用任務(wù)管理器或命令行查看進(jìn)程占用。# Linux / macOS ps aux | grep node # Windows tasklist | findstr node如果發(fā)現(xiàn)多個(gè) node 進(jìn)程殘留通常是開(kāi)發(fā)時(shí)反復(fù)啟停服務(wù)導(dǎo)致建議全部結(jié)束后重新啟動(dòng)pkill node # 或者 Windows 下直接結(jié)束相關(guān)進(jìn)程8.3 端口沖突處理服務(wù)啟動(dòng)失敗最常見(jiàn)的報(bào)錯(cuò)是port 3001 is already in use。處理方式# 查看端口占用進(jìn)程 lsof -i :3001 # 殺掉占用進(jìn)程PID 換成實(shí)際輸出 kill -9 PID也可以直接換一個(gè)端口啟動(dòng)避免沖突。開(kāi)發(fā)時(shí)建議把端口寫在配置項(xiàng)里比如.env文件或config.js這樣反復(fù)調(diào)整方便。9. 常見(jiàn)問(wèn)題與排查方法問(wèn)題現(xiàn)象可能原因排查方式解決方案頁(yè)面打開(kāi)是白屏JS 報(bào)錯(cuò)導(dǎo)致未渲染打開(kāi) Console 查看報(bào)錯(cuò)把完整報(bào)錯(cuò)喂給 AI定位代碼位置并修復(fù)角色不自動(dòng)戰(zhàn)斗setInterval 未啟動(dòng)或循環(huán)中斷檢查 Console 是否有 error檢查 fightLoop 函數(shù)是否定義在 window.onload 中初始化并啟動(dòng) fightLoop經(jīng)驗(yàn)值不增長(zhǎng)擊殺判定邏輯錯(cuò)誤在 Console 手動(dòng)調(diào)用 monster.takeDamage檢查戰(zhàn)斗結(jié)算條件確認(rèn)使用 而不是 掉落裝備但背包不顯示渲染函數(shù)未在數(shù)據(jù)變化后調(diào)用Console 檢查背包數(shù)組是否已 push在 push 后調(diào)用 renderBackpack()刷新后存檔丟失未調(diào)用 loadGame檢查 localStorage 是否有數(shù)據(jù)在頁(yè)面啟動(dòng)時(shí)加載存檔服務(wù)端口被占用其他進(jìn)程占用端口使用 lsof / netstat 查看端口結(jié)束占用進(jìn)程或換端口啟動(dòng)AI 改完功能后其他功能崩了沒(méi)有版本回滾查看 Git 提交記錄git reset 回滾到最近可用版本長(zhǎng)時(shí)間運(yùn)行頁(yè)面卡頓DOM 節(jié)點(diǎn)累積或日志過(guò)多Performance 面板分析限制日志條數(shù)優(yōu)化渲染頻率接口返回 404路由寫錯(cuò)或服務(wù)未重啟檢查路由定義訪問(wèn) /api/xxx修改路由后重啟服務(wù)瀏覽器提示存儲(chǔ)空間不足localStorage 存了太多數(shù)據(jù)檢查存檔數(shù)據(jù)大小清理舊日志壓縮存檔字段這套排查思路也適用于任何 vibe coding 生成的前端小應(yīng)用核心就一句話先看控制臺(tái)報(bào)錯(cuò)再定位數(shù)據(jù)類型和渲染順序最后讓 AI 針對(duì)局部代碼做修復(fù)。10. 最佳實(shí)踐與使用建議從 13 天的開(kāi)發(fā)過(guò)程里我總結(jié)了幾條對(duì) vibe coding 項(xiàng)目最實(shí)用的建議。第一項(xiàng)目起步時(shí)不要貪功能。第一天的工作目標(biāo)就是“角色面板出現(xiàn)并自動(dòng)攻擊”只要這個(gè)閉環(huán)跑通后續(xù)所有功能都是在上面疊加。如果一開(kāi)始就把裝備、副本、技能、商店全部寫進(jìn)提示詞AI 生成的代碼大概率會(huì)在第 3 個(gè)功能開(kāi)始互相干擾。第二用 README 和結(jié)構(gòu)化數(shù)據(jù)模型作為團(tuán)隊(duì)的“公共知識(shí)庫(kù)”。這里的“團(tuán)隊(duì)”就是你和 AI。數(shù)據(jù)結(jié)構(gòu)、玩法規(guī)格、技術(shù)棧寫清楚之后AI 每次修改代碼都會(huì)遵循這些約定不會(huì)產(chǎn)生第二個(gè)變量命名體系。第三設(shè)計(jì)一個(gè)“驗(yàn)收腳本”。每完成一輪功能手動(dòng)跑一遍測(cè)試并在 README 里記錄結(jié)果例如自動(dòng)戰(zhàn)斗通過(guò)升級(jí)成長(zhǎng)通過(guò)背包系統(tǒng)通過(guò)存檔系統(tǒng)通過(guò)這樣每次修改后可以快速回歸直接看之前的記錄再點(diǎn)一遍能省很多時(shí)間。第四注意 AI 生成內(nèi)容的版權(quán)和許可證。vibe coding 出來(lái)的代碼可能混用了開(kāi)源庫(kù)和 AI 訓(xùn)練語(yǔ)料中的代碼模式如果項(xiàng)目要公開(kāi)發(fā)布或商用建議檢查這些依賴項(xiàng)的許可證并把 AI 生成代碼納入常規(guī)代碼審查。第五公開(kāi)分享前做好合規(guī)檢查。如果項(xiàng)目名為“QQ華夏掛機(jī)版”建議在說(shuō)明中明確注明“非官方、非商業(yè)、致敬向”并且不要在項(xiàng)目里使用原游戲的商業(yè)美術(shù)資源和音效素材。第六不要迷信 vibe coding 能替代編程能力。它能顯著降低從 0 到 1 的啟動(dòng)成本但到了性能優(yōu)化、模塊重構(gòu)、安全處理這些環(huán)節(jié)你需要具備基本的代碼閱讀能力和系統(tǒng)思維。把 AI 當(dāng)成一個(gè)“寫得很慢但不能理解的實(shí)習(xí)程序員”你作為工程師負(fù)責(zé)指引方向。11. 總結(jié)與下一步這個(gè)項(xiàng)目最值得嘗試的點(diǎn)就是把“我想做一個(gè)小游戲”這件事壓縮到 13 天里完成。vibe coding 的價(jià)值不在于免寫代碼而在于把想法到原型之間的反饋周期壓縮到分鐘級(jí)它能讓你把精力集中在“游戲玩得爽不爽”“界面交互順不順”這些問(wèn)題上而不是被 JavaScript 語(yǔ)法和事件綁定擋住。如果你也要做類似的掛機(jī)游戲 Demo我建議先從第 6 節(jié)的 5 個(gè)測(cè)試用例開(kāi)始。第一個(gè)應(yīng)跑通的永遠(yuǎn)是最小戰(zhàn)斗閉環(huán)它決定整個(gè)項(xiàng)目的骨架最容易踩的坑則是日志不截?cái)嘁l(fā)的內(nèi)存問(wèn)題以及 AI 重構(gòu)時(shí)破壞舊功能導(dǎo)致的連鎖報(bào)錯(cuò)這兩點(diǎn)在開(kāi)發(fā)初期就會(huì)遇到。后續(xù)可以繼續(xù)擴(kuò)展的方向包括離線收益計(jì)算、裝備詞綴隨機(jī)生成、多角色陣容、劇情事件文本生成甚至可以把戰(zhàn)斗數(shù)據(jù)導(dǎo)出成圖表做分析。每一步都可以用 vibe coding 去迭代重要的是保持項(xiàng)目節(jié)奏測(cè)試一個(gè)功能、提交一個(gè)版本、再進(jìn)入下一個(gè)功能。如果你最近也在用 AI 編程助手做自己的小項(xiàng)目建議把這次的項(xiàng)目記錄成一份開(kāi)發(fā)日志里面有需求變更、Bug 復(fù)現(xiàn)、AI 生成代碼的修改記錄。這些材料比最終成果本身更能體現(xiàn) vibe coding 的真實(shí)工作方式。