Cocos2d-x3.3RC0 Cpp-test分析之NewAudioEngineDemo

1、.h文件

#ifndef __NewAudioEngineDemo__NewAudioEngineDemo__
#define __NewAudioEngineDemo__NewAudioEngineDemo__

#include "cocos2d.h"
#include "ui/CocosGUI.h"
#include "VisibleRect.h"
#include "audio/include/AudioEngine.h"

USING_NS_CC;
using namespace ui;

class NewAudioEngineDemo : public Scene
{
public:
    CREATE_FUNC(NewAudioEngineDemo);
    virtual bool init();
};

class BaseTest : public Layer
{
public:
    CREATE_FUNC(BaseTest);
    virtual bool init();
    virtual std::string title() const;//主标题
    virtual std::string subtitle() const;//副标题
    virtual void onExit() override;
    
    virtual void restartCallback(Ref* sender);//重新执行当前test
    virtual void nextCallback(Ref* sender);//下一个test
    virtual void backCallback(Ref* sender);//上一个test

    void menuCloseCallback(cocos2d::Ref* pSender);//关闭菜单回调函数
};

class AudioControlTest : public BaseTest
{
public:
    CREATE_FUNC(AudioControlTest);
    virtual ~AudioControlTest();
    virtual bool init();
    virtual void update(float dt);
    virtual std::string subtitle() const override;
private:
    int _audioID;
    bool _loopEnabled;
    float _volume;
    float _duration;
    float _timeRatio;
    
    void* _playItem;
    void* _timeSlider;
    bool _updateTimeSlider;

};

class PlaySimultaneouslyTest : public BaseTest
{
public:
    CREATE_FUNC(PlaySimultaneouslyTest);
    virtual ~PlaySimultaneouslyTest();
    virtual bool init();
    virtual std::string subtitle() const override;
private:
    static const int TEST_COUNT = 10;
    std::string _files[TEST_COUNT];
    void* _playItem;
    int _playingcount;
};

class AudioProfileTest : public BaseTest
{
public:
    CREATE_FUNC(AudioProfileTest);
    virtual bool init();
    virtual ~AudioProfileTest();
    virtual std::string subtitle() const override;
    virtual void update(float dt);
private:
    static const int FILE_COUNT = 2;
    std::string _files[FILE_COUNT];
    cocos2d::experimental::AudioProfile _audioProfile;
    int _audioCount;
    Label* _showLabel;
    float _time;
    float _minDelay;
    void* _timeSlider;
};
class InvalidAudioFileTest : public BaseTest
{
public:
    CREATE_FUNC(InvalidAudioFileTest);
    virtual bool init();
    virtual ~InvalidAudioFileTest();
    virtual std::string subtitle() const override;
};
class LargeAudioFileTest : public BaseTest
{
public:
    CREATE_FUNC(LargeAudioFileTest);
    virtual bool init();
    virtual ~LargeAudioFileTest();
    virtual std::string subtitle() const override;
};
#endif /* defined(__NewAudioEngineDemo__NewAudioEngineDemo__) */

2、.cpp文件

#include "NewAudioEngineDemo.h"
#include "platform/CCPlatformConfig.h"
#if CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID || CC_TARGET_PLATFORM == CC_PLATFORM_IOS || CC_TARGET_PLATFORM == CC_PLATFORM_MAC || CC_TARGET_PLATFORM == CC_PLATFORM_WIN32
using namespace cocos2d::experimental;


#define CL(__className__) [](){ return __className__::create();}
static int sceneIdx = -1;

static std::function<Layer*()> createFunctions[] =
{
    CL(AudioControlTest),CL(PlaySimultaneouslyTest),CL(AudioProfileTest),CL(InvalidAudioFileTest),CL(LargeAudioFileTest)};

#define MAX_LAYER    (sizeof(createFunctions) / sizeof(createFunctions[0]))

static Layer* nextAction()
{
    sceneIdx++;
    sceneIdx = sceneIdx % MAX_LAYER;
    
    auto layer = (createFunctions[sceneIdx])();
    return layer;
}

static Layer* backAction()
{
    sceneIdx--;
    int total = MAX_LAYER;
    if( sceneIdx < 0 )
        sceneIdx += total;
    
    auto layer = (createFunctions[sceneIdx])();
    return layer;
}

static Layer* restartAction()
{
    auto layer = (createFunctions[sceneIdx])();
    return layer;
}

