iT邦幫忙

2025 iThome 鐵人賽

DAY 13
1

前陣子,我們介紹了許多跟畫面顯示有關的功能,而今天,我們要來介紹遊戲中除了畫面以外,另外一個同等重要的元素——聲音

PixiJS 雖然作為一個 2D 繪圖引擎,但它其實還提供了一系列與音訊有關的功能,讓我們可以快速的播放、控制音訊。如果你是在自己的環境的話,需要先自行安裝 pixijs/sound 這個擴充套件,因為它並不包含在 PixiJS 本體裡面。不過 CG 作為一個線上遊戲開發平台,自然也是幫我們把這一步做好了,而我們要做的事情就是享用它!

▸ 播放音訊

與創建 Sprite 一樣,我們需要先載入音訊檔案至專案中,再利用資源的別名來播放音訊,詳細的載入方式可以參考 Day 03,你可以使用其他人上傳的公開音訊,也可以自行上傳音訊,.mp3.ogg 等皆可。

確保專案內已經有音訊資源後,就可以用下方程式碼的方式來播放音訊。

import pixi = CG.Pixi.pixi;

async function start() {

	// 載入資源(記得將資源別名修改成你自己專案的資源別名喔!)
	await pixi.assets.add("ironman2025_cook.音效.pop").load();

	// 播放音效
	pixi.assets.playSound("ironman2025_cook.音效.pop");
}

start();

所有的專案資源在使用前,都必須利用 pixi.assets 將該資源載入至遊戲中。

而在 CG 上,pixi.assets 幫我們把播放音訊這件事情變得更加簡單了,只需要一行程式碼 pixi.assets.playSound(),我們就可以播放音訊。

而如果你想要改變播放的音訊音量,或是讓它循環播放,可以這樣:

pixi.assets.playSound("ironman2025_cook.音效.pop", {
    volume: 0.5, // 音量 50%
    loop: true   // 啟用循環播放
});

如此一來,這個音效的音量就會被調整到 50%,並且循環播放。volume 的範圍通常是 0 ~ 1,0 就是 0%,1 就是 100% 的意思。

▸ 掌握音訊物件:PIXI.sound.Sound

雖然 playSound() 提供了便利的播放功能,但在某些情境下,你可能會需要更直接地操作音訊物件本身,例如:暫停、恢復或停止播放。這時,我們就需要使用 pixi.assets.getSound() 來取得 PIXI.sound.Sound 物件。

// 取得 sound 物件
const sound: PIXI.sound.Sound = pixi.assets.getSound("ironman2025_cook.音效.pop");

// 播放音訊
sound.play({ volume: 0.5, loop: true });

PIXI.sound.Sound 物件讓我們可以對聲音進行控制。以下是一些常用的方法:

  • sound.play():播放音訊。
  • sound.pause():暫停播放。
  • sound.resume():從暫停的地方繼續播放。
  • sound.stop():停止播放,並將播放進度歸零。

有了這些方法,你就可以輕鬆實現背景音樂的暫停與恢復功能,這在遊戲暫停選單中非常有用。

直接對 Sound 操作的話,會影響到所有由這個 Sound 創建的 IMediaInstance,例如停止所有 IMediaInstance 的播放,下面再來看看 IMediaInstance 是什麼。

▸ 單一播放實例的細緻控制:PIXI.sound.IMediaInstance

如果你想要更細緻地操控音訊,例如同時播放多個相同的音效,並分別控制它們的音量,就需要處理單一播放實例(Instance)。一個 Sound 物件可以有多個播放實例,每個實例都代表著一次獨立的音訊播放。

pixi.assets.playSound() 播放 Sound 的回傳值就是一個 PIXI.sound.IMediaInstance 物件。

const instance: PIXI.sound.IMediaInstance = pixi.assets.playSound("ironman2025_cook.音效.pop");

這個 instance 物件讓我們能對這次播放進行獨立的控制,而不會影響到其他正在播放的相同音效。

// 暫停這個特定的音效播放實例
instance.pause();

// 播放這個特定的音效播放實例
instance.resume();

// 停止這個特定的音效播放實例
instance.stop();

// 檢查這個實例是否正在播放
console.log(instance.isPlaying); // true 或 false

// 隨時調整這個實例的音量
instance.volume = 0.8;

這個功能在處理快速重複的音效時非常有用,例如射擊遊戲中的槍聲,每次射擊都會產生一個新的播放實例,讓你可以獨立地控制每一發子彈的聲音。

此外,你還可以利用這個特性來避免聲音重疊。舉例來說,當玩家連續快速射擊時,你可能不希望有太多個槍聲同時響起而造成雜音。這時,你就可以在每次播放新音效前,先停止上一個播放實例,或是將其音量快速淡出,如此一來,就能有效管理音訊,讓遊戲體驗更流暢。

▸ 結合 Tween

還記得 Day 11 的 Tween 嗎?它不只是可以用在 PixiJS 上製作動畫,前面我們提到了如何使用 IMediaInstance 物件來控制單一音效的播放,這時,如果我們再結合昨天介紹的 Tween,就可以實現一些很酷的效果,例如音效淡入淡出`

這個功能在遊戲中非常實用,像是當玩家進入一個新場景時,你可以讓背景音樂從無聲慢慢淡入;或是當遊戲暫停時,讓背景音樂慢慢淡出。

// 播放音樂,將一開始的音量設定為 0,並將音效實例儲存在 musicInstance
const musicInstance = pixi.assets.playSound("ironman2025_cook.音樂.bgm", { volume: 0 });

// 創建一個 Tween,將 instance 的音量從 0 淡入到 0.5
new TWEEN.Tween(musicInstance)
	.to({ volume: 0.5 }, 2000) // 2000 毫秒內將音量從 0 漸變到 0.5
	.start();

怎麼樣?想不到 Tween 還可以這樣用吧!同樣的,我們也可以搭配緩動函數(Easing Function)來讓音訊的淡入淡出變得更加平滑順暢,這個部分就給各位去琢磨琢磨啦~

點我查看範例程式碼

▸ 總結

今天的內容讓我們將「聲音」這個重要元素帶進了遊戲。

  • 最簡單的方式是使用 pixi.assets.playSound() 來播放音效。
  • 如果需要暫停或停止播放,可以透過 pixi.assets.getSound() 取得 PIXI.sound.Sound 物件來操作。
  • 如果需要管理同一音效的多個播放,則可以使用 PIXI.sound.IMediaInstance 來進行最細緻的控制。
  • 此外,我們還可以結合昨天介紹的 Tween,輕鬆實現音效的淡入淡出效果,為遊戲增添更多層次感。

經過這幾天的介紹,我們已經掌握了遊戲主迴圈(Game Loop)補間動畫(Tween)、**圖集動畫(Spritesheet)音訊控制(Sound)**這四大核心技術。

明天,我們將把所有學到的知識融會貫通,將第一階段做個總結,一起動手實作一個會動、會響、且能夠互動的小場景吧!


上一篇
Day 12:遊戲世界中的定格動畫 - Spritesheet
下一篇
Day 14:第一階段總結 - 一個會動、會響的互動場景——幸運餅乾
系列文
用 PixiJS 寫遊戲!告別繁瑣設定,在 Code.Gamelet 打造你的第一個遊戲16
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言