本文隶属于专题系列: cocos2dx基础篇

【唠叨】

    本节比较简单,主要讲讲cocos2dx引擎中的音乐音效SimpleAudioEngine

【致谢】

    http://gl.paea.cn/contents/f86d1f6e2a52e7ea.html

【小知识】

    单例类:说的通俗一点,它就是一个全局静态类。第一次调用时会创建一个全局静态对象,整个游戏的运行过程中会一直存在,全局都可以访问。

【Demo下载】

    http://down.51cto.com/data/1868000

【3.x】

    (1)获取单例:sharedEngine() 改为 getInstance()

    (2)实现了:音量的调节。

    (3)修改了播放音效 playEffect() 的参数:

//
	// 现在还不能完全支持所有参数,限制的功能如下:
	// 在Samsung Galaxy S2上如果启用了OpenSL那么pitch参数无效;
	// 在emscrippten, win32, marmalade上pitch/pan/gain参数无效
	virtual unsigned int playEffect	(
		const char* pszFilePath, // 音效文件的路径
		bool  bLoop = false,     // 是否循环播放,默认为false,不循环
		float pitch = 1.0f,      // 频率,正常情况下为1.0,在播放时也可以改变该值
		float pan = 0.0f,        // 声道,范围为-1到1,为-1时表示只有左声道,为1时表示只有右声道
		float gain = 1.0f        // 音量增益, 范围为0到1,默认值为1
	)
//

    (4)其他变化不大。

【SimpleAudioEngine】

    音乐音效是每个游戏中不可或缺的部分,一个好的声音会给玩家留下深刻的印象,当一听到游戏的声音,就会不自觉得说出游戏的名称来。就像《中国好声音》一样,笔者对那首《斑马,斑马》印象就非常深刻,当然唱这首歌的那个妹子也不错。i_f32.gif

    好了,不扯了,继续学习……

1、音乐音效介绍

    声音分为两类:背景音乐、音效。

    (1)背景音乐:一般是贯穿整个游戏的音乐,时间长、重复次数少。

    (2)音效:    一般是很短的那种声音特效,如砍杀、爆炸、走路等,短暂但使用比较频繁。

    cocos2dx是一个跨平台的游戏引擎,它支持多种声音格式(比如MP3、WAV等)。可是呢,对于不同的平台,声音的格式可不一定是统一的。这就需要大家根据不同的平台,选择合适的声音格式了。

    根据两种声音的特点,其采用的声音格式也有所不同。以下列出各平台所推荐的声音格式(当然并不是全部支持的格式,如IOS中背景音乐除了MP3和CAF外,还可以使用AAC、AMR等等)。

背景音乐 音效
Win32 MP3、MID、WAV MID、WAV
Android MP3、MID、WAV OGG
IOS MP3、CAF CAF

    由此可见,背景音乐最适合的选择是MP3格式。虽然音效也可以使用MP3格式,但是MP3是一种有损的压缩格式,而音效多数是短暂而快速的声响,有损的压缩方式可能导致有些采样音源消失,故音效不推荐使用MP3格式。而每个平台的音效格式均不相同,故需要根据不同平台,选用合适的格式。

2、SimpleAudioEngine

    cocos2dx为我们提供了声音模块CocosDenshion。而其中有个SimpleAudioEngine类,是我们学习研究的对象。

    使用SimpleAudioEngine时需要引入头文件和命名空间:

//
	#include "SimpleAudioEngine.h"
	using namespace CocosDenshion;
//

    SimpleAudioEngine和CCDirector一样,也是一个单例类。说的通俗一点,它就是一个全局静态类。第一次调用时会创建一个全局静态对象,整个游戏的运行过程中会一直存在,全局都可以访问。

3、获取单例对象

    SimpleAudioEngine的单例对象获取方法:

//
	//通过SimpleAudioEngine::sharedEngine()获得
	static SimpleAudioEngine* sharedEngine();
//

4、背景音乐的函数

    相关操作:预加载、播放、停止、暂停、恢复、重播,以及设置音量等。

