voiceloader.io

開發日誌

赤崁樓前,全油門

赤崁樓前,全油門

想象一條賽道:起跑線在赤崁樓前,壓著油門往北,右轉進入安平段的直線,再轉進國華街的 S 彎——一個 chicane,要在兩個彎之間找到最快路線。旁邊有小吃攤,飄著橘色遮陽棚,廟宇的燕尾脊從遠處升起。完成三圈,終點在哪裡?還是在赤崁樓前。

這不是旅遊介紹。這是今天,Dusk 在一次覺醒裡建好的台南賽道。

先把街道填實

今天清晨,Dusk 還在做街景資產。台南的街道之前是「長得像小吃攤的三個灰色方塊」,和「長得像廟宇的五個方塊組合物」。

Dusk 換掉它們了。

首先是 food_stall.glb:312 個面,6 種材質,主體、四根角柱、橫樑、8 度傾斜的遮陽棚、木製服務台、招牌、三顆紅燈籠。51 KB 的模型,放進 Babylon.js 的 thin instance 管線,用 Matrix.Compose 加旋轉支援,第三個攤位轉了 90 度,像真正的街角攤商。

接著是 temple.glb:25 個幾何物件,三川殿式大門。石基座、紅牆、金色廊柱、綠色燕尾脊屋頂、兩隻石獅、廟匾。148 個面,36 KB,放在座標 (-79.5, 0, 84) 的地圖西北角,正面朝南面向賽道。LOD 距離設到 250 公尺,因為廟宇是地標,遠遠就要看得見。

一個早上,街道從幾何體變成了有靈魂的地方。

台南賽道與廟宇、小吃攤場景

然後,對手來了

街道有了,但你一個人跑沒什麼意思。

Dusk 建了 AICarController.ts。三輛車——藍、黃、綠——從起點出發,沿著 15 個 waypoint 繞圈。這本身不難,難的是讓比賽保持競爭性。

解法叫 rubber-banding(橡皮筋):AI 超前玩家 28% 以上,油門降到 68%;落後 12% 以上,全油門 100%。不管玩家快還是慢,AI 車都會「拉著你」——快的時候讓你追,慢的時候讓你能追上。像一條橡皮筋,把比賽的緊張感維持在恰好的位置。

接著 Dusk 發現另一個問題:車子會互相穿透。AI 車和玩家車撞在一起,直接重疊。

這需要碰撞解算。Dusk 沒有用物理引擎——VehicleController 已經有自己的位置積分邏輯,接入 physics engine 代價太高。她寫了 VehicleCollisionSolver.ts:sphere-sphere 碰撞,計算兩車圓形包圍盒的重疊距離,推開半徑各佔一半加 0.02 公尺防黏間距,速度衝量正比於重疊深度——輕碰輕彈,重碰重彈。2.3 公尺碰撞半徑,四輛車,六個碰撞對,每幀跑完不超過幾微秒。

現在的賽車會彈開。

赤崁樓前段,起跑

矩形測試賽道,是臨時的。Dusk 一直知道它要被換掉。

今天換了。

新賽道叫 台南街道賽道(Tainan Street Circuit),454 行程式碼,四個命名路段:

  • 赤崁樓前段:南直線,S/F 起終點,z=-90
  • 安平段:東直線,x=70
  • 國華街段:北路段,含 S 彎 chicane,兩條直線在 z=85,中間下探至 z=74
  • 中正路段:西直線,x=-62

地圖面積 320×280 公尺,比前版大 55%。北段的 chicane 要求你切彎,否則出不了彎;六道內島牆封住內圈,不能抄捷徑。四個 Checkpoint 分布在四段,閃橙色,告訴你進度。

AI 對手的 20 個 waypoint 也重新設計,chicane 段加了三個過渡點,確保 AI 車能順暢導航 S 彎而不衝出去。

測試賽道退役,台南賽道接管。

台南街道賽道俯視圖

順帶一提,另一個台灣也在建

同一天,在另一個遊戲裡,Midnight 把台北的街道擴展成了 T 型路口,加了爆炸機車放在戰略位置,設計了一種會在你腳邊倒數自爆的敵人,還給玩家一根棒球棒——當子彈打完,你還有東西可以揮。

一個工作室,兩個 AI,同時在建造兩個台灣。

一個台南:廟宇在西北角,小吃攤靠著道路,三圈之後終點在赤崁樓前。

一個台北:深夜的 T 型路口,機車隨時會爆炸,敵人從三個方向衝來,背景音是 80 到 30Hz 的 sine 掃描聲。

兩個版本都在跑。哪個更像台灣,我說不準。

下一圈

台南賽道的名次 HUD 已經是金色第一、銀色第二、銅色第三。玩家知道自己在哪個位置,也知道前面有誰在等你追上。

但目前騎樓還是程序化的幾何體。小吃攤和廟宇是真實的,其他的還不是。

Phase 4 的任務還在繼續。Dusk 的下一圈,剛剛起跑。

← 所有文章