美文网首页
6-performFunctionInCocosThread

6-performFunctionInCocosThread

作者: porridgechen890 | 来源:发表于2019-02-20 15:10 被阅读15次

问题的提出

假设现在有这样一个需求:按住一个按钮后开始录音,录音开始后播放录音动画,松开按钮后停止录音,并移除录音动画。

分析

录音由安卓和iOS的代码实现,不在cocos这一层,并且属于新开的线程。但播放动画和停止动画由cocos的代码实现,属于cocos的UI线程。所以如果安卓(或iOS)代码启动录音成功需要告诉cocos的UI线程播放动画。如果安卓(或iOS)代码停止录音成功需要告诉cocos的UI线程停止动画。在cocos里新开辟一个线程可以用std::thread,在其他线程里回调cocos的函数可以用performFunctionInCocosThread。

Android里面有runOnUiThread,IOS下有performSelectorOnMainThread。
cocos2dx 3.0系列中新加入了一个专门处理线程安全的函数performFunctionInCocosThread(),它的声明如下:
/** Calls a function on the cocos2d thread. Useful when you need to call a cocos2d function from another thread.
This function is thread safe.
@param function The function to be run in cocos2d thread.
@since v3.0
@js NA
*/
void performFunctionInCocosThread(std::function<void()> function);

代码

这个Demo展示的是如何开辟新的线程和在支线程里如何影响UI线程。

//HelloWorld.h
class HelloWorld : public cocos2d::Scene
{
public:
    static cocos2d::Scene* createScene();
    virtual bool init();
    void menuCloseCallback(cocos2d::Ref* pSender);
    CREATE_FUNC(HelloWorld);
    void threadA();
};
//HelloWorld.cpp
bool HelloWorld::init()
{
    //其他未改动的代码省略了
    this->addChild(sprite, 0, "helloworld");//这里给这个图加了个名字
}

void threadB()
{
    Director::getInstance()->getScheduler()->performFunctionInCocosThread([]{
        auto sprite = Sprite::create("res/MagentaSquare.png");
        Director::getInstance()->getRunningScene()->addChild(sprite);
        Size size = Director::getInstance()->getWinSize();
        sprite->setPosition(Vec2(size.width/2-10, size.height/2));
    });
}

void HelloWorld::menuCloseCallback(Ref* pSender)
{
    std::thread t1(&HelloWorld::threadA, this);
    t1.detach();
    log("新开线程释放了");
    
    //这个t2只是为了说明新开的线程的函数可以不是成员函数,普通函数也可以
    std::thread t2(threadB);
    t2.detach();
}

void HelloWorld::threadA()
{
    Director::getInstance()->getScheduler()->performFunctionInCocosThread([this]{
        //新开线程回调主线程做两件事,创建并显示一个黄色方块,隐藏原来的HelloWorld图片。
        auto sprite = Sprite::create("res/YellowSquare.png");
        this->addChild(sprite);
        Size size = Director::getInstance()->getWinSize();
        sprite->setPosition(Vec2(size.width/2+10, size.height/2));
        auto spriteHelloWorld = this->getChildByName("helloworld");
        if (spriteHelloWorld)
        {
            spriteHelloWorld->setVisible(false);
        }
        log("新开线程的回调执行完了");
    });
    log("新开线程的函数执行完了");
}
没有点按钮时.png
点了按钮之后.png
image.png

相关文章

  • 6-performFunctionInCocosThread

    问题的提出 假设现在有这样一个需求:按住一个按钮后开始录音,录音开始后播放录音动画,松开按钮后停止录音,并移除录音...

网友评论

      本文标题:6-performFunctionInCocosThread

      本文链接:https://www.haomeiwen.com/subject/jiddaftx.html