//基类Layer
bool BaseTest::init()
{
    bool bRet = false;
    do{
        CC_BREAK_IF(!Layer::init());
        
        Size visibleSize = Director::getInstance()->getVisibleSize();
        Vec2 origin = Director::getInstance()->getVisibleOrigin();
        
        /////////////////////////////
        // 2. add a menu item with "X" image,which is clicked to quit the program
        //    you may modify it.
        
        // add a "close" icon to exit the progress. it's an autorelease object
        auto closeItem = MenuItemImage::create(
                                               "CloseNormal.png","CloseSelected.png",CC_CALLBACK_1(BaseTest::menuCloseCallback,this));
        closeItem->setPosition(Vec2(origin.x + visibleSize.width - closeItem->getContentSize().width/2,origin.y + visibleSize.height - closeItem->getContentSize().height/2));
        
        // create menu,it's an autorelease object
        auto menu1 = Menu::create(closeItem,NULL);
        menu1->setPosition(Vec2::ZERO);
        this->addChild(menu1,1);
        
        std::string str = title();
        const char * pTitle = str.c_str();
        TTFConfig ttfConfig("fonts/tahoma.ttf",35);
        auto label = Label::createWithTTF(ttfConfig,pTitle);
        addChild(label,9999);
        label->setPosition( Vec2(VisibleRect::center().x,VisibleRect::top().y - 30) );
        
        std::string strSubtitle = subtitle();
        if( ! strSubtitle.empty() )
        {
            ttfConfig.fontFilePath = "fonts/tahoma.ttf";
            ttfConfig.fontSize = 30;
            auto l = Label::createWithTTF(ttfConfig,strSubtitle.c_str());
            addChild(l,9999);
            l->setPosition( Vec2(VisibleRect::center().x,VisibleRect::top().y - 100) );
        }
        
        auto item1 = MenuItemFont::create("backCallback",CC_CALLBACK_1(BaseTest::backCallback,this) );
        auto item2 = MenuItemFont::create("restartCallback",CC_CALLBACK_1(BaseTest::restartCallback,this) );
        auto item3 = MenuItemFont::create("nextCallback",CC_CALLBACK_1(BaseTest::nextCallback,this) );
        
        auto menu = Menu::create(item1,item2,item3,NULL);
        
        menu->setPosition(Vec2::ZERO);
        item1->setPosition(Vec2(VisibleRect::center().x - item2->getContentSize().width*2,VisibleRect::bottom().y+item2->getContentSize().height/2));
        item2->setPosition(Vec2(VisibleRect::center().x,VisibleRect::bottom().y+item2->getContentSize().height/2));
        item3->setPosition(Vec2(VisibleRect::center().x + item2->getContentSize().width*2,VisibleRect::bottom().y+item2->getContentSize().height/2));
        
        addChild(menu,9999);
        
        bRet = true;
    }while(0);
    return bRet;
}

void BaseTest::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
}

//重新执行当前test
void BaseTest::restartCallback(cocos2d::Ref *sender)
{
    auto s = new (std::nothrow) NewAudioEngineDemo();
    s->addChild(restartAction());
    Director::getInstance()->replaceScene(s);
    s->release();
}
//下一个test
void BaseTest::nextCallback(cocos2d::Ref *sender)
{
    auto s = new (std::nothrow) NewAudioEngineDemo();
    s->addChild(nextAction());
    Director::getInstance()->replaceScene(s);
    s->release();
}
//上一个test
void BaseTest::backCallback(cocos2d::Ref *sender)
{
    auto s = new (std::nothrow) NewAudioEngineDemo();
    s->addChild(backAction());
    Director::getInstance()->replaceScene(s);
    s->release();
}
//onExit函数
void BaseTest::onExit()
{
    AudioEngine::stopAll();
    Layer::onExit();
}

std::string BaseTest::title() const
{
    return "NewAudioEngineDemo Test";
}

std::string BaseTest::subtitle() const
{
    return "";
}

//封装按钮
class TextButton : public cocos2d::Label
{
public:
    //静态创建函数
    static TextButton* create(const std::string& text,const std::function<void(TextButton*)>& onTriggered)
    {
        //如果非配内存失败,返回0
        auto ret = new(std::nothrow) TextButton();
        TTFConfig ttfconfig("fonts/arial.ttf",25);
        //创建成功,设置Label
        if(ret && ret->setTTFConfig(ttfconfig))
        {
            //设置内容
            ret->setString(text);
            //设置回调函数
            ret->_onTriggered = onTriggered;
            ret->autorelease();
            return ret;
        }
        delete ret;
        return nullptr;
    }
    //设置触摸响应
    void setEnabled(bool enabled)
    {
        _enabled = enabled;
        //如果没有触摸
        if(_enabled)
        {
            //设置Lable颜色为White
            this->setColor(Color3B::WHITE);
        }else{
            //如果已经触摸,设置颜色Gray
            this->setColor(Color3B::GRAY);
        }
    }
private:
    //构造函数,_enabled为true,_onTriggered为nullptr
    TextButton()
    :_enabled(true),_onTriggered(nullptr)
    {
        //注册监听事件
        auto listener = EventListenerTouchOneByOne::create();
        listener->setSwallowTouches(true);//事件禁止向下传递
        //触摸事件类型
        listener->onTouchBegan = CC_CALLBACK_2(TextButton::onTouchBegan,this);
        listener->onTouchEnded = CC_CALLBACK_2(TextButton::onTouchEnded,this);
        listener->onTouchCancelled = CC_CALLBACK_2(TextButton::onTouchCancelled,this);
        //加入事件
        Director::getInstance()->getEventDispatcher()->addEventListenerWithSceneGraphPriority(listener,this);
    }
    //判断是否在触摸范围内
    bool touchHits(Touch* touch)
    {
        //将屏幕坐标转为节点坐标
        auto hitPos = this->convertToNodeSpace(touch->getLocation());
        //触摸点在节点坐标内,返回true,否则返回false
        if(hitPos.x >= 0 && hitPos.y >= 0 && hitPos.x <= _contentSize.width && hitPos.y <= _contentSize.height)
        {
            return true;
        }
        return false;
    }
    //触摸开始
    bool onTouchBegan(Touch* touch,Event* event)
    {
        //调用touchHit函数,返回true,在节点上
        auto hits = touchHits(touch);
        if(hits)
        {
            scaleButtonTo(0.95f);//执行按钮缩放
        }
        return hits;//响应后面触摸事件
    }
    //触摸结束
    void onTouchEnded(Touch* touch,Event* event)
    {
        //如果没有触摸
        if(_enabled)
        {
            //判断是否在节点上
            auto hits = touchHits(touch);
            //如果在节点上,且响应事件不为nullptr
            if(hits && _onTriggered)
            {
                //调用响应事件
                _onTriggered(this);
            }
        }
        //执行按钮缩放
        scaleButtonTo(1);
    }
    //触摸取消
    void onTouchCancelled(Touch* touch,Event* event)
    {
        scaleButtonTo(1);
    }
    //缩放操作
    void scaleButtonTo(float scale)
    {
        auto action = ScaleTo::create(0.05f,scale);
        action->setTag(10000);
        stopActionByTag(10000);
        runAction(action);
    }
    //事件回调函数指针
    std::function<void(TextButton*)> _onTriggered;
    bool _enabled;//是否触摸
};

