iT邦幫忙

2026 iThome 鐵人賽

DAY 30
0
Modern Web

《九重燼》Vue3 + PixiJS + Ink.js 視覺小說遊戲開發全紀錄系列 第 30

Day30 AI 改變了我的遊戲開發:30 天打造《九重燼》的總結與未來規劃

  • 分享至 

  • xImage
  •  

30 篇寫到這裡,終於要收尾了。

最後一天,我想回頭看一件事:AI 到底改變了什麼?

答案不是「AI 幫我把遊戲做完」。

AI 把很多原本會拖垮一人開發的工作,變成可以反覆迭代的工作。但它也把另一件事變得更重要:你必須有能力回頭查證。規格、程式碼、測試、文件,少一個都很容易把「看起來合理」誤當成「真的完成」。

這 30 天最後做出了什麼

目前《九重燼》已經不是只有序章和前兩章的 Demo。src/narrative/main.ink 已經接入序章到第八章、Demo 結局、正式結局 dispatcher、六位女主角感情結局,以及番外一到番外九。

以 repo 現況來看,src/narrative 共有:

  • 42 個 .ink
  • 1041 個 VAR 宣告
  • 1010 條選項行
  • 762 個 # choice: 標籤
  • 24 個 # ending: 標籤

這些數字不是為了炫耀。它們只是提醒我:這個專案已經大到不能靠記憶維護了。

如果沒有 main.inkINCLUDE 結構、validate:storyvalidate:assets、20 支測試腳本,以及這一系列文章裡每天回頭查程式碼的習慣,後面一定會開始用印象開發。用印象開發,對互動敘事很危險。因為一條路線斷掉時,通常不是馬上白屏,而是玩家幾小時後才走到一個不存在的門。

技術上,最後收斂成三個邊界

這 30 天裡,我一直在替系統切邊界。做到最後,最穩的不是某個單一技術,而是邊界本身。

第一個邊界是 Ink 和 UI。

Ink 負責劇情、選項、旗標、數值和結局入口。Vue 不把劇情正文寫死在元件裡。當 Ink 送出 # bg# char# cg# vfx# bgm# ui 這些 tag 時,前端才把它們解析成畫面行為。這讓劇本可以繼續擴,UI 也不用知道每一段劇情在講什麼。

第二個邊界是 Vue 和 Pixi。

PixiJS 負責背景、CG、VFX、轉場。角色立繪則是 Vue DOM。這點一開始可能會讓人意外,但後來證明很實際:角色立繪需要跟對話框、RWD、安全區、可及性一起調整,用 DOM 反而比全部丟進 Pixi 更好維護。

第三個邊界是 Pinia 和 inkjs runtime。

src/stores/story.ts 是遊戲狀態中心。UI 和 Pixi 都讀 store,不直接碰 inkjs。Ink 變數不是每改一次就發事件,而是在幾個明確節點透過 _syncVariables() 拉回 Pinia。畫面層再用 Vue 的 watch() 訂閱 store 變化,呼叫 SceneManager 或其他 UI 行為。

《九重燼》沒有真正的 pub/sub 事件匯流排。它靠的是 Pinia state、Vue reactivity 和幾個明確的同步點。這比一開始想像的 Event Bus 樸素,但可追蹤很多。

AI 真正幫上忙的地方

AI 最好用的地方,不是一次產出完美答案,而是幫我加速「草稿變成可驗證版本」。

寫劇情時,它能幫我把企劃文件整理成 Ink 初稿。做文章時,它能幫我把技術過程整理成段落。做資產時,OpenAI 圖片生成讓場景、CG、角色立繪不再完全卡死在素材來源上。這些都是真正的加速。

但前提是我得給它可核對的東西。

如果只有一句「幫我做宮廷文字冒險」,AI 會產出看起來很像遊戲的東西;但如果有 CHOICE_BRANCHES.mdENDING_CONDITIONS.mdINK_SCRIPT_GUIDE.mdAGENTS.md,它才比較可能產出能接進專案的東西。

所以我現在對 AI 協作的看法很務實:它不是替代規格,而是放大規格的效益。規格清楚,它跑得很快;規格模糊,它也會很快,只是快到錯的地方。

幾個真的踩過的坑

這系列不是一路順利。比較有代表性的坑,現在回頭看都很有教育意義。

第一個是自由行動地圖卡死。

