【amazing cocos2d-x 3.0之十九】游戏的背景音乐和音效

玩游戏的时候,背景音乐和音效能够使一款游戏增添不少色彩。

背景音乐:时间相对比较长,同一时间内只能播放一首背景音乐。

音效:时间相对比较短,同一时间内可以播放多个音效。

不管是音乐还是音效,cocos2d-x中都采用SimpleAudioEngine类实现跨平台的声音引擎。


1. 游戏背景音乐


1.1 背景音乐在不同平台下所支持的声音

关于背景音乐,cocos2d-x 在不同平台下所支持的格式如下:

平台名称                   支持类型
Android                android.media.MediaPlayer类支持的格式,包括MP3、WAV和3GP
iOS                       cocos2d-iPhone中cocosDenshion支持的类型,推荐MP3和CAF
Win32                  MID和WAV

1.2 背景音乐SimpleAudioEngine类常用的函数

函数名                                                  返回类型                 描述
preloadBackgroundMusic                    空                    预加载背景音乐
playBackgroundMusic                           空                   播放背景音乐
stopBackgroundMusic                          空                   停止背景音乐
pauseBackgroundMusic                      空                   暂停背景音乐
resumeBackgroundMusic                   空                   重新开始背景音乐
rewindBackgroundMusic                     空                   回放背景音乐
willPlayBackgroundMusic                   布尔型            是否会播放背景音乐
isBackgroundMusicPlaying                布尔型            是否正播放背景音乐
getBackgroundMusicVolume             浮点型             获得背景音乐音量
setBackgroundMusicVolume              空                    设置背景音乐音量


2. 游戏音效


2.1 音效在不同平台下所支持的音效格式

平台名称                  支持类型
Android           对应OGG格式支持最好,同时支持WAV格式
iOS                  cocos2d-iPhone中cocosDenshion支持的类型,推荐CAF
Win32             MID和WAV


2.2 音效SimepleAudioEngine类常用的函数

函数名                              返回类型       描述
getEffectsVolume          浮点型          获得音效音量
setEffectsVolume           空                设置音效音量
playEffect                         整型             播放音效,参数为文件路径和是否循环
pauseEffect                     空                暂停音效,参数为播放时获得的ID号
pauseAllEffects              空                 暂停所有音效
resumeEffect                  空                 开始音效,参数为播放时获得的ID号
resumeAllEffects           空                开始所有音效
stopEffect                        空                停止音效,参数为播放时获得的ID号
stopAllEffects                 空                 停止所有音效
preloadEffect                  空                 预加载音效
unloadEffect                   空                 将预加载的音效从缓存中删除


备注:预加载音乐和音效能够提高程序的执行效率,但是这样也会增加内存的占用。所以,在实际使用时,要根据项目特点来平衡效率和内存压力的问题。


3. 实例代码


相信源码就是最好的教材了,以下实例来自源码。

运行TestCpp,打开CocosDenshionTest,界面如下:



你可以一个个试试,然后再品尝以下原滋原味的代码,相信会有不少的收获。源码如下:

CocosDenshionTest.h

#ifndef __COCOS_DENSHION_TEST__
#define __COCOS_DENSHION_TEST__

#include "../testBasic.h"

class CocosDenshionTest : public CCLayer
{
public:
    CocosDenshionTest(void);
    ~CocosDenshionTest(void);

    void menuCallback(CCObject * pSender);
    virtual void ccTouchesMoved(CCSet *pTouches, CCEvent *pEvent);
    virtual void ccTouchesBegan(CCSet *pTouches, CCEvent *pEvent);
    virtual void onExit();

private:
    CCMenu* m_pItmeMenu;
    CCPoint m_tBeginPos;
    int m_nTestCount;
    unsigned int m_nSoundId;
};

class CocosDenshionTestScene : public TestScene
{
public:
    virtual void runThisTest();
};

#endif //__COCOS_DENSHION_TEST__

CocosDenshionTest.cpp

#include "CocosDenshionTest.h"
#include "cocos2d.h"
#include "SimpleAudioEngine.h"