//封装进度条类,拖动进度条响应事件
class SliderEx : public Slider
{
public:
    //触摸事件,按下,移动,抬起,取消
    enum class TouchEvent
    {
        DOWN,MOVE,UP,CANCEL
    };
    //定义函数函数指针
    typedef std::function<void(SliderEx*,float,TouchEvent)> ccSliderExCallback;
    //静态创建函数
    static SliderEx* create()
    {
        //std::nothrow分配内存失败返回0,必须包含头文件#include <new>
        auto ret = new(std::nothrow)SliderEx();
        if(ret && ret->init())
        {
            //初始化进度条
            ret->_callback = nullptr;
            ret->loadBarTexture("sliderTrack.png");
            ret->loadSlidBallTextures("sliderThumb.png","sliderThumb.png","");
            ret->loadProgressBarTexture("sliderProgress.png");
            ret->autorelease();
            return ret;
        }
        //如果分配内存失败,删除ret并置空
        CC_SAFE_DELETE(ret);
        return ret;
    }
    //设置回调函数
    void setCallBack(const ccSliderExCallback& callback){
        _callback = callback;
    }
    //设置进度比
    void setRatio(float ratio)
    {
        if(ratio > 1.0f)
        {
            ratio = 1.0f;
        }else if(ratio < 0.0f)
        {
            ratio = 0.0f;
        }
        
        _ratio = ratio;
        _percent = 100* _ratio;
        
        //设置进度条光标的位置,
        float dis = _barLength * _ratio;
        _slidBallRenderer->setPosition(dis,_contentSize.height/2.0f);
        
        //设置进度条已走过的进度
        if(_scale9Enabled)
        {
            //如果开启9宫格精灵,设置进度条已走过的进度比
            _progressBarRenderer->setPreferredSize(Size(dis,_progressBarTextureSize.height));
        }else{
            //如果没有开启9宫格精灵
            //首先获取进度条ProgressBar的精灵
            auto spriteRenderer = _progressBarRenderer->getSprite();
            //精灵不为空
            if(nullptr != spriteRenderer)
            {
                //获取精灵的Rect
                Rect rect = spriteRenderer->getTextureRect();
                rect.size.width = _progressBarTextureSize.width * _ratio;//设置获取精灵的Rect大小
                spriteRenderer->setTextureRect(rect,spriteRenderer->isTextureRectRotated(),rect.size);//设置ProgressBar精灵的Rect
            }
        }
    }
    //触摸开始事件
    virtual bool onTouchBegan(Touch* touch,Event* unusedEvent) override{
        //进度条开始触摸
        auto ret = Slider::onTouchBegan(touch,unusedEvent);
        //_callback不为空
        if(ret && _callback){
            _touchEvent = TouchEvent::DOWN;
            Vec2 nsp = convertToNodeSpace(_touchBeganPosition);//触摸点坐标转为节点坐标
            _ratio = nsp.x / _barLength;//取得进度比,当前触摸位置除以进度条的长度
            if(_ratio < 0.0f)
            {
                _ratio = 0.0f;
            }else if(_ratio > 1.0f)
            {
                _ratio = 1.0f;
            }
            _callback(this,_ratio,_touchEvent);//回调事件
        }
        return ret;
    }
    //移动触摸
    virtual void onTouchMoved(Touch* touch,Event* unusedEvent) override{
        _touchEvent = TouchEvent::MOVE;//设置触摸类型
        Slider::onTouchMoved(touch,unusedEvent);//Slider基类触摸
        Vec2 nsp = convertToNodeSpace(_touchMovePosition);//触摸点坐标转为节点坐标
        _ratio = nsp.x / _barLength;
        if(_ratio < 0.0f)
        {
            _ratio = 0.0f;
        }else if(_ratio > 1.0f)
        {
            _ratio = 1.0f;
        }
        if(_callback)
        {
            _callback(this,_touchEvent);//事件回调
        }
    }
    //取消触摸
    virtual void onTouchCancelled(Touch* touch,Event* unusedEvent) override
    {
        _touchEvent = TouchEvent::CANCEL;
        Slider::onTouchCancelled(touch,unusedEvent);
        if (_callback) {
            _callback(this,_touchEvent);//事件回调
        }
    }
    
private:
    TouchEvent _touchEvent;//触摸事件类型
    float _ratio;//进度比
    ccSliderExCallback _callback;//回调事件的指针函数
};
//基类Scene
bool NewAudioEngineDemo::init()
{
    bool bRet;
    do{
        CC_BREAK_IF(!Scene::init());
        //初始化AudioEngine
        CCASSERT(AudioEngine::lazyInit(),"Fail to initialize AudioEngine!");
        //初始化sceneIdx
        sceneIdx = -1;
        //执行nextAction,执行第一个test
        auto layer = nextAction();
        //加入NewAudioEngineDemo场景
        addChild(layer);
        //切换场景
        Director::getInstance()->replaceScene(this);

        bRet = true;
    }while(0);
    return bRet;
}

