美文网首页
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

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