欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

cocos2d-x 3.x学习之声音系统

程序员文章站 2022-07-03 11:30:44
#include "cocos2d.h" #include "SimpleAudioEngine.h" #include "...
#include "cocos2d.h"
#include "SimpleAudioEngine.h"
#include "extensions/GUI/CCControlExtension/CCControlSlider.h"
USING_NS_CC;
using namespace CocosDenshion;
using namespace extension;
class AudioSlider;
class HelloWorld : public Layer{
private:
    //音效的id
    unsigned int _soundId;
    //调整背景音乐值和音效值的滑块
    AudioSlider *_sliderMusicVolume;
    AudioSlider *_sliderEffectsVolume;
    AudioSlider *_sliderPitch;
    AudioSlider *_sliderPan;
    AudioSlider *_sliderGain;
public:
    static Scene* createScene();
    virtual bool init();
    //背景音乐滑块响应函数
    void musicValueChanged(Ref* pSender,Control::EventType controlEvent);
    //音效滑块响应函数
    void effectsValueChanged(Ref* pSender,Control::EventType controlEvent);
    void menuCloseCallback(cocos2d::Ref* pSender);
    CREATE_FUNC(HelloWorld);
};
#include "HelloWorldScene.h"
// 根据不同平台选择不同的音效格式文件
#if (CC_TARGET_PLATFORM == CC_PLATFOR_ANDROID)
#define EFFECT_FILE        "effect2.ogg"
#elif( CC_TARGET_PLATFORM == CC_PLATFOR_MARMALADE)
#define EFFECT_FILE        "effect1.raw"
#else
#define EFFECT_FILE        "effect1.wav"
#endif
// 根据不同平台选择不同的背景音乐格式文件
#if (CC_TARGET_PLATFORM == CC_PLATFOR_WIN32)
#define MUSIC_FILE        "music.mid"
#elif (CC_TARGET_PLATFORM == CC_PLATFOR_BLACKBERRY || CC_TARGET_PLATFORM == CC_PLATFOR_LINUX )
#define MUSIC_FILE        "background.ogg"
#else
#define MUSIC_FILE        "background.mp3"
#endif
class Button : public Node{
public:
    //使用图片路径创建精灵
    static Button *createWithSprite(const char *filePath){
        auto b = new Button();
        if(b && !b->initSpriteButton(filePath)){
            delete b;
            b = NULL;
        }
        return b;
    }
    //使用文本创建精灵
    static Button *createWithText(const char *text){
        auto b = new Button();
        if(b && !b->initTextButton(text)){
            delete b;
            b = NULL;
        }
        return b;
    }
    //析构函数
    ~Button(){
    
    }
    //绑定的响应事件函数
    void onTriggered(const std::function &onTriggered){
        _onTriggered = onTriggered;
    }
private:
    Button():_child(NULL){
      //创建单点触摸事件监听器
        auto listener = EventListenerTouchOneByOne::create();
        listener->setSwallowTouches(true);
        listener->onTouchBegan = [=](Touch* touch,Event *event){
            const bool hits = touchHits(touch);
            if(hits)
                scaleButtonTo(0.9f);
            return hits;
        };
        //触摸结束,调用响应函数,同时缩放标签
        listener->onTouchEnded = [=](Touch *touch,Event *event){
            const bool hits = touchHits(touch);
            if(hits && _onTriggered)
                _onTriggered();
            scaleButtonTo(1);
        };
        //触摸取消。缩放标签
        listener->onTouchCancelled = [=](Touch *touch,Event *event){
            scaleButtonTo(1);
        };
        //添加场景优先事件监听器
        _eventDispatcher->addEventListenerWithSceneGraphPriority(listener,this);
    }
    //使用图片路径创建精灵
    bool initSpriteButton(const char *filePath){
        _child = Sprite::create(filePath);
        addChild(_child);
        return true;
    }
    //使用文本创建精灵
    bool initTextButton(const char *text){
        _child = Label::createWithSystemFont(text,"Arial", 32);
        addChild(_child);
        return true;
    }
    //判断触摸位置是否在标签之内
    bool touchHits(Touch *touch){
        const Rect area(0,0,_child->getContentSize().width,_child->getContentSize().height);
        return area.containsPoint(_child->convertToNodeSpace(touch->getLocation()));
    }
    //缩放标签动作
    void scaleButtonTo(float scale){
        auto action = ScaleTo::create(0.1f, scale);
        action->setTag(900);
        stopActionByTag(900);
        runAction(action);
    }
    Node *_child;
    std::function _onTriggered;
};
//自定义音量调节类
class AudioSlider : public Node{
  //create函数,如果init函数调用出错则回收对象
public:
    static AudioSlider *create(){
        auto ret = new AudioSlider();
        if(ret && !ret->init()){
            delete ret;
            ret = NULL;
        }
        return ret;
    }
    //返回滑块当前值
    float getValue()const{
        return _slider->getValue();
    }
    void setValue(float minValue,float maxValue,float value){
      //设置音量滑块的范围最小值,最大值和当前值
        _slider->setMinimumValue(minValue);
        _slider->setMaximumValue(maxValue);
        _slider->setValue(value);
        //创建滑块上面显示的最小值和最大值的标签
        char buffer[32];
        sprintf(buffer,"%.2f",minValue);
        _lblMinValue = Label::createWithSystemFont(buffer,"Arial",18);
        addChild(_lblMinValue);
        sprintf(buffer,"%.2f",maxValue);
        _lblMaxValue = Label::createWithSystemFont(buffer,"Arial",18);
        addChild(_lblMaxValue);
    }
    //设置滑块、最小值标签、最大值标签位置
    void setSliderPosition(float x,float y){
        Size visibleSize = Director::getInstance()->getVisibleSize();
        _slider->setPosition(visibleSize.width * x,visibleSize.height * y);
        _lblMinValue->setPosition(visibleSize.width * (x - 0.1),visibleSize.height * (y + 0.05));
        _lblMaxValue->setPosition(visibleSize.width * (x + 0.1),visibleSize.height * (y + 0.05));
        
    }
    //返回滑块对象
    ControlSlider* getSlider(){
        return _slider;
    }
private:
    bool init(){
        _slider = ControlSlider::create("sliderTrack.png","sliderProgress.png","sliderThumb.png");
        addChild(_slider);
        return true;
    }
    ControlSlider *_slider;//调整滑块
    Label *_lblMinValue;//最小音量
    Label *_lblMaxValue;//最大音量
};
Scene* HelloWorld::createScene(){
    auto scene = Scene::create();
    auto layer = HelloWorld::create();
    scene->addChild(layer);
    return scene;
}
bool HelloWorld::init(){
    if ( !Layer::init() ){
        return false;
    }
    Size visibleSize = Director::getInstance()->getVisibleSize();
    Vec2 origin = Director::getInstance()->getVisibleOrigin();
    auto closeItem = MenuItemImage::create(
                                           "CloseNormal.png",
                                           "CloseSelected.png",
                                           CC_CALLBACK_1(HelloWorld::menuCloseCallback, this));
    
	closeItem->setPosition(Vec2(origin.x + visibleSize.width - closeItem->getContentSize().width/2 ,
                                origin.y + closeItem->getContentSize().height/2));
    auto menu = Menu::create(closeItem, NULL);
    menu->setPosition(Vec2::ZERO);
    this->addChild(menu, 1);
    //预加载音乐和音效
    SimpleAudioEngine::getInstance()->preloadBackgroundMusic(MUSIC_FILE);
    SimpleAudioEngine::getInstance()->preloadEffect(EFFECT_FILE);
    //背景音乐控制标签
    auto lbMusic = Label::createWithSystemFont("背景音乐控制","Arial",32);
    lbMusic->setPosition(visibleSize.width * 0.25,visibleSize.height * 0.9);
    this->addChild(lbMusic);
    //播放背景音乐
    auto playMusic = Button::createWithText("播放");
    playMusic->onTriggered([]{
        SimpleAudioEngine::getInstance()->playBackgroundMusic(MUSIC_FILE);
    });
    playMusic->setPosition(visibleSize.width * 0.1,visibleSize.height * 0.8);
    this->addChild(playMusic);
    //停止背景音乐
    auto stopMusic = Button::createWithText("停止");
    stopMusic->onTriggered([]{
        SimpleAudioEngine::getInstance()->stopBackgroundMusic();
    });
    stopMusic->setPosition(visibleSize.width * 0.25,visibleSize.height * 0.8);
    this->addChild(stopMusic);
    //回访背景音乐
    auto rewinMusic = Button::createWithText("回放");
    rewinMusic->onTriggered([]{
        SimpleAudioEngine::getInstance()->rewindBackgroundMusic();
    });
    rewinMusic->setPosition(visibleSize.width * 0.40,visibleSize.height * 0.8);
    this->addChild(rewinMusic);
    //暂停背景音乐
    auto pauseMusic = Button::createWithText("暂停");
    pauseMusic->onTriggered([]{
        SimpleAudioEngine::getInstance()->pauseBackgroundMusic();
    });
    pauseMusic->setPosition(visibleSize.width * 0.10,visibleSize.height * 0.65);
    this->addChild(pauseMusic);
    //继续背景音乐
    auto resumeMusic = Button::createWithText("继续");
    resumeMusic->onTriggered([]{
        SimpleAudioEngine::getInstance()->resumeBackgroundMusic();
    });
    resumeMusic->setPosition(visibleSize.width * 0.25,visibleSize.height * 0.65);
    this->addChild(resumeMusic);
    //音效控制标签
    auto lblSound = Label::createWithSystemFont("音效控制","Arial",32);
    lblSound->setPosition(visibleSize.width * 0.75,visibleSize.height * 0.9);
    this->addChild(lblSound);
    //播放音效
    auto playEffect = Button::createWithText("播放");
    playEffect->onTriggered([this]{
        const float pitch = _sliderPitch->getValue();
        const float pan = _sliderPan->getValue();
        const float gain = _sliderGain->getValue();
        _soundId = SimpleAudioEngine::getInstance()->playEffect(EFFECT_FILE,false,pitch,pan,gain);
    });
    playEffect->setPosition(visibleSize.width * 0.6,visibleSize.height * 0.8);
    this->addChild(playEffect);
    //暂停音效
    auto pauseEffect = Button::createWithText("暂停");
    pauseMusic->onTriggered([this]{
        SimpleAudioEngine::getInstance()->pauseEffect(_soundId);
    });
    pauseEffect->setPosition(visibleSize.width * 0.75,visibleSize.height * 0.8);
    this->addChild(pauseEffect);
    //继续音效
    auto resumeEffect = Button::createWithText("继续");
    resumeEffect->onTriggered([this]{
        SimpleAudioEngine::getInstance()->resumeEffect(_soundId);
    });
    resumeEffect->setPosition(visibleSize.width * 0.9,visibleSize.height * 0.8);
    this->addChild(resumeEffect);
    //停止音效
    auto stopEffect = Button::createWithText("停止");
    stopEffect->onTriggered([this]{
        SimpleAudioEngine::getInstance()->stopEffect(_soundId);
    });
    stopEffect->setPosition(visibleSize.width * 0.6,visibleSize.height * 0.7);
    this->addChild(stopEffect);
    //循环播放音效
    auto playEffectInLoop = Button::createWithText("循环播放");
    playEffectInLoop->onTriggered([this]{
        const float pitch = _sliderPitch->getValue();
        const float pan = _sliderPan->getValue();
        const float gain = _sliderGain->getValue();
        _soundId = SimpleAudioEngine::getInstance()->playEffect(EFFECT_FILE,true,pitch,pan,gain);
    });
    playEffectInLoop->setPosition(visibleSize.width * 0.75,visibleSize.height * 0.70);
    this->addChild(playEffectInLoop);
    //暂停所有音效
    auto pauseAllEffect = Button::createWithText("暂停所有");
    pauseAllEffect->onTriggered([this]{
        SimpleAudioEngine::getInstance()->pauseAllEffects();
    });
    pauseAllEffect->setPosition(visibleSize.width * 0.55,visibleSize.height * 0.60);
    this->addChild(pauseAllEffect);
    //继续所有音效
    auto resumeAllEffect = Button::createWithText("继续所有");
    resumeAllEffect->onTriggered([this]{
        SimpleAudioEngine::getInstance()->resumeAllEffects();
    });
    resumeAllEffect->setPosition(visibleSize.width * 0.75,visibleSize.height * 0.60);
    this->addChild(resumeAllEffect);
    //停止所有音效
    auto stopAllEffect = Button::createWithText("停止所有");
    stopAllEffect->onTriggered([this]{
        SimpleAudioEngine::getInstance()->stopAllEffects();
    });
    stopAllEffect->setPosition(visibleSize.width * 0.92,visibleSize.height * 0.60);
    this->addChild(stopAllEffect);
    //音量调整标签
    auto lblMusicVolume = Label::createWithSystemFont("音量","Arial",24);
    lblMusicVolume->setPosition(visibleSize.width * 0.08,visibleSize.height * 0.45);
    this->addChild(lblMusicVolume);
    //音量大小调整滑块
    _sliderMusicVolume = AudioSlider::create();
    _sliderMusicVolume->setValue(0.00f,1.00f, 1.0f);
    _sliderMusicVolume->setSliderPosition(0.28,0.45);
    //绑定音量事件处理函数,当滑块被拖动时被调用
    _sliderMusicVolume->getSlider()->addTargetWithActionForControlEvents(this, cccontrol_selector(HelloWorld::musicValueChanged),Control::EventType::VALUE_CHANGED);
    this->addChild(_sliderMusicVolume);
    //音效调整标签
    auto lblEffectsVolume = Label::createWithSystemFont("音效","Arial", 24);
    lblEffectsVolume->setPosition(visibleSize.width * 0.60,visibleSize.height * 0.45);
    this->addChild(lblEffectsVolume);
    //音效大小调整滑块
    _sliderEffectsVolume = AudioSlider::create();
    _sliderEffectsVolume->setValue(0.00f, 1.00f, 1.0f);
    _sliderEffectsVolume->setSliderPosition(0.80,0.45);
    //绑定音量事件处理函数,当滑块被拖动时被调用
    _sliderEffectsVolume->getSlider()->addTargetWithActionForControlEvents(this, cccontrol_selector(HelloWorld::effectsValueChanged),Control::EventType::VALUE_CHANGED);
    this->addChild(_sliderEffectsVolume);
    //高音调整标签
    auto lblPltich = Label::createWithSystemFont("高音","Arial",24);
    lblPltich->setPosition(visibleSize.width * 0.60,visibleSize.height * 0.35);
    this->addChild(lblPltich);
    //高音大小调整滑块
    _sliderPitch = AudioSlider::create();
    _sliderPitch->setValue(-0.50f, 2.00f, 1.0f);
    _sliderPitch->setSliderPosition(0.85, 0.35);
    this->addChild(_sliderPitch);
    //立体效果调整标签
    auto lblPan = Label::createWithSystemFont("立体效果","Arial", 24);
    lblPan->setPosition(visibleSize.width * 0.60,visibleSize.height * 0.25);
    this->addChild(lblPan);
    //立体效果调整滑块
    _sliderPan = AudioSlider::create();
    _sliderPan->setValue(-1.00f, 1.00f, 0.0f);
    _sliderPan->setSliderPosition(0.80, 0.25);
    this->addChild(_sliderPan);
    //音量调整标签
    auto lblGain = Label::createWithSystemFont("音量","Arial",24);
    lblGain->setPosition(visibleSize.width * 0.60,visibleSize.height * 0.15);
    this->addChild(lblGain);
    //音量调整滑块
    _sliderGain = AudioSlider::create();
    _sliderGain->setValue(0.00f, 1.00f, 1.0f);
    _sliderGain->setSliderPosition(0.80, 0.15);
    this->addChild(_sliderGain);
    return true;
}
void HelloWorld::musicValueChanged(Ref *pSender, Control::EventType controlEvent){
  //将pSender类型转换成拖动滑块ControlSlider
    ControlSlider* pSlider = dynamic_cast(pSender);
    //获取滑块当前值
    const float musicVolume = pSlider->getValue();
    //设置背景音乐值
    SimpleAudioEngine::getInstance()->setBackgroundMusicVolume(musicVolume);
    
}
void HelloWorld::effectsValueChanged(Ref *pSender, Control::EventType controlEvent){
    ControlSlider* pSlider = dynamic_cast(pSender);
    const float effectVolume = pSlider->getValue();
    SimpleAudioEngine::getInstance()->setEffectsVolume(effectVolume);
}
void HelloWorld::menuCloseCallback(Ref* pSender)
{
#if (CC_TARGET_PLATFORM == CC_PLATFORM_WP8) || (CC_TARGET_PLATFORM == CC_PLATFORM_WINRT)
	MessageBox("You pressed the close button. Windows Store Apps do not implement a close button.","Alert");
    return;
#endif

    Director::getInstance()->end();

#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
    exit(0);
#endif
}

cocos2d-x 3.x学习之声音系统