bool AudioControlTest::init()
{
    bool bRet = false;
    do{
        CC_BREAK_IF(!BaseTest::init());
        
        _audioID = AudioEngine::INVAILD_AUDIO_ID;
        //是否循环
        _loopEnabled = false;
        //音量大小
        _volume = 1.0f;
        //
        _duration = AudioEngine::TIME_UNKNOWN;
        //更新间隔
        _timeRatio = 0.0f;
        //更新进度条
        _updateTimeSlider = true;
        //字体路径
        std::string fontFilePath = "fonts/arial.ttf";
        //当前Size
        auto layerSize = this->getContentSize();
        //play按钮,第一个参数是按钮名称,第二个参数是回调函数,在触摸结束后响应
        auto playItem = TextButton::create("play",[&](TextButton* button)
        {
            //判断ID是否为INVAILD_AUTIO_ID
            if(_audioID == AudioEngine::INVAILD_AUDIO_ID)
            {
                //播放音乐,第一个参数音乐文件路径,第二个参数,是否循环播放,第三个参数,音量,跟进去发现函数返回一个int值,值为0
                _audioID = AudioEngine::play2d("background.mp3",_loopEnabled,_volume);
                log("_audioID = %d",_audioID);//打印0,即unordered_map的对象个数
                log("INVAILD_AUDIO_ID = %d",AudioEngine::INVAILD_AUDIO_ID);//打印-1
                //如果ID不等于AudioEngine::INVAILD_AUDIO_ID,执行以下代码
                if(_audioID != AudioEngine::INVAILD_AUDIO_ID)
                {
                    //设置按钮被按下,设置Lable字体颜色为灰色
                    button->setEnabled(false);
                    //如果音乐播放完毕的回调函数
                    AudioEngine::setFinishCallback(_audioID,[&](int id,const std::string& filePath)
                    {
                        //重新恢复ID值为-1
                        _audioID = AudioEngine::INVAILD_AUDIO_ID;
                        ((TextButton*)_playItem)->setEnabled(true);//设置按钮为非触摸状态,即没有被按下,按钮字体颜色为White
                        _timeRatio = 0.0f;//更新时间间隔为0
                        ((SliderEx*)_timeSlider)->setRatio(_timeRatio);//设置进度比
                    });
                }
            }
        });
        _playItem = playItem;//将当前playItem赋值给_playItem,这一步在初始化时执行,先于触摸playItem前执行
        playItem->setPosition(layerSize.width*0.3f,layerSize.height*0.7f);
        addChild(playItem);
        //停止按钮
        auto stopItem = TextButton::create("stop",[&](TextButton* button){
            if(_audioID != AudioEngine::INVAILD_AUDIO_ID)
            {
                AudioEngine::stop(_audioID);
                _audioID = AudioEngine::INVAILD_AUDIO_ID;
                ((TextButton*)_playItem)->setEnabled(true);//停止按钮按下,play按钮字体颜色变为White
            }
        });
        stopItem->setPosition(layerSize.width*0.7f,layerSize.height*0.7f);
        addChild(stopItem);
        //暂停按钮
        auto pauseItem = TextButton::create("pause",[&](TextButton* button){
            if(_audioID != AudioEngine::INVAILD_AUDIO_ID)
            {
                AudioEngine::pause(_audioID);
            }
        });
        pauseItem->setPosition(layerSize.width*0.3f,layerSize.height*0.6f);
        addChild(pauseItem);
        //恢复播放按钮
        auto resumeItem = TextButton::create("resume",[&](TextButton* button){
            if(_audioID != AudioEngine::INVAILD_AUDIO_ID)
            {
                AudioEngine::resume(_audioID);
            }
        });
        resumeItem->setPosition(layerSize.width*0.7f,layerSize.height*0.6f);
        addChild(resumeItem);
        //是否循环播放
        auto loopItem = TextButton::create("enable-loop",[&](TextButton* button){
            _loopEnabled = !_loopEnabled;//取非,使_loopEnabled循环
            if(_audioID != AudioEngine::INVAILD_AUDIO_ID)
            {
                AudioEngine::setLoop(_audioID,_loopEnabled);//设置是否循环
            }
            //设置循环播放按钮字体内容
            if(_loopEnabled)
            {
                button->setString("disable-loop");
            }else{
                button->setString("enable-loop");
            }
        });
        loopItem->setPosition(layerSize.width*0.3f,layerSize.height*0.5f);
        addChild(loopItem);
        
        //加载缓冲
        auto uncacheItem = TextButton::create("uncache",[&](TextButton* button){
            AudioEngine::uncache("background.mp3");
            _audioID = AudioEngine::INVAILD_AUDIO_ID;
            ((TextButton*)_playItem)->setEnabled(true);//设置play按钮为非触摸状态
        });
        uncacheItem->setPosition(layerSize.width*0.7f,layerSize.height*0.5f);
        addChild(uncacheItem);
        //声音进度条
        auto volumeSlider = SliderEx::create();
        volumeSlider->setPercent(100);
        volumeSlider->setCallBack([&](SliderEx* sender,float ratio,SliderEx::TouchEvent event){
            _volume = ratio;//获取音量值
            if(_audioID != AudioEngine::INVAILD_AUDIO_ID)
            {
                //设置音量
                AudioEngine::setVolume(_audioID,_volume);
            }
        });
        volumeSlider->setPosition(Vec2(layerSize.width*0.5f,layerSize.height*0.35f));
        addChild(volumeSlider);
        
        //时间进度条
        auto timeSlider = SliderEx::create();
        //参数引用类对象,参数传递在触摸事件中
        timeSlider->setCallBack([&](SliderEx* sender,SliderEx::TouchEvent event){
            switch (event) {
                case SliderEx::TouchEvent::MOVE:
                case SliderEx::TouchEvent::DOWN:
                    _updateTimeSlider = false;//按钮和移动状态下,不更新时间进度条
                    break;
                case SliderEx::TouchEvent::UP://抬起
                    if(_audioID != AudioEngine::INVAILD_AUDIO_ID && _duration != AudioEngine::TIME_UNKNOWN)
                    {
                        //设置当前时间进度条的进度
                        AudioEngine::setCurrentTime(_audioID,_duration*ratio);
                    }
                    break;
                case SliderEx::TouchEvent::CANCEL:
                    _updateTimeSlider = true;//取消动作,继续更新进度条
                    break;
                default:
                    break;
            }
        });
        timeSlider->setPosition(Vec2(layerSize.width*0.5f,layerSize.height*0.25f));
        addChild(timeSlider);
        _timeSlider = timeSlider;
        
        //音量标签
        auto volumeSliderPos = volumeSlider->getPosition();
        auto sliderSize = volumeSlider->getContentSize();
        auto volumeLabel = Label::createWithTTF("volume:",fontFilePath,20);
        volumeLabel->setAnchorPoint(Vec2::ANCHOR_MIDDLE_RIGHT);
        volumeLabel->setPosition(volumeSliderPos.x - sliderSize.width/2,volumeSliderPos.y);
        addChild(volumeLabel);
        //时间标签
        auto timeSliderPos = timeSlider->getPosition();
        auto timeLabel = Label::createWithTTF("time:",20);
        timeLabel->setAnchorPoint(Vec2::ANCHOR_MIDDLE_RIGHT);
        timeLabel->setPosition(timeSliderPos.x-sliderSize.width/2,timeSliderPos.y);
        addChild(timeLabel);
        //每0.1秒更新帧
        this->schedule(CC_CALLBACK_1(AudioControlTest::update,this),0.1f,"update_key");
        
        bRet = true;
    }while(0);
    return bRet;
}
void AudioControlTest::update(float dt)
{
    //如果有音乐播放
    if(_audioID != AudioEngine::INVAILD_AUDIO_ID)
    {
        //并且时间未知
        if(_duration == AudioEngine::TIME_UNKNOWN)
        {
            //设置时间间隔
            _duration = AudioEngine::getDuration(_audioID);
        }
        if(_duration != AudioEngine::TIME_UNKNOWN)
        {
            //如果时间间隔不为TIME_UNKNOWN,获取当前的播放时间
            auto time = AudioEngine::getCurrentTime(_audioID);
            _timeRatio = time / _duration;//计算时间进度比
            if(_updateTimeSlider)//如果更新进度条为true
            {
                ((SliderEx*)_timeSlider)->setRatio(_timeRatio);//设置时间进度条的进度
            }
        }
    }
}
AudioControlTest::~AudioControlTest()
{
    
}
std::string AudioControlTest::subtitle() const
{
    return "audio control test";
}

