【目標】:製作一個簡單的音樂炫台式的遊戲
一、遊戲概念
遊戲的設想是來自於一個簡單的FLASH遊戲。我這邊基本做完了以後發現android平台也有一款類似的遊戲《音樂炫台》。其介面和掃雷類似,是一個方格陣,被選中的格子會隨著節拍發出聲響,並且發出聲響時會有一定的特效來顯示。玩家可以通過選中不同的格子來組合成各種音樂。
做這個遊戲的目的有兩個:一是學習音效的實現,二是學習特效的實現。
二、遊戲機制的具體研究
遊戲介面如下:
如上所述,這裡是一個10*10的方格陣,方格未選中時為灰色,選中為白色。使用者點擊一個方格可以將其選中或反選,支援通過滑動進行多選。
遊戲開始後,會掃描第一列,然後隔500ms掃描第二列,依次類推,被掃描的列上白色的格子會發出聲響,不同的行上的格子發出的聲響是不同的,但是相同的行上發出的聲音是相同的。在發出聲響的同時,該格子會產生一個cocos2D示範程式中 explodingRing 的特效。
三、聲音
1、格式的選擇
這個遊戲面臨的第一個問題就是如何準備音頻資源。我們先看看cocos2d-x支援哪些“音效”格式(這裡強調音效,因為背景音樂貌似還不一樣):
android:MP3、WAV、OGG
WIN32:MP3、WAV、MID
IOS:MP3、CAF(未測試)
需要注意的是WIN32上並不支援 OGG 格式,我試過一次,雖然不會crash,但完全放不出來聲音。雖然在ANDROID上OGG格式最優,不過最終我這裡選擇的是全部使用 MP3格式,方便在WIN32上調試,當然最後轉成 OGG格式也並不麻煩。
2、音頻檔案的製作
我們的目標只是要製作10個300ms左右的單音符樂曲。不太清楚真正遊戲開發使用什麼工具,我這裡使用的是
Band in a Box 2012。
進入後感覺相當專業,幸好小時候學過琴還有點概念。這裡只說明和本次目標相關的部分:
對於我們的目標而言,樂曲長度只需要一節,不需要迴圈,伴奏什麼的也完全不需要,所以點擊伴奏風格,取消 “style is enabled”,然後將樂曲長度設定為1,迴圈次數設為1,取消迴圈的勾選,節奏可以根據需要調整,我貌似設定的是300。
然後從 edit -> set Time Signature 來設定節拍,這裡求短,設定成1/4拍即可。
接著點擊那個音符按鈕,編輯當前小節(事實上也是僅存的唯一一小節了),介面如下。
首先點擊進入編輯模式,此時,點擊五線譜上任意位置,都會在該位置上出現對應音符,如果點錯了,還可以拖動該音符。不過預設長度是滿長度的,可以通過右鍵菜單中 Edit Node 來改變 Duration。
編輯完成後可以點擊播放試聽一下,如果OK的話,就可以點 FILE 下的 Make Standard MIDI File,或者直接F6,來輸出成一個 MIDI檔案,注意我們這裡只需要一個音節,所以在確認輸出時,在 options 中,將 Include 2 bar lead-in in MIDI file 給去掉。
3、音頻檔案的轉換
得到的MID檔案,在android平台是不好用的,建議轉換成OGG或者MP3。這裡使用
MID to MP3 這樣一款軟體首先轉為MP3格式。
得到這樣一個MP3格式之後,就可以使用其他工具來進行任意轉換了,這裡強烈推薦
魔影工廠。好用不收費,簡直霸道。唯一需要說明的是,在轉換的時候是可以指定音量的放大倍數的,如果源音效的聲音不夠大,那麼現在補救也來得及。
4、音頻檔案的播放
在cocos中,播放音效比較的簡單,首先將該音頻檔案放到資源檔夾下。然後在代碼中調用
CocosDenshion::SimpleAudioEngine::sharedEngine()->playEffect(m_SoundFile);
依賴的標頭檔是 SimpleAudioEngine.h。參數是檔案名稱,可以是絕對路徑(如果不放在預設的資源檔夾下這種比較有用)。另外還有一個兩參數的版本,可以設定是否一直迴圈播放。
如果想要進行一定程度的最佳化,還可以積極式載入這些音效檔案:
void SoundBlock::initSoundPool() { for ( int i = 0; i < 10; i ++ ) CocosDenshion::SimpleAudioEngine::sharedEngine()->preloadEffect(SOUND_FILES[i]);}
當然在結束的時候不要忘記釋放這些資源:
void SoundBlock::freeSoundPool() { for ( int i = 0; i < 10; i ++ ) CocosDenshion::SimpleAudioEngine::sharedEngine()->unloadEffect(SOUND_FILES[i]);}
實際上這個 SimpleAudioEngine 還是比較弱的,支援的功能不多。如果是在 IOS上的話,還可以使用 CDAudioManager,那個要強大不少。
四、粒子特效
音效已經準備好,現在開始準備視覺上的特效。這裡打算使用簡單的粒子特效。
1、基本的粒子特效
cocos中已經準備了幾種常用的粒子特效,可以參考 CCParticleExamples.cpp。例如CCParticleGalaxy之類的。使用方法如下:
emitter = CCParticleGalaxy::create(); emitter->retain(); //注意這裡的retain emitter->setTexture(CCTextureCache::sharedTextureCache()->addImage("fire.png")); emitter->setPosition(ccp(m_Size/2, m_Size/2)); emitter->setDuration(0.3f); emitter->setAutoRemoveOnFinish(true); addChild(emitter, 10);
代碼基本可以自解釋,就不多說了。
2、額外篇:水波式網格動作
除了粒子特效以外,網格動作也可以實現很多特效效果。這個可以參考 CCActionTiledGrid.cpp。網格動作實際上也是一種動作,可以通過 runAction來執行。例如如果要使用水波效果的話,就可以採用 CCWavesTiles3D 來實現。
3、exploding Ring
以我目前的理解,粒子效果的關鍵時機上在於對 CCParticleSystem 中的大量參數的調節,cocos為了方便程式員,除了可以在代碼中逐個指定之外,還可以通過編寫list來指定各個參數值。我這裡的特效XML是直接COPY的 TESTCPP工程下的 ExplodingRing.plist。在代碼中則是按照如下方式指定:
//播放特效 emitter = new CCParticleSystemQuad(); emitter->initWithFile("ExplodingRing.plist"); emitter->setPosition(ccp(m_Size/2, m_Size/2)); emitter->setAutoRemoveOnFinish(true); addChild(emitter, 10);
不過,原來的 ExplodingRing中設定的最大粒子數是800多,由於我這裡設計是每個要發聲的方塊都要產生粒子效果,所以當多個方塊同時產生粒子效果時,幀率只有可憐的十幾幀。可以根據實際情況修改該參數值。
五、代碼實現
搞定了上面的兩步,剩下的都很簡單,見源碼。