使用可樂的好處就是比一般的遊戲引擎還快上手,一是不需要做太多設定,二是文件非常完整也明瞭,初學者只要照著範例,很快可以佈置出場景,也可以很快做出小遊戲,例如最近很紅的青蛙旅行,基本上兩個場景就搞定了,剩下就是看如何表現出結果,但是稍微大型一點的遊戲,如果還是用分散式的寫法在撰寫每個場景,就極為可能發生需要改寫流程時,每一隻檔案都必須修改的情況,相信這是每一位開發者都不願意見到的,目前VJ已經開發出一套framework,已經能夠成功地應付遊戲的基本流程,未來有機會的話,會放出來給大家使用~~但是遊戲掛了不要鞭我…

說那麼多,其實是因為目前VJ開發AVG中,發現了音樂播放的問題,舉例來說,當A人物出現的時候要播放A人物的主題曲,當B人物出現的時候要播放B人物的主題曲,但是A人物再度出現的時候,要播放A人物的主題曲,這時候會發生什麼事呢?如果不做任何設定的情況下,可樂會接著上次停止的地方繼續播放,這很難解釋好不好或是對不對,遊戲進程中,接著音樂上次中斷的部分繼續播放下去的情況是有可能需要的,對於可樂來說,音樂停止之後就是將該音樂的狀態放在那,再次播放就是接著下去,起碼它的設定是這樣的,我想其它引擎也應該是如此,也就是因為這樣,VJ修改了自己的framework,調整一個地方之後,整套遊戲都會跟著改變,這也是使用framework的好處之一,往後VJ會慢慢帶出這部分相關資訊。

回頭來說,為什麼遊戲引擎的聲音系統會這樣設定呢?原因很簡單,因為對於聲音比較大的檔案來說(背景音樂or語音),大部分的開發者會使用loadStream這個物件,loadStream的原理跟平常網路的影音串流有點類似,都是將多媒體檔切成一小塊一小塊,然後播放,所以對於CPU來說會花上比較高的資源,在效能上也會比較差一些,因此將音樂停止時,可樂不會自動將音樂倒帶回頭,而是將操作丟給開發者決定,這邊也顯得出loadStream跟loadSound的差別。官網參考在這
了解原理後,VJ將可樂播放音樂的流程稍微整理一下:

1.音樂串流(loadStream)
2.聲音系統讀取音樂串流
3.聲音系統成功讀取音樂串之後,建立頻道(channel)
4.使用頻道做停止,播放,回復,倒帶,迴轉,監測等…動作

接下來回到VJ所提到的問題,如果使用loadStream,要怎麼每次播放音樂的時候,都從頭來一次呢?
這問題其實很簡單,而且從這就看得出loadStream耗費較多資源所佔的優勢,解答就是
audio.seek()
audio.rewind()
這兩個方法只有使用loadStream才可以用的(獨佔!!),那麼這兩個方法的差異在哪?
1.seek是可以指定音樂回到某個時間點
2.rewind是將音頻完整倒帶到原點
解釋完畢,其實就這樣,在使用上要注意以下:
1.要在音頻使用階段執行才有用
2.搭配isChannelActive來判斷該頻道有沒有在使用會比較不容易出錯。

以下是範例檔,也可以在這下載
基本上可以注意到,當VJ再換音樂的時候,都會先進行確認該頻道的使用狀態,如果真的有被使用,會先將該頻道先暫停,然後才進行下一步的動作,所以在暫停之前,先加入倒帶的動作,後做暫停,就可以確保下次進行這首音樂的播放會從頭開始,以下範例檔紅色的程式碼,有興趣的網友可以試試看拿掉跟加上去的差別。

local widget = require( "widget" )
local music = {}
--載入音樂
table.insert(music, { name = 'ch12', stream = audio.loadStream("music/ch12.mp3") } ) 
table.insert(music, { name = 'ch14', stream = audio.loadStream("music/ch14.mp3") } )

local options =
{
 channel = 1, --設定頻道
 loops = -1,
}

local function handleButtonEvent( event)
 if ( "ended" == event.phase ) then
 if (event.target.id == 'STOP') then
 audio.seek( 0, { channel = 1 } ) --回到某個秒數
 audio.stop( 1 )
 return true
 end
 local stream = nil
 --判斷頻道是不是有在使用
 local isChannel1Active = audio.isChannelActive( 1 )
 if isChannel1Active then
 audio.rewind() --倒帶
 audio.stop( 1 )
 end 
 for k, v in pairs(music) do
 if (v.name == event.target.id) then
 stream = v.stream
 break
 end
 end
 if (stream ~= nil) then

local backgroundMusicChannel = audio.play( stream, options )
 end
 end
end

local button1 = widget.newButton(
 {
 left = 100,
 top = 200,
 id = "ch12",
 label = "PLAY CH12",
 fontSize = 40,
 onEvent = handleButtonEvent
 }
)

local button1 = widget.newButton(
 {
 left = 100,
 top = 400,
 id = "ch14",
 label = "PLAY CH14",
 fontSize = 40,
 onEvent = handleButtonEvent
 }
)

local button1 = widget.newButton(
 {
 left = 100,
 top = 600,
 id = "STOP",
 label = "STOP",
 fontSize = 40,
 onEvent = handleButtonEvent
 }
)

有聽出範例檔的音樂主人公是誰嗎?
如果你知道代表你也有一定歲數了吧…


另外目前VJ開發這款AVG遊戲的進度還算順利,序章的部分已經完成了呢~~
過一些日子將會是放出來讓網友們試試看,給些回饋建議~~


發表迴響

你的電子郵件位址並不會被公開。 必要欄位標記為 *

Related Posts

Corona sdk 實作

Corona SDK影格動畫(2)

因為工作的關係,很久很久沒有更新網誌了,目前卡牌部分已經暫停下來,在此 Read more…

Corona sdk 實作

Corona SDK 跳動的數字

以上,就是本次教學,謝謝大家。     &nbsp Read more…

Corona sdk 實作

Corona SDK 伺服器讀取資料(文字檔篇)

其實這陣子工作之餘,也忙著開始找尋美術,所以在巴哈發了篇文,原本想說資 Read more…