bool PlaySimultaneouslyTest::init()
{
    bool bRet = false;
    do{
        CC_BREAK_IF(!BaseTest::init());
        
        char text[36];
        int tmp = 81;
        //获取音乐文件
        for(int index = 0; index < TEST_COUNT;++index)
        {
            sprintf(text,"FX0%d.mp3",tmp+index);
            _files[index] = text;
        }
        //统计正在播放数量
        _playingcount = 0;
        //创建播放按钮,回调函数的参数button在TextButton的触摸事件中,传递的是this对象,即当前playItem对象
        auto playItem = TextButton::create("play-simultaneously",[&](TextButton* button){
            int audioId;
            _playingcount = 0;
            //设置按钮为触摸状态,即按下按钮
            button->setEnabled(false);
            //获取当前时间,返回今天当前秒和微秒的值
            auto startTime = utils::gettime();
            for(int index = 0; index < TEST_COUNT; ++index)
            {
                //播放_files里的音乐
                audioId = AudioEngine::play2d(_files[index]);
                if(audioId != AudioEngine::INVAILD_AUDIO_ID)
                {
                    //正在播放增加1
                    _playingcount += 1;
                    //播放完毕的回调函数
                    AudioEngine::setFinishCallback(audioId,const std::string& filePath){
                        //正在播放减1
                        _playingcount -= 1;
                        //如果正在播放的数量小于等于-1,设置播放按钮为true,即未按下状态
                        if(_playingcount <= 0)
                        {
                            ((TextButton*)_playItem)->setEnabled(true);
                        }
                    });
                }else//如果ID等于-1,则没有音乐文件播放,或播放音乐文件失败
                {
                    log("%s,%d,Fail to play File:%s",__FILE__,__LINE__,_files[index].c_str());
                }
            }
            //打印播放的时长
            log("diff time:%lf",utils::gettime() - startTime);
        });
        //设置像素级坐标
        playItem->setNormalizedPosition(Vec2(0.5f,0.5f));
        this->addChild(playItem);
        _playItem = playItem;
        
        bRet = true;
    }while(0);
    return bRet;
}
PlaySimultaneouslyTest::~PlaySimultaneouslyTest()
{
    
}
std::string PlaySimultaneouslyTest::subtitle() const
{
    return "PlaySimultaneously Test";
}

