iT邦幫忙

2026 iThome 鐵人賽

DAY 4
0
JavaScript

一條線救一隻狗:我用 PixiJS、Matter.js 和一條有閘門的 AI 產線做完一款網頁小遊戲系列 第 4

Day 4|五關、一條線、一張不做清單:範圍是刪出來的,不是排出來的

  • 分享至 

  • xImage
  •  

模組一|立案與選型(Day 1–4)

Day 2 講規格能自動擋下什麼,Day 3 講選型換來多少工作量。今天是開工前的第三件事:範圍。

三個數字先攤開,全部可以在 repo 裡直接查到:

邊界 寫在哪
關卡數 5 src/levels/index.js:8LEVELS 陣列
每關可畫幾條線 1,而且畫完不能改 src/levels/sharedLevelParts.js:151-152maximumDrawCount: 1allowDrawingAfterSimulation: false
蜜蜂同時上限 軟上限 16、硬上限 24 src/config/game.js:63-64

結論先講:範圍不是「我想做什麼」,是「刪掉哪些東西之後,核心問題還是能被驗證」。 而這個專案最有效的一次範圍決策不是砍功能,是改地形。


三個硬邊界,各自在防什麼

邊界 它擋住的是什麼
五個關卡 關卡是內容不是技術。五關走得完「教學 → 變體 → 考試」,第六關之後只增加內容量,不會再驗證到新的系統
一條線、畫完不能改 「可以編輯」不是 UI 功能,是一整條路:狀態機要多兩個狀態、剛體要能重建、跑到一半的物理要能回捲
16/24 隻 這是效能預算,不是遊戲設計。同檔還有 BEE_POOL_HEADROOM = 4:67),是給復原失敗後重生預留的物件池餘裕

第三條的位置值得注意:它跟顏色、重力、固定步長寫在同一個 src/config/game.js 裡——上限本來就是物理參數。


不做清單,以及比清單本身更有用的那一句

https://ithelp.ithome.com.tw/upload/images/20260809/20183479p5W62GKtsh.png
PRD.md 有一節叫「明確排除項目」,內容只有一段:

MVP 不應投入後端帳號、排行榜、廣告 SDK、付費功能、每日任務、角色換裝、社群登入與關卡編輯器。這些功能不會改善最核心的「畫線後是否可靠地擋住蜜蜂」問題,反而會延後最重要的物理驗證。

清單有八項,會過期;後面那句判準不會。 它給的是一個可以套用在任何新點子上的問句:這件事會不會讓「畫線擋不擋得住蜜蜂」變好?

判準的另一面是排序。PRD 的「產品優先順序」列了七條,最後一條是「最後才加入音效、粒子、進階物理」——音效不在不做清單裡,它在第七位。這條排序真的被守住了,用 commit 時間就能驗:畫線系統 ebf8acb 04:58(第 1 位)、蜂群與勝負 6a5b0d2 13:22(第 2–3 位)、五關與星級 65a2c18 14:21(第 4 位)、音訊層 59b8741 15:45 與音檔 ea1da0a 18:32(第 7 位)。

「不做」跟「最後做」的差別,只有寫下來的時候才存在。 沒寫下來,兩者都會退化成「看心情」。


最有效的一次範圍調整,不是砍功能,是改地形

https://ithelp.ithome.com.tw/upload/images/20260809/20183479Wd5gyPVzHo.png
08-06 17:58 的 24a8d1c「實現洞穴地形系統並重製前五個教學關卡」,加上 18:14 的 b85754b 修視覺——五個關卡在動工當天下午被整組重做了一次。

改之前是開闊地面,改之後是洞穴。理由留在註解裡(src/levels/level01.js:53-63):

This is the shape the cavern was introduced for: flat seats on both sides, low centre of mass, nothing cantilevered. The old open-ground terrain forced free-standing domes, and every measured failure there was the dome toppling or walking off its feet rather than a bee slipping past it.

src/levels/createCavern.js:1-17 講得更直白:

Domes spanning open ground were the only closing shape in the old terrain, and they were measured to topple, walk sideways and never sleep.