// android effect only support ogg
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
    #define EFFECT_FILE        "effect2.ogg"
#elif( CC_TARGET_PLATFORM == CC_PLATFORM_MARMALADE)
    #define EFFECT_FILE        "effect1.raw"
#else
    #define EFFECT_FILE        "effect1.wav"
#endif // CC_PLATFORM_ANDROID

#if (CC_TARGET_PLATFORM == CC_PLATFORM_WIN32)
    #define MUSIC_FILE        "music.mid"
#elif (CC_TARGET_PLATFORM == CC_PLATFORM_BLACKBERRY || CC_TARGET_PLATFORM == CC_PLATFORM_LINUX )
    #define MUSIC_FILE        "background.ogg"
#elif (CC_TARGET_PLATFORM == CC_PLATFORM_WP8)
    #define MUSIC_FILE        "background.wav"
#else
    #define MUSIC_FILE        "background.mp3"
#endif // CC_PLATFORM_WIN32

USING_NS_CC;
using namespace CocosDenshion;

#define LINE_SPACE          40

CocosDenshionTest::CocosDenshionTest()
: m_pItmeMenu(NULL),
m_tBeginPos(CCPointZero),
m_nSoundId(0)
{
    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",
        "unload effect",
        "add background music volume",
        "sub background music volume",
        "add effects volume",
        "sub effects volume",
        "pause effect",
        "resume effect",
        "pause all effects",
        "resume all effects",
        "stop all effects"
    };

    // add menu items for tests
    m_pItmeMenu = CCMenu::create();

    m_nTestCount = sizeof(testItems) / sizeof(testItems[0]);

    for (int i = 0; i < m_nTestCount; ++i)
    {
//#if (CC_TARGET_PLATFORM == CC_PLATFORM_MARMALADE)
//        CCLabelBMFont* label = CCLabelBMFont::create(testItems[i].c_str(),  "fonts/arial16.fnt");
//#else
        CCLabelTTF* label = CCLabelTTF::create(testItems[i].c_str(), "Arial", 24);
//#endif        
        CCMenuItemLabel* pMenuItem = CCMenuItemLabel::create(label, this, menu_selector(CocosDenshionTest::menuCallback));
        
        m_pItmeMenu->addChild(pMenuItem, i + 10000);
        pMenuItem->setPosition( ccp( VisibleRect::center().x, (VisibleRect::top().y - (i + 1) * LINE_SPACE) ));
    }

    m_pItmeMenu->setContentSize(CCSizeMake(VisibleRect::getVisibleRect().size.width, (m_nTestCount + 1) * LINE_SPACE));
    m_pItmeMenu->setPosition(CCPointZero);
    addChild(m_pItmeMenu);

    setTouchEnabled(true);

    // preload background music and effect
    SimpleAudioEngine::sharedEngine()->preloadBackgroundMusic( MUSIC_FILE );
    SimpleAudioEngine::sharedEngine()->preloadEffect( EFFECT_FILE );
    
    // set default volume
    SimpleAudioEngine::sharedEngine()->setEffectsVolume(0.5);
    SimpleAudioEngine::sharedEngine()->setBackgroundMusicVolume(0.5);
}

CocosDenshionTest::~CocosDenshionTest()
{
}

void CocosDenshionTest::onExit()
{
    CCLayer::onExit();

    SimpleAudioEngine::sharedEngine()->end();
}