bool AudioProfileTest::init()
{
    bool bRet = false;
    do{
        CC_BREAK_IF(!BaseTest::init());
        
        char text[30];
        _files[0] = "background.mp3";
#if CC_TARGET_PLATFORM == CC_PLATFORM_IOS || CC_TARGET_PLATFORM == CC_PLATFORM_MAC
        _files[1] = "background.caf";
#else
        _files[1] = "background.ogg";
#endif
        std::string fontFilePath = "fonts/arial.ttf";
        _minDelay = 1.0f;//两个声音的最小时间间隔
        _time = 0.0f;
        
        _audioProfile.name = "AudioProfileTest";//name不可为空
        _audioProfile.maxInstances = 3;//音乐文件数量
        _audioProfile.minDelay = 1.0;//两个声音的最小时间间隔
        Vec2 pos(0.5f,0.7f);
        for(int index = 0; index < FILE_COUNT; ++index)
        {
            sprintf(text,"play %s",_files[index].c_str());
            auto playItem = TextButton::create(text,[&](TextButton* button){
                int index = button->getTag();
                //播放文件,参数1:文件路径,参数2:不循环播放,参数3:音量,参数4:AudioProfile对象,设置相关配置
                auto id = AudioEngine::play2d(_files[index],false,1.0f,&_audioProfile);
                if(id != AudioEngine::INVAILD_AUDIO_ID)
                {
                    _time = _minDelay;
                    _audioCount += 1;
                    char show[30];
                    sprintf(show,"audio count:%d",_audioCount);
                    _showLabel->setString(show);
                    //播放完毕回调事件
                    AudioEngine::setFinishCallback(id,const std::string& filePath){
                        _audioCount = -1;
                        char show[30];
                        sprintf(show,_audioCount);
                        _showLabel->setString(show);
                    });
                }
            });
            playItem->setTag(index);
            playItem->setNormalizedPosition(pos);
            this->addChild(playItem);
            pos.y -= 0.15f;
        }
        
        Vec2 origin = Director::getInstance()->getVisibleOrigin();
        Size winSize = Director::getInstance()->getVisibleSize();
        
        auto profileInfoLabel = Label::createWithTTF("AudioProfile Info:\n  max instance:3  \n  minimum delay:1.0",20);
        profileInfoLabel->setAnchorPoint(Vec2::ANCHOR_MIDDLE_LEFT);
        profileInfoLabel->setPosition(Vec2(origin.x,origin.y+winSize.height*0.65f));
        addChild(profileInfoLabel);
        
        _audioCount = 0;
        //初始化_showLabel对象
        _showLabel = Label::createWithTTF("audio count:0",20);
        _showLabel->setAnchorPoint(Vec2::ANCHOR_MIDDLE_LEFT);
        _showLabel->setPosition(Vec2(origin.x,origin.y+winSize.height*0.5f));
        addChild(_showLabel);
        
        //初始化timeSlider对象
        auto timeSlider = SliderEx::create();
        timeSlider->setEnabled(false);
        timeSlider->setNormalizedPosition(pos);
        addChild(timeSlider);
        _timeSlider = timeSlider;
        this->schedule(CC_CALLBACK_1(AudioProfileTest::update,0.05f,"update_key");
        
        bRet = true;
    }while(0);
    return bRet;
}