//
	void preloadBackgroundMusic('音乐路径const char*');                  //预加载
	void playBackgroundMusic('音乐路径const char*', bool bLoop = false); //播放,是否循环,默认不循环
	void stopBackgroundMusic(bool bReleaseData = false);                 //停止,是否释放音乐资源
	void pauseBackgroundMusic();                                         //暂停
	void resumeBackgroundMusic();                                        //恢复
	void rewindBackgroundMusic();                                        //重播
	//返回是否将要播放背景音乐
	bool willPlayBackgroundMusic();
	//返回是否正在播放背景音乐
	//注意:暂停也算正在播放,只有停止了才算未播放。
	bool isBackgroundMusicPlaying(); 
	//设置音量,取值范围0~1.0
	//查看了内部源码,发现音量的设置没有实现,即音量永远是1.0
	float getBackgroundMusicVolume();
	void setBackgroundMusicVolume(float volume);
//

5、音效的函数

    相关操作:预加载、播放、停止、暂停、恢复、卸载,以及设置音量等。

//
	void preloadEffect('音乐路径const char*');                          //预加载
	unsigned int playEffect('音乐路径const char*', bool bLoop = false); //播放,返回该音效的ID。是否循环
	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);                         //卸载音效资源
	//设置音量,取值范围0~1.0
	//查看了内部源码,发现音量的设置没有实现,即音量永远是1.0
	float getEffectsVolume();
	void setEffectsVolume(float volume);
//

6、关于预加载

    加载音乐和音效通常是一个耗时的过程,为了防止由即时加载产生的延迟导致实际播放与游戏不协调的现象发生,在播放音效和背景音乐之前,记得要预加载音乐文件preload。另外需要根据不同的平台,选择不同的预加载音乐格式。

    具体操作如下:

        其中MUSIC_FILE就是音乐文件相对Resources文件夹的相对路径下的文件名。

//
/**
 *		根据平台选择音乐音效的格式
 */
	//音效文件
	//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、关于音量调节

    我在测试调节音量大小的时候,惊人的发现:cocos2dx中的音量设置没有实现,即使你设置了音量大小也没用,它永远都是1.0t_0012.gif所以要想调节音量大小,还是通过设置系统的音量吧……

    PS:在V3.x中已经实现了音量的调节。

    源码如下:

//
	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()获取单例对象,然后调用相关函数。

    (2)当退出程序时,记得要通过如下函数来释放单例对象,释放所有声音资源。

//
	SimpleAudioEngine::sharedEngine()->end()
//

    (3)加载音乐和音效通常是一个耗时的过程,为了防止由即时加载产生的延迟导致实际播放与游戏不协调的现象发生,在播放音效和背景音乐之前,记得要预加载音乐文件preload。

【代码实战】

    代码来源于cocos2dx的官方项目TestCpp中。

1、资源文件

        将音乐音效文件资源放在项目的“Resources\music”目录下。

        资源来自官方项目TestCpp中。

wKioL1P9nPWiEaOJAAEAkw90kkE677.jpg

2、引入头文件和命名空间

//
	#include "SimpleAudioEngine.h"
	using namespace CocosDenshion;
//

3、预加载音乐音效

//
/**
 *		根据平台选择音乐音效的格式
 */
	//音效文件
	//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、创建控制音乐音效的菜单按钮

    用菜单按钮来控制音乐的播放、暂停、停止、恢复等。

//
	//创建控制音乐音效的菜单按钮
		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"
		};
	//创建菜单
		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、编写菜单按钮回调函数

    根据点击的菜单项Tag,来控制音乐音效。

//
	void HelloWorld::menuCallback(CCObject* sender)
	{
	//获取菜单按钮编号
		int idx = ((CCMenuItem*)sender)->getTag();
		switch(idx)
		{
	//音乐控制
		case 0: SimpleAudioEngine::sharedEngine()->playBackgroundMusic(MUSIC_FILE, true); break; //播放音乐,循环
		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; //播放音效,不循环
		case 7: m_soundID = SimpleAudioEngine::sharedEngine()->playEffect(EFFECT_FILE, true);  break; //播放音效,循环
		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、运行结果

        声音不是视觉效果,所以自己实现代码后,玩耍去吧!i_f01.gif

wKiom1P9qcnBzAD9AAD_vfjwE4Y376.jpg

你可能感兴趣的内容
MySQL 基础面试题 收藏,3609 浏览
Git简单入门教程 收藏,4457 浏览
0条评论

dexcoder

这家伙太懒了 <( ̄ ﹌  ̄)>
Owner