dionysosLai(906391500@qq.com) 2014/12/25
Cocos2dx使用的是一个比较简单、粗糙的语音系统,从语音系统名字SimpleAudioEngine,即可看出来这个系统本身没有多大的复杂难度,因此使用音效系统时,会有一些比较隐晦的细节,需要我们在开发时特别注意。
语音和音效的区别
一般来说,在cocos2dx中,只用两种声音通道模式,一个backmuscic,另一个是effectmusic。前者用来播放背景音乐,后者一般用来播放音效。背景音和音效的区别在于前者比较大,后者比较小。同时背景音提供检测是否播放完毕功能,而音效没有。如果,在游戏中,需要另外检测声音播放问题,则只能自己修改引擎代码,添加一个语音通道。在我们公司开发项目中,由于游戏要时刻检测声音播放问题,因此添加了一个名为voice通道,用来专门播放人物声音。
另一方面,在预加载方面,背景音不需要预加载,只有音效才需要预加载。同时如果预加载两个背景音,前一个背景音内存会自动抛弃掉,这个问题在音效方面则没有。
音效预加载问题
音效是肯定会加载到内存中的,及时未使用preLoadEffect接口预加载音效,在我们第一次播放音效时,同样会将该音效加载加载到内存中,然后再播放该音效。这也就是为什么有时候游戏第一次音效没有播放出来,或者第一次播放音效时,游戏明显卡顿一下。
但另一方面,预加载音效是会消耗一定时间的,不可一次性加载过多。一般是进入该场景,才将该场景音效加载进来。退出该场景时,可将音效内存释放。
同时,在加载音效时,或者没有加载音效时,在播放该音效的瞬间,游戏进入后台,十分有可能将系统挂掉,重启。这是一个必然的bug。这个问题,引起的原因,应该是在加载音效过程中,执行了pauseAllEffects。相信大家appDelegate代码均如下:
// This function will be called when the app is inactive. When comes a phone call,it's be invoked too void AppDelegate::applicationDidEnterBackground() { CCDirector::sharedDirector()->stopAnimation(); // if you use SimpleAudioEngine,it must be pause SimpleAudioEngine::sharedEngine()->pauseBackgroundMusic(); SimpleAudioEngine::sharedEngine()->pauseVoice(); SimpleAudioEngine::sharedEngine()->pauseAllEffects(); } // this function will be called when the app is active again void AppDelegate::applicationWillEnterForeground() { CCDirector::sharedDirector()->startAnimation(); // if you use SimpleAudioEngine,it must resume here SimpleAudioEngine::sharedEngine()->resumeBackgroundMusic(); SimpleAudioEngine::sharedEngine()->resumeVoice(); SimpleAudioEngine::sharedEngine()->resumeAllEffects(); }
这个问题,基本不可避免,或者目前无力解决这个问题,只能是尽量避免。
循环音效播放问题
有时候,有些音效需要循环播放。循环播放音效时,在PC端会引起各种各样的问题,例如不能及时关闭,游戏退到后台,又进入前台,以前暂停过的循环音效,又会重新播放,因此循环音效调试,一定要在移动端。
循环音效的播放,有时候会播放不出来,这个问题很奇怪,一般来说,如果要播放循环音效,该音效的大小,最好在40k以内。
另一方面循环音效需要记录该音效的播放ID值,在win32端,改音效ID值是根据音效路径pszFilePath计算得到,因此第一次播放A音效,第二次播放A音效,前后得到的ID值是一样的。而在移动端,每次播放音效,ID值都会自增+1,同时如果不预加载音效,第一次得到的音效ID值为0,这个很重要。这点,可以参考文章:http://post.justbilt.com/2013/11/28/cocos2dx_loop_sound/, 里面讲的细致到位。
播放多个音效问题
同时播放多个音效时,游戏会卡顿,及时时播放同一个音效,如果同时播放多个,会明显感觉游戏卡顿,而且音效不是一起播放的,会有明显的前后间隔。因此,避免同时播放多个音效,这也是为什么我曾在三消游戏中,不提倡使用每个物品消除都多一个音效问题,而是根据物品个数播放音效。比方消除物品数在3以下,播放A音效,消除物品数超过多少,播放B音效等。能够要求提供不同种类音效,是程序设计的一个要求。
音效资源释放问题
一般来说,游戏退出,结束整个程序,系统会将游戏内存释放掉。但是,对于声音内存,系统并不释放,需要我们主动释放,这里只需要在游戏退出时,添加一个简单的接口:CocosDenshion::SimpleAudioEngine::end();即可。很神奇吧,我也觉得。