void AudioProfileTest::update(float dt)
{
    if(_time > 0.0f)
    {
        _time -= dt;
        //设置进度比
        ((SliderEx*)_timeSlider)->setRatio(_time / _minDelay);
    }
}

AudioProfileTest::~AudioProfileTest()
{
    
}
std::string AudioProfileTest::subtitle() const
{
    return "AudioProfile test";
}

bool InvalidAudioFileTest::init()
{
    bool bRet = false;
    do{
        CC_BREAK_IF(!BaseTest::init());
        
        auto playItem = TextButton::create("play unsupported media type",[&](TextButton* button){
#if CC_TARGET_PLATFORM == CC_PLATFORM_IOS || CC_TARGET_PLATFORM == CC_PLATFORM_MAC
            AudioEngine::play2d("background.ogg");
#elif CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID || CC_TARGET_PLATFORM == CC_PLATFORM_WIN32
            AudioEngine::play2d("background.caf");
#endif
        });
        playItem->setNormalizedPosition(Vec2(0.5f,0.6f));
        this->addChild(playItem);
        //播放不存在的音乐文件,查看控制台
        auto playItem2 = TextButton::create("play not-existent file",[&](TextButton* button){
            AudioEngine::play2d("not-existent file.mp3");
        });
        playItem2->setNormalizedPosition(Vec2(0.5f,0.4f));
        this->addChild(playItem2);
        
        bRet = true;
    }while(0);
    return bRet;
}

InvalidAudioFileTest::~InvalidAudioFileTest()
{
    
}
std::string InvalidAudioFileTest::subtitle() const
{
    return "InvalidAudioFile test";
}
//播放比较大的音乐文件
bool LargeAudioFileTest::init()
{
    bool bRet = false;
    do{
        CC_BREAK_IF(!BaseTest::init());
        
        auto playItem = TextButton::create("play large audio file",[&](TextButton* button){
            AudioEngine::play2d("LuckyDay.mp3");
        });
        playItem->setNormalizedPosition(Vec2::ANCHOR_MIDDLE);
        this->addChild(playItem);
        
        bRet = true;
    }while(0);
    return bRet;
}

LargeAudioFileTest::~LargeAudioFileTest()
{
    
}
std::string LargeAudioFileTest::subtitle() const
{
    return "LargeAudioFile Test";
}
#endif

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


    本文实践自 RayWenderlich、Ali Hafizji 的文章《How To Create Dynamic Textures with CCRenderTexture in Cocos2D 2.X》,文中使用Cocos2D,我在这里使用Cocos2D-x 2.1.4进行学习和移植。在这篇文章,将会学习到如何创建实时纹理、如何用Gimp创建无缝拼接纹
Cocos-code-ide使用入门学习地点:杭州滨江邮箱:appdevzw@163.com微信公众号:HopToad 欢迎转载,转载标注出处:http://blog.csdn.netotbaron/article/details/424343991.  软件准备 下载地址:http://cn.cocos2d-x.org/download 2.  简介2.1         引用C
第一次開始用手游引擎挺激动!!!进入正题。下载资源1:从Cocos2D-x官网上下载,进入网页http://www.cocos2d-x.org/download,点击Cocos2d-x以下的Download  v3.0,保存到自定义的文件夹2:从python官网上下载。进入网页https://www.python.org/downloads/,我当前下载的是3.4.0(当前最新
    Cocos2d-x是一款强大的基于OpenGLES的跨平台游戏开发引擎,易学易用,支持多种智能移动平台。官网地址:http://cocos2d-x.org/当前版本:2.0    有很多的学习资料,在这里我只做为自己的笔记记录下来,错误之处还请指出。在VisualStudio2008平台的编译:1.下载当前稳
1.  来源 QuickV3sample项目中的2048样例游戏,以及最近《最强大脑》娱乐节目。将2048改造成一款挑战玩家对数字记忆的小游戏。邮箱:appdevzw@163.com微信公众号:HopToadAPK下载地址:http://download.csdn.net/detailotbaron/8446223源码下载地址:http://download.csdn.net/
   Cocos2d-x3.x已经支持使用CMake来进行构建了,这里尝试以QtCreatorIDE来进行CMake构建。Cocos2d-x3.X地址:https://github.com/cocos2d/cocos2d-x1.打开QtCreator,菜单栏→"打开文件或项目...",打开cocos2d-x目录下的CMakeLists.txt文件;2.弹出CMake向导,如下图所示:设置
 下载地址:链接:https://pan.baidu.com/s/1IkQsMU6NoERAAQLcCUMcXQ提取码:p1pb下载完成后,解压进入build目录使用vs2013打开工程设置平台工具集,打开设置界面设置: 点击开始编译等待编译结束编译成功在build文件下会出现一个新文件夹Debug.win32,里面就是编译