# ui:show_map 在真正選項出現前就觸發,地圖面板打開後,對話框的推進被擋住,store.choices 還是空的,地圖卡片就全部變成不可點。這不是 UI 長得醜,而是 Ink 推進時序和面板守衛互相卡住。

第二個是番外 knot 斷鏈。

番外二到番外九曾經有場景結尾寫 -> DONE,沒有跳到下一場,玩家幾十行內就會提前結束。這種問題很可怕,因為檔案後面明明有內容,看起來像完成了;但 runtime 根本走不到。

第三個是 Pixi resolver alias 覆蓋。

不同 bundle 裡可能有同名素材,如果 alias 只用檔名,就會被後載入的檔案覆蓋。後來改成 ${bundleId}:${url},才把跨 bundle 同名資產切開。

第四個是證據存檔消失。

一筆格式不符的證據紀錄,曾經會讓整個 evidenceRecords map 被歸零。修法是逐筆 sanitize,只丟掉壞的那一筆。這件事讓我印象很深,因為它不是「功能沒做」,而是「防護做得太粗」。有時候 bug 就藏在這種看似合理的驗證函式裡。

測試救了很多次

目前 npm run test 串了 20 支 tsx 測試腳本,涵蓋存檔、migration、StoryRuntime、tag parser、command router、結局 resolver、番外解鎖、CH00 到 CH08 分支、證據系統、角色事件和 PixiStage。

這些測試不是完整保證。Day27 已經說過,跨瀏覽器自動化還沒補齊,Playwright 目前只有 Chromium smoke test。但它們已經足夠讓我在大規模改文章、改劇情、改資產流程時,不至於完全靠手感。

互動敘事最怕的是「看起來只是改一行,結果另一條路線死掉」。測試不能消除這件事,但能讓我比較早聽到警報。

PWA、行動版:不要急著背太多平台

Day24 已經把平台邊界講清楚了:目前 Web 是主軸,Vercel 是實際部署平台。

PWA 已經有可安裝雛形。vite.config.ts 裡接了 vite-plugin-pwa,manifest 的 start_url 指向 /play.html,service worker 只 precache JS / CSS app shell,不預先快取整包美術和音訊。這很重要,因為 public/assets 很大,直接做完整離線包不實際。

所以接下來 PWA 的方向,不是立刻宣稱「離線完整遊玩」,而是先把安裝體驗、icon、啟動畫面、更新提示和真機行為測好。

一人開發最容易犯的錯,就是把「以後可以」當成「現在應該」。

接下來最小可行的下一步

真的要進下一輪,我會先做三件事。

第一,補跨瀏覽器測試。Playwright 加 firefoxwebkit project,再補一條手機 viewport 測試。這比一口氣導入大型測試平台實際。

第二,補社群分享預覽。Portal 還沒有 Open Graph、Twitter Card、sitemap.xmlrobots.txt。這件事不難,但很影響公開後的第一眼。

第三,整理玩家回饋入口。正式公開後,最重要的不是我自己覺得哪裡還可以,而是玩家在哪裡卡住、哪個角色被喜歡、哪條路線讓人困惑。鮮花與雞蛋榜是一個輕量情緒入口,但 bug 回報和心得回收還需要更清楚的路徑。

最後一天的真心話

30 天連續寫到這裡,我最大的收穫不是「AI 讓一個人做完遊戲」。更準確地說,是 AI 讓我能更快地把想法推到可檢查的狀態,而我也被迫更認真地建立檢查方法。

這個過程有時候很爽,有時候很狼狽。AI 會幫你寫出一段看起來很完整的說法,然後你打開 repo,發現根本沒有那個模組。它也會在你卡住時給你一個方向,讓你突然把一個本來要拖兩天的問題拆開。

所以我現在不想把 AI 神化,也不想把它貶低成普通工具。它更像一個很快、很有用、但需要被校對的協作者。你給它脈絡,它能跑;你給它幻想,它也會跑。

《九重燼》這 30 天,最後留下來的不是某個單一功能,而是一套工作方法:

  • 先寫規格
  • 再做實作
  • 用測試守住變更
  • 用文章逼自己講清楚
  • 發現講不清楚時,回 repo 查到清楚為止

謝謝看到這裡的你。下一步,我會先把分享預覽和跨瀏覽器測試補起來,讓已經完成的內容更容易被看見,也更穩定地被玩到。


上一篇
Day29 《九重燼》正式公開!
系列文
《九重燼》Vue3 + PixiJS + Ink.js 視覺小說遊戲開發全紀錄30
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言