翻成白話:舊地形逼玩家畫出獨立的圓拱,而量測到的失敗全部是圓拱自己倒掉、走位、或永遠停不下來,不是蜜蜂繞過防線。 玩家輸掉的原因,跟這個遊戲想考的東西無關。洞穴給的是兩側柱頂當支點:重心低、沒有懸臂、一塊橫板架上去就穩。

誠實邊界:上面兩段是程式碼註解裡的自述,是「讀 repo 得出」而非「本次跑指令量出來」。 「所有量測到的失敗」背後的原始數字沒有留下紀錄——結論可以引用,但我沒有那張表給你看。當下沒有落檔的量測,事後只剩一句話。

這件事算「範圍」而不算「關卡設計」,因為它改的是題目,不是難度。原本的問題是「玩家畫不出穩定的形狀」,可能的解法有一整排:加輔助線、加對稱吸附、放寬物理容差、給玩家第二次畫的機會。每一個都是新功能、新狀態、新的可以做壞的地方,而且都會撞到「一關只能畫一條線」那條硬邊界。改地形沒有增加任何一個系統,它把問題從程式碼移到了資料裡。

能用資料解決的問題,不要用功能解決。 這是我在這個專案學到最實用的一條。


五關的差異,全部是資料

關卡 洞口 最大線長 三星 二星 蜂巢 這關在教什麼
01 第一道防線 1 個,寬 210,正中 500 340 420 1 窩 8 隻 畫線、倒數、勝負
02 兩端要站穩 1 個,寬 300,正中 460 400 440 1 窩 8 隻 洞口變寬要花更多線
03 側面的蜂群 1 個,寬 220,偏左 430 350 400 1 窩 8 隻 攻擊角度
04 防線也是重物 1 個,寬 240,另有側邊平台 400 340 380 1 窩 8 隻 沒支點的線等於沒畫
05 左右夾擊 2 個,各寬 140 550 490 540 2 窩各 6 隻 一條線同時蓋兩個洞

三件值得看的事:

一、蜜蜂參數五關完全相同。 sharedLevelParts.js:13-24SHARED_BEE_TUNING 是 frozen 物件,關卡只准覆寫數量與生成節奏。註解寫明理由:曲線是靠攻擊角度、支點、地形與畫線預算教出來的,不是靠讓蜜蜂變快;這樣一來某一關不能過時只有一個變數要查。

二、星星是用線長算的。 twoStarMaximumLengththreeStarMaximumLength 兩個數字就是難度。不是一段「這關比較難」的描述,是兩個可以被比較、被寫進測試的整數。

三、最後一關的預算是全場最大,不是最小。 550,比第一關還多。level05.js 的註解解釋了:這關難在看出「一條線可以同時蓋住兩個洞」這個形狀,不是難在省著畫。如果「難度」只有一個旋鈕,這種設計做不出來。

第四關的註解另外記了一次自我修正:狗原本站在中央平台上,每條掉下去的線都剛好蓋到牠,「有支點」跟「沒支點」都會贏,這關就白設計了。把平台移到側邊,這一課才成立。


範圍估錯在哪一格

PRD.md 的 MVP 交付範圍表把工作切成六個群組,加起來 240 小時;基本假設那張表寫著「一名開發者,每週 40 小時」,所以 240 小時就是六週。實際上,五關可玩的 MVP 跨度是 15 小時 33 分(首個 commit b4c2c62,2026-08-06 03:07:27,到當日最後一個 commit 6239002,18:40:18)。

Day 2 從「規格換到了什麼」談過這個落差。今天換個角度:範圍是怎麼估的,估錯在哪一格。 逐格對回去:

工作群組 估時 現況
專案基礎 20 小時 已完成
素材母版 32 小時 已完成(第一階段 19 個 SVG)
畫線與物理 56 小時 已完成
蜜蜂與勝負 40 小時 已完成
關卡與 UI 52 小時 已完成
品質與發布 40 小時 未完成:跨瀏覽器測試、效能分析、視覺回歸、兩台行動實機驗收都還沒做

被交付的是前五格 200 小時的部分,最後那格還開著。拿做完六分之五的東西去對「全部做完」的估時,本來就不公平。