分享一下我老师大神的人工智能教程吧。零基础!通俗易懂!风趣幽默!还带黄段子!希望你也加入到我们人工智能的队伍中来!http://www.captainbed.net前言上次用象棋演示了cocos2dx的基本用法,但是对cocos2dx并没有作深入的讨论,这次以超级马里奥的源代码为线索,我们一起来学习超级马里奥的实
1. 圆形音量button事实上作者的本意应该是叫做“电位计button”。可是我觉得它和我们的圆形音量button非常像,所以就这么叫它吧~先看效果:好了,不多解释,本篇到此为止。(旁白: 噗。就这样结束了?)啊才怪~我们来看看代码:[cpp] viewplaincopyprint?CCContro
原文链接:http://www.cnblogs.com/physwf/archive/2013/04/26/3043912.html为了进一步深入学习贯彻Cocos2d,我们将自己写一个场景类,但我们不会走的太远,凡是都要循序渐进,哪怕只前进一点点,那也至少是前进了,总比贪多嚼不烂一头雾水的好。在上一节中我们建
2019独角兽企业重金招聘Python工程师标准>>>cocos2d2.0之后加入了一种九宫格的实现,主要作用是用来拉伸图片,这样的好处在于保留图片四个角不变形的同时,对图片中间部分进行拉伸,来满足一些控件的自适应(PS: 比如包括按钮,对话框,最直观的形象就是ios里的短信气泡了),这就要求图
原文链接:http://www.cnblogs.com/linji/p/3599478.html1.环境和工具准备Win7VS2010/2012,至于2008v2版本之后似乎就不支持了。 2.安装pythonv.2.0版本之前是用vs模板创建工程的,到vs2.2之后就改用python创建了。到python官网下载版本2.7.5的,然后
环境:ubuntu14.04adt-bundle-linux-x86_64android-ndk-r9d-linux-x86_64cocos2d-x-3.0正式版apache-ant1.9.3python2.7(ubuntu自带)加入环境变量exportANDROID_SDK_ROOT=/home/yangming/adt-bundle-linux/sdkexportPATH=${PATH}:/$ANDROID_SDK_ROOTools/export
1开发背景游戏程序设计涉及了学科中的各个方面,鉴于目的在于学习与进步,本游戏《FlappyBird》采用了两个不同的开发方式来开发本款游戏,一类直接采用win32底层API来实现,另一类采用当前火热的cocos2d-x游戏引擎来开发本游戏。2需求分析2.1数据分析本项目要开发的是一款游
原文链接:http://www.cnblogs.com/linji/p/3599912.html//纯色色块控件(锚点默认左下角)CCLayerColor*ccc=CCLayerColor::create(ccc4(255,0,0,128),200,100);//渐变色块控件CCLayerGradient*ccc=CCLayerGradient::create(ccc4(255,0,0,
原文链接:http://www.cnblogs.com/linji/p/3599488.html//载入一张图片CCSprite*leftDoor=CCSprite::create("loading/door.png");leftDoor->setAnchorPoint(ccp(1,0.5));//设置锚点为右边中心点leftDoor->setPosition(ccp(240,160));/
为了答谢广大学员对智捷课堂以及关老师的支持,现购买51CTO学院关老师的Cocos2d-x课程之一可以送智捷课堂编写图书一本(专题可以送3本)。一、Cocos2d-x课程列表:1、Cocos2d-x入门与提高视频教程__Part22、Cocos2d-x数据持久化与网络通信__Part33、Cocos2d-x架构设计与性能优化内存优
Spawn让多个action同时执行。Spawn有多种不同的create方法,最终都调用了createWithTwoActions(FiniteTimeAction*action1,FiniteTimeAction*action2)方法。createWithTwoActions调用initWithTwoActions方法:对两个action变量初始化:_one=action1;_two=action2;如果两个a
需要环境:php,luajit.昨天在cygwin上安装php和luajit环境,这真特么是一个坑。建议不要用虚拟环境安装打包环境,否则可能会出现各种莫名问题。折腾了一下午,最终将环境转向linux。其中,luajit的安装脚本已经在quick-cocos2d-x-develop/bin/中,直接luajit_install.sh即可。我的lin
v3.0相对v2.2来说,最引人注意的。应该是对触摸层级的优化。和lambda回调函数的引入(嗯嗯,不枉我改了那么多类名。话说,每次cocos2dx大更新。总要改掉一堆类名函数名)。这些特性应该有不少人研究了,所以今天说点跟图片有关的东西。v3.0在载入图片方面也有了非常大改变,仅仅只是