十年網(wǎng)站開發(fā)經(jīng)驗 + 多家企業(yè)客戶 + 靠譜的建站團隊
量身定制 + 運營維護+專業(yè)推廣+無憂售后,網(wǎng)站問題一站解決
【嘮叨】
嵩明網(wǎng)站制作公司哪家好,找成都創(chuàng)新互聯(lián)公司!從網(wǎng)頁設(shè)計、網(wǎng)站建設(shè)、微信開發(fā)、APP開發(fā)、自適應(yīng)網(wǎng)站建設(shè)等網(wǎng)站項目制作,到程序開發(fā),運營維護。成都創(chuàng)新互聯(lián)公司自2013年創(chuàng)立以來到現(xiàn)在10年的時間,我們擁有了豐富的建站經(jīng)驗和運維經(jīng)驗,來保證我們的工作的順利進行。專注于網(wǎng)站建設(shè)就選成都創(chuàng)新互聯(lián)公司。
本節(jié)比較簡單,主要講講cocos2dx引擎中的音樂音效SimpleAudioEngine。
【致謝】
http://gl.paea.cn/contents/f86d1f6e2a52e7ea.html
【小知識】
單例類:說的通俗一點,它就是一個全局靜態(tài)類。第一次調(diào)用時會創(chuàng)建一個全局靜態(tài)對象,整個游戲的運行過程中會一直存在,全局都可以訪問。
【Demo下載】
https://github.com/shahdza/Cocos_LearningTest/tree/master/demo_%E9%9F%B3%E4%B9%90%E9%9F%B3%E6%95%88SimpleAudioEngine
【3.x】
(1)獲取單例:sharedEngine() 改為 getInstance()
(2)實現(xiàn)了:音量的調(diào)節(jié)。
(3)修改了播放音效 playEffect() 的參數(shù):
// // 現(xiàn)在還不能完全支持所有參數(shù),限制的功能如下: // 在Samsung Galaxy S2上如果啟用了OpenSL那么pitch參數(shù)無效; // 在emscrippten, win32, marmalade上pitch/pan/gain參數(shù)無效 virtual unsigned int playEffect ( const char* pszFilePath, // 音效文件的路徑 bool bLoop = false, // 是否循環(huán)播放,默認為false,不循環(huán) float pitch = 1.0f, // 頻率,正常情況下為1.0,在播放時也可以改變該值 float pan = 0.0f, // 聲道,范圍為-1到1,為-1時表示只有左聲道,為1時表示只有右聲道 float gain = 1.0f // 音量增益, 范圍為0到1,默認值為1 ) //
(4)其他變化不大。
【SimpleAudioEngine】
音樂音效是每個游戲中不可或缺的部分,一個好的聲音會給玩家留下深刻的印象,當一聽到游戲的聲音,就會不自覺得說出游戲的名稱來。就像《中國好聲音》一樣,筆者對那首《斑馬,斑馬》印象就非常深刻,當然唱這首歌的那個妹子也不錯。
好了,不扯了,繼續(xù)學習……
1、音樂音效介紹
聲音分為兩類:背景音樂、音效。
(1)背景音樂:一般是貫穿整個游戲的音樂,時間長、重復次數(shù)少。
(2)音效: 一般是很短的那種聲音特效,如砍殺、爆炸、走路等,短暫但使用比較頻繁。
cocos2dx是一個跨平臺的游戲引擎,它支持多種聲音格式(比如MP3、WAV等)??墒悄兀瑢τ诓煌钠脚_,聲音的格式可不一定是統(tǒng)一的。這就需要大家根據(jù)不同的平臺,選擇合適的聲音格式了。
根據(jù)兩種聲音的特點,其采用的聲音格式也有所不同。以下列出各平臺所推薦的聲音格式(當然并不是全部支持的格式,如IOS中背景音樂除了MP3和CAF外,還可以使用AAC、AMR等等)。
背景音樂 | 音效 | |
Win32 | MP3、MID、WAV | MID、WAV |
Android | MP3、MID、WAV | OGG |
IOS | MP3、CAF | CAF |
由此可見,背景音樂最適合的選擇是MP3格式。雖然音效也可以使用MP3格式,但是MP3是一種有損的壓縮格式,而音效多數(shù)是短暫而快速的聲響,有損的壓縮方式可能導致有些采樣音源消失,故音效不推薦使用MP3格式。而每個平臺的音效格式均不相同,故需要根據(jù)不同平臺,選用合適的格式。
2、SimpleAudioEngine
cocos2dx為我們提供了聲音模塊CocosDenshion。而其中有個SimpleAudioEngine類,是我們學習研究的對象。
使用SimpleAudioEngine時需要引入頭文件和命名空間:
// #include "SimpleAudioEngine.h" using namespace CocosDenshion; //
SimpleAudioEngine和CCDirector一樣,也是一個單例類。說的通俗一點,它就是一個全局靜態(tài)類。第一次調(diào)用時會創(chuàng)建一個全局靜態(tài)對象,整個游戲的運行過程中會一直存在,全局都可以訪問。
3、獲取單例對象
SimpleAudioEngine的單例對象獲取方法:
// //通過SimpleAudioEngine::sharedEngine()獲得 static SimpleAudioEngine* sharedEngine(); //
4、背景音樂的函數(shù)
相關(guān)操作:預加載、播放、停止、暫停、恢復、重播,以及設(shè)置音量等。
// void preloadBackgroundMusic('音樂路徑const char*'); //預加載 void playBackgroundMusic('音樂路徑const char*', bool bLoop = false); //播放,是否循環(huán),默認不循環(huán) void stopBackgroundMusic(bool bReleaseData = false); //停止,是否釋放音樂資源 void pauseBackgroundMusic(); //暫停 void resumeBackgroundMusic(); //恢復 void rewindBackgroundMusic(); //重播 //返回是否將要播放背景音樂 bool willPlayBackgroundMusic(); //返回是否正在播放背景音樂 //注意:暫停也算正在播放,只有停止了才算未播放。 bool isBackgroundMusicPlaying(); //設(shè)置音量,取值范圍0~1.0 //查看了內(nèi)部源碼,發(fā)現(xiàn)音量的設(shè)置沒有實現(xiàn),即音量永遠是1.0 float getBackgroundMusicVolume(); void setBackgroundMusicVolume(float volume); //
5、音效的函數(shù)
相關(guān)操作:預加載、播放、停止、暫停、恢復、卸載,以及設(shè)置音量等。
// void preloadEffect('音樂路徑const char*'); //預加載 unsigned int playEffect('音樂路徑const char*', bool bLoop = false); //播放,返回該音效的ID。是否循環(huán) void stopEffect(unsigned int nSoundId); //停止指定ID的音效 void stopAllEffects(); //停止所有音效 void pauseEffect(unsigned int nSoundId); //暫停指定ID的音效 void pauseAllEffects(); //暫停所有音效 void resumeEffect(unsigned int nSoundId); //恢復指定ID的音效 void resumeAllEffects(); //恢復所有音效 void unloadEffect(const char* pszFilePath); //卸載音效資源 //設(shè)置音量,取值范圍0~1.0 //查看了內(nèi)部源碼,發(fā)現(xiàn)音量的設(shè)置沒有實現(xiàn),即音量永遠是1.0 float getEffectsVolume(); void setEffectsVolume(float volume); //
6、關(guān)于預加載
加載音樂和音效通常是一個耗時的過程,為了防止由即時加載產(chǎn)生的延遲導致實際播放與游戲不協(xié)調(diào)的現(xiàn)象發(fā)生,在播放音效和背景音樂之前,記得要預加載音樂文件preload。另外需要根據(jù)不同的平臺,選擇不同的預加載音樂格式。
具體操作如下:
其中MUSIC_FILE就是音樂文件相對Resources文件夾的相對路徑下的文件名。
// /** * 根據(jù)平臺選擇音樂音效的格式 */ //音效文件 //Android平臺只支持OGG的音效格式 #if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) #define EFFECT_FILE "music/effect2.ogg" #elif( CC_TARGET_PLATFORM == CC_PLATFORM_MARMALADE) #define EFFECT_FILE "music/effect1.raw" #else #define EFFECT_FILE "music/effect1.wav" #endif //音樂文件 #if (CC_TARGET_PLATFORM == CC_PLATFORM_WIN32) #define MUSIC_FILE "music/music.mid" #elif (CC_TARGET_PLATFORM == CC_PLATFORM_BLACKBERRY || CC_TARGET_PLATFORM == CC_PLATFORM_LINUX ) #define MUSIC_FILE "music/background.ogg" #elif (CC_TARGET_PLATFORM == CC_PLATFORM_WP8) #define MUSIC_FILE "music/background.wav" #else #define MUSIC_FILE "music/background.mp3" #endif /** * 預加載音樂音效 */ //加載背景音樂 SimpleAudioEngine::sharedEngine()->preloadBackgroundMusic(MUSIC_FILE); //加載音效 SimpleAudioEngine::sharedEngine()->preloadBackgroundMusic(EFFECT_FILE); //
7、關(guān)于音量調(diào)節(jié)
我在測試調(diào)節(jié)音量大小的時候,驚人的發(fā)現(xiàn):cocos2dx中的音量設(shè)置沒有實現(xiàn),即使你設(shè)置了音量大小也沒用,它永遠都是1.0。所以要想調(diào)節(jié)音量大小,還是通過設(shè)置系統(tǒng)的音量吧……
PS:在V3.x中已經(jīng)實現(xiàn)了音量的調(diào)節(jié)。
源碼如下:
// float SimpleAudioEngine::getBackgroundMusicVolume() { return 1.0; } void SimpleAudioEngine::setBackgroundMusicVolume(float volume) { } float SimpleAudioEngine::getEffectsVolume() { return 1.0; } void SimpleAudioEngine::setEffectsVolume(float volume) { } //
8、使用技巧
(1)通過SimpleAudioEngine::sharedEngine()獲取單例對象,然后調(diào)用相關(guān)函數(shù)。
(2)當退出程序時,記得要通過如下函數(shù)來釋放單例對象,釋放所有聲音資源。
// SimpleAudioEngine::sharedEngine()->end() //
(3)加載音樂和音效通常是一個耗時的過程,為了防止由即時加載產(chǎn)生的延遲導致實際播放與游戲不協(xié)調(diào)的現(xiàn)象發(fā)生,在播放音效和背景音樂之前,記得要預加載音樂文件preload。
【代碼實戰(zhàn)】
代碼來源于cocos2dx的官方項目TestCpp中。
1、資源文件
將音樂音效文件資源放在項目的“Resources\music”目錄下。
資源來自官方項目TestCpp中。
2、引入頭文件和命名空間
// #include "SimpleAudioEngine.h" using namespace CocosDenshion; //
3、預加載音樂音效
// /** * 根據(jù)平臺選擇音樂音效的格式 */ //音效文件 //Android平臺只支持OGG的音效格式 #if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) #define EFFECT_FILE "music/effect2.ogg" #elif( CC_TARGET_PLATFORM == CC_PLATFORM_MARMALADE) #define EFFECT_FILE "music/effect1.raw" #else #define EFFECT_FILE "music/effect1.wav" #endif //音樂文件 #if (CC_TARGET_PLATFORM == CC_PLATFORM_WIN32) #define MUSIC_FILE "music/music.mid" #elif (CC_TARGET_PLATFORM == CC_PLATFORM_BLACKBERRY || CC_TARGET_PLATFORM == CC_PLATFORM_LINUX ) #define MUSIC_FILE "music/background.ogg" #elif (CC_TARGET_PLATFORM == CC_PLATFORM_WP8) #define MUSIC_FILE "music/background.wav" #else #define MUSIC_FILE "music/background.mp3" #endif /** * 預加載音樂音效 */ //加載背景音樂 SimpleAudioEngine::sharedEngine()->preloadBackgroundMusic(MUSIC_FILE); //加載音效 SimpleAudioEngine::sharedEngine()->preloadBackgroundMusic(EFFECT_FILE); //
4、創(chuàng)建控制音樂音效的菜單按鈕
用菜單按鈕來控制音樂的播放、暫停、停止、恢復等。
// //創(chuàng)建控制音樂音效的菜單按鈕 std::string testItems[] = { "play background music", "stop background music", "pause background music", "resume background music", "rewind background music", "is background music playing", "play effect", "play effect repeatly", "stop effect", "pause effect", "resume effect", "pause all effects", "resume all effects", "stop all effects", "unload effect", "add background music volume", "sub background music volume", "add effects volume", "sub effects volume" }; //創(chuàng)建菜單 CCMenu* pMenu = CCMenu::create(); pMenu->setContentSize(CCSizeMake(480,1000)); for (int i = 0; i < 19; ++i) { CCLabelTTF* label = CCLabelTTF::create(testItems[i].c_str(), "Arial", 24); CCMenuItemLabel* pMenuItem = CCMenuItemLabel::create(label, this, menu_selector(HelloWorld::menuCallback)); pMenuItem->setPosition( ccp(mysize.width/2, 1000 - (i+1)*50 ) ); pMenu->addChild(pMenuItem, 0, i); } //將菜單作為容器,放入滾動視圖中 CCScrollView* scrollView = CCScrollView::create(CCSizeMake(480, 320), pMenu); scrollView->setDirection(kCCScrollViewDirectionVertical); scrollView->setPosition(CCPointZero); pMenu->setPosition( ccp(0, 320-1000) ); this->addChild(scrollView); //
5、編寫菜單按鈕回調(diào)函數(shù)
根據(jù)點擊的菜單項Tag,來控制音樂音效。
// void HelloWorld::menuCallback(CCObject* sender) { //獲取菜單按鈕編號 int idx = ((CCMenuItem*)sender)->getTag(); switch(idx) { //音樂控制 case 0: SimpleAudioEngine::sharedEngine()->playBackgroundMusic(MUSIC_FILE, true); break; //播放音樂,循環(huán) case 1: SimpleAudioEngine::sharedEngine()->stopBackgroundMusic(); break; //停止音樂 case 2: SimpleAudioEngine::sharedEngine()->pauseBackgroundMusic(); break; //暫停音樂 case 3: SimpleAudioEngine::sharedEngine()->resumeBackgroundMusic(); break; //恢復音樂 case 4: SimpleAudioEngine::sharedEngine()->rewindBackgroundMusic(); break; //重播音樂 case 5: if (SimpleAudioEngine::sharedEngine()->isBackgroundMusicPlaying()) //是否正在播放背景音樂 { CCLOG("background music is playing"); } else { CCLOG("background music is not playing"); } break; //音效控制 case 6: m_soundID = SimpleAudioEngine::sharedEngine()->playEffect(EFFECT_FILE); break; //播放音效,不循環(huán) case 7: m_soundID = SimpleAudioEngine::sharedEngine()->playEffect(EFFECT_FILE, true); break; //播放音效,循環(huán) case 8: SimpleAudioEngine::sharedEngine()->stopEffect(m_soundID); break; //停止指定ID的音效 case 9: SimpleAudioEngine::sharedEngine()->pauseEffect(m_soundID); break; //暫停指定ID的音效 case 10: SimpleAudioEngine::sharedEngine()->resumeEffect(m_soundID); break; //恢復指定ID的音效 case 11: SimpleAudioEngine::sharedEngine()->pauseAllEffects(); break; //暫停所有音效 case 12: SimpleAudioEngine::sharedEngine()->resumeAllEffects(); break; //恢復所有音效 case 13: SimpleAudioEngine::sharedEngine()->stopAllEffects(); break; //停止所有音效 case 14: SimpleAudioEngine::sharedEngine()->unloadEffect(EFFECT_FILE); break; //卸載音效 //音量控制 case 15: SimpleAudioEngine::sharedEngine()->setBackgroundMusicVolume(SimpleAudioEngine::sharedEngine()->getBackgroundMusicVolume() + 0.1f); break; case 16: SimpleAudioEngine::sharedEngine()->setBackgroundMusicVolume(SimpleAudioEngine::sharedEngine()->getBackgroundMusicVolume() - 0.1f); break; case 17: SimpleAudioEngine::sharedEngine()->setEffectsVolume(SimpleAudioEngine::sharedEngine()->getEffectsVolume() + 0.1f); break; case 18: SimpleAudioEngine::sharedEngine()->setEffectsVolume(SimpleAudioEngine::sharedEngine()->getEffectsVolume() - 0.1f); break; } } //
6、運行結(jié)果
聲音不是視覺效果,所以自己實現(xiàn)代碼后,玩耍去吧!