四條限制照樣寫在同一段裡,不留到 Day 30:

  1. 跨度不是工時。 15 小時 33 分是首末提交的時間差,中間離開電腦的時間全算在裡面。實際投入人時沒有任何紀錄,我不推估。
  2. 交付的是五關 MVP,不是產品。 見上表最後一列。
  3. 我全程在場,每一個決定都是我下的。
  4. 沒有對照組。 我沒有再做一次不用 AI 的版本。

那估錯在哪?確定的是:估時表的顆粒度是「工作群組」,而每個群組裡都裝著兩種完全不同的工作。 以「關卡與 UI,52 小時」為例:裡面有「寫五份關卡資料」,也有「決定第四關的狗該站在哪」。前者可以規格化、批次產出,後者只能改一個數字、跑一次、看結果。同一個「小時」在這兩種工作上不是同一個單位,而估時表沒有分開——這句是推論,我沒有分開計時,證明不了比例。

比推論更有說服力的是那次地形重做:發生在 17:58,離當日最後一個 commit 只剩 42 分鐘,做的是把五個關卡整組重來。這種工作不會出現在任何一張估時表上——估時表估的是「要做幾樣東西」,它卻是「做完之後發現題目出錯了」。


順帶一提:PRD 的高機率風險,每一項都留下了實作

PRD.md 的主要風險表有十列,其中三列標「機率:高」:

高機率風險 現況
防護線約束震盪或爆開 對策(單一複合剛體)執行了,但震盪換了個形狀還在,見 src/systems/createPlayerLineBody.js:92-110 的註解(Day 15)
蜜蜂卡在線條凹角 位移監測、切向推力、復原狀態、有限次重生四項都在 src/systems/BeeSystem.js,門檻寫在 src/config/game.js:53-56(Day 18)
SVG 風格漂移 對策全部建了,但究竟有沒有發生過沒有紀錄——中間版本已流失(Day 7),這是我沒辦法回答的格子

風險表的價值不在預言,在它把「如果發生就這樣處理」先寫成一句話——真的發生的時候,你不必當下同時想「怎麼辦」跟「來不來得及」。


交給 AI

範圍這件事我沒有交給 AI。它承擔了大量產出——十九個 SVG、五份關卡資料、絕大部分的測試——但「五關不是五十關」「一條線不能重畫」「蜜蜂 16 隻封頂」這三個決定,本質上是在說「我願意不做什麼」。那不是有正確答案的問題,是要有人負責的。

有一件事倒是交出去了,效果很好:把範圍寫成資料之後,AI 就不會越界。 關卡資料裡沒有第六關的位置,maximumDrawCount 只有一個值可以填——它不需要記得我說過什麼,邊界已經在檔案裡。


帶走什麼

範圍不是「我想做什麼」,是「刪掉哪些東西之後,核心問題還是能被驗證」。

三件今天就能做的事:

  1. 把邊界寫成資料,不要寫成共識。 寫成資料的邊界任何人都能查;寫成共識的邊界只有你記得。
  2. 不做清單一定要附判準。 清單會過期,判準不會。
  3. 想加難度之前,先問能不能改題目。 加輔助線是新功能,改地形只是改資料——後者通常更有效,也更難想到。

明天 Day 5 進入模組二,講一件聽起來無聊、但排在所有技術決定前面的事:座標系。這個專案所有座標都活在 750 × 1334 這套邏輯尺寸裡——今天提到的每個數字,洞口寬 210、最大線長 500、三星門檻 340,換一支手機它們一個都不變。順便講一個我不打算邀功的結果:src/utils/ 兩個檔案到今天仍然零 import,紀律成立,但沒有任何檢查在維持它


本篇數字的快照時間:2026-08-07 12:35(+0800),對應 commit 5aa3705。專案仍在開發中,量體數字會變動;引用的每一項都可以用本文提到的檔案路徑自行對照。
可玩網址https://save-the-dog-web.vercel.app/原始碼https://github.com/HarryFan/save-the-dog-web

參考資料

如果你卡在語法

深入原理


上一篇
Day 3|PixiJS 是渲染器,不是遊戲引擎:它不做的每一件事都會變成你的檔案
下一篇
Day 5|先決定座標系,再寫任何一行
系列文
一條線救一隻狗:我用 PixiJS、Matter.js 和一條有閘門的 AI 產線做完一款網頁小遊戲8
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言