void CocosDenshionTest::menuCallback(CCObject * pSender)
{
    // get the userdata, it's the index of the menu item clicked
    CCMenuItem* pMenuItem = (CCMenuItem *)(pSender);
    int nIdx = pMenuItem->getZOrder() - 10000;

    switch(nIdx)
    {
    // play background music
    case 0:

        SimpleAudioEngine::sharedEngine()->playBackgroundMusic(MUSIC_FILE, true);
        break;
    // stop background music
    case 1:
        SimpleAudioEngine::sharedEngine()->stopBackgroundMusic();
        break;
    // pause background music
    case 2:
        SimpleAudioEngine::sharedEngine()->pauseBackgroundMusic();
        break;
    // resume background music
    case 3:
        SimpleAudioEngine::sharedEngine()->resumeBackgroundMusic();
        break;
    // rewind background music
    case 4:
        SimpleAudioEngine::sharedEngine()->rewindBackgroundMusic();
        break;
    // is background music playing
    case 5:
        if (SimpleAudioEngine::sharedEngine()->isBackgroundMusicPlaying())
        {
            CCLOG("background music is playing");
        }
        else
        {
            CCLOG("background music is not playing");
        }
        break;
    // play effect
    case 6:
        m_nSoundId = SimpleAudioEngine::sharedEngine()->playEffect(EFFECT_FILE);
        break;
    // play effect
    case 7:
        m_nSoundId = SimpleAudioEngine::sharedEngine()->playEffect(EFFECT_FILE, true);
        break;
    // stop effect
    case 8:
        SimpleAudioEngine::sharedEngine()->stopEffect(m_nSoundId);
        break;
    // unload effect
    case 9:
        SimpleAudioEngine::sharedEngine()->unloadEffect(EFFECT_FILE);
        break;
        // add bakcground music volume
    case 10:
        SimpleAudioEngine::sharedEngine()->setBackgroundMusicVolume(SimpleAudioEngine::sharedEngine()->getBackgroundMusicVolume() + 0.1f);
        break;
        // sub backgroud music volume
    case 11:
        SimpleAudioEngine::sharedEngine()->setBackgroundMusicVolume(SimpleAudioEngine::sharedEngine()->getBackgroundMusicVolume() - 0.1f);
        break;
        // add effects volume
    case 12:
        SimpleAudioEngine::sharedEngine()->setEffectsVolume(SimpleAudioEngine::sharedEngine()->getEffectsVolume() + 0.1f);
        break;
        // sub effects volume
    case 13:
        SimpleAudioEngine::sharedEngine()->setEffectsVolume(SimpleAudioEngine::sharedEngine()->getEffectsVolume() - 0.1f);
        break;
    case 14:
        SimpleAudioEngine::sharedEngine()->pauseEffect(m_nSoundId);
        break;
    case 15:
        SimpleAudioEngine::sharedEngine()->resumeEffect(m_nSoundId);
        break;
    case 16:
        SimpleAudioEngine::sharedEngine()->pauseAllEffects();
        break;
    case 17:
        SimpleAudioEngine::sharedEngine()->resumeAllEffects();
        break;
    case 18:
        SimpleAudioEngine::sharedEngine()->stopAllEffects();
        break;
    }
    
}

void CocosDenshionTest::ccTouchesBegan(CCSet *pTouches, CCEvent *pEvent)
{
    CCSetIterator it = pTouches->begin();
    CCTouch* touch = (CCTouch*)(*it);

    m_tBeginPos = touch->getLocation();    
}

void CocosDenshionTest::ccTouchesMoved(CCSet *pTouches, CCEvent *pEvent)
{
    CCSetIterator it = pTouches->begin();
    CCTouch* touch = (CCTouch*)(*it);

    CCPoint touchLocation = touch->getLocation();
    float nMoveY = touchLocation.y - m_tBeginPos.y;

    CCPoint curPos  = m_pItmeMenu->getPosition();
    CCPoint nextPos = ccp(curPos.x, curPos.y + nMoveY);

    if (nextPos.y < 0.0f)
    {
        m_pItmeMenu->setPosition(CCPointZero);
        return;
    }

    if (nextPos.y > ((m_nTestCount + 1)* LINE_SPACE - VisibleRect::getVisibleRect().size.height))
    {
        m_pItmeMenu->setPosition(ccp(0, ((m_nTestCount + 1)* LINE_SPACE - VisibleRect::getVisibleRect().size.height)));
        return;
    }

    m_pItmeMenu->setPosition(nextPos);
    m_tBeginPos = touchLocation;
}

void CocosDenshionTestScene::runThisTest()
{
    CCLayer* pLayer = new CocosDenshionTest();
    addChild(pLayer);
    pLayer->autorelease();

    CCDirector::sharedDirector()->replaceScene(this);
}



  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值