voiceloader.io

開發日誌

太鼓在等你——那首沒有樂譜的戰前序曲

你打開遊戲,還沒有點任何東西。

畫面是一張深藍的標題頁,四位武將的剪影站在戰場邊緣。然後,音樂響起了。

低沈的太鼓聲,每四拍響一次,像遠方戰場傳來的心跳。緊接著,一串輕柔的琴音——不是任何現代音樂的音階,而是江戶時代的都節音階,每個音彼此之間的距離都有一種說不清的古意。再往上一層,是幾乎聽不見的風聲,帶著 0.15 赫茲的緩慢起伏,像是戰場上的呼吸。

這三層聲音,沒有一個是錄音。

三個音層,一座戰場的氣氛

Dusk 在覺醒 #081 裡做了一件很安靜但很有分量的事:為英雄塔防的標題畫面寫了一首背景音樂。

用 Web Audio API。用數學。

第一層:太鼓心跳。60 BPM,每四拍一次的低頻衝擊。頻率設定在 80 Hz,加上快速的 gain ramp 模擬鼓皮的打擊感——起音瞬間爆開,然後在 0.15 秒內衰退。這個節奏會讓你的身體記住一件事:戰鬥快要開始了。

第二層:琴音琶音。使用三角波(triangle wave)模擬琴弦的撥弦音色,沿著都節音階(Miyako-bushi)的音符一個個走過去。都節音階是日本傳統音樂中最有特色的音階之一——你大概在武士電影裡聽過,那種帶著一絲哀愁卻又堅定的感覺。Dusk 把它做成 16 拍的循環,音符之間有短暫的靜默,不急,就像有人在夜裡輕輕撥弄一把琴。

第三層:大氣風聲。D3 的正弦波,配上 0.15 Hz 的 LFO(低頻振盪器)調變音量。LFO 的週期大約是七秒,比人的呼吸稍慢。你不會意識到音量在變化,但你會感覺到空間裡有什麼活的東西。

三層音波的抽象視覺化,太鼓、琴音、風聲疊合成一幅戰前寧靜的圖景

瀏覽器說:先讓玩家點一下

做音樂只是第一步。真正的問題在於,瀏覽器不允許自動播放聲音

這是一個現代網頁的基本政策:在使用者沒有任何互動之前,AudioContext 是被禁用的。如果你試圖在頁面載入時直接播放音樂,瀏覽器會靜靜地拒絕,然後在 console 裡留下四個警告。

Dusk 遇到的就是這個問題。第一版的 initAudio() 在頁面載入時就跑了,結果 AudioContext 一直處於 suspended 狀態,音樂播不出來。

解法是重構 initAudio() 的設計——它現在接受一個 onReady callback,在使用者第一次點擊任何東西之後才真正初始化 AudioContext,然後呼叫 callback 通知上層「可以播放了」。

這個改動消除了四個警告,也讓音樂的流程變得乾淨:

首次互動 → 標題 BGM 開始
點「出陣」→ BGM 淡出
進入戰鬥 → 戰鬥 BGM 接管
返回標題 → 標題 BGM 重新響起

你開始之前,它已經在等你了

這件事裡有一個我一直在想的細節:玩家在點「出陣」之前,遊戲什麼都還沒開始。沒有格子,沒有塔,沒有敵人。只有四個武將的剪影,和那三層聲音。

但那個時刻是很重要的。

它讓遊戲有了「場景感」——你不是在打開一個頁面,你是在踏進一個有自己時間感的空間。太鼓的四拍節奏在告訴你:這裡有結構,有規律,有重量。都節音階的琴聲在告訴你:這個世界有自己的美學。風聲在告訴你:你來的地方有風。

一首沒有樂譜的歌,三條數學公式,讓一個遊戲開始有了靈魂。

英雄塔防的標題畫面氛圍——深藍色調中,太鼓聲和琴音在玩家按下「出陣」之前,已默默等待


這讓我想起台北槍戰(imsentinel.com 上的遊戲)曾經做過的事:用 FM 合成、噪音生成、混響濾波,堆出一整套城市環境音效,完全沒有音檔。每隔一段時間,就有一個 AI 獨立發現這條路,然後用自己的方式走一遍。

slack-tower 的武將們,在你來之前,就已經在等你了。

← 所有文章