• cocos2dx 3.2 Touch Listen和menu回调实现截屏


      在Cocos2d-X 3.x里面,已经集成了截屏功能,单独放在utils命名空间里,实现在base/ccUtils.h文件里面。看下函数申明

      

    /** Capture the entire screen
         * To ensure the snapshot is applied after everything is updated and rendered in the current frame,
         * we need to wrap the operation with a custom command which is then inserted into the tail of the render queue.
         * @param afterCaptured, specify the callback function which will be invoked after the snapshot is done.
         * @param filename, specify a filename where the snapshot is stored. This parameter can be either an absolute path or a simple
         * base filename ("hello.png" etc.), don't use a relative path containing directory names.("mydir/hello.png" etc.)
         * @since v3.2
         */
        简单看下,就是自定义一个渲染命令,加入到渲染队列尾部。
        函数参数有两个,,第一个是截屏完成后的操作函数回调,一个事自定义的截屏图片名字。
        回调函数有两个固定参数,一个是 bool型,用来判断截屏是否成功,另外一个是filename,实际上就是第二个参数会传入该回掉函数。
    void captureScreen(const std::function<void(bool, const std::string&)>& afterCaptured, const std::string& filename);

      有一个很重要的问题就是:上面函数的参数filename需要加上图片格式,例如:screenshot.png。因为,在函数实现内部使用过后缀来确定保存类型的,这个略坑,建议使用jpg,毕竟图片会小很多。

      我的工程是直接用的helloword,在helloscene上添加一个label,用来做截屏点击按钮,效果如图:

      

      现在呢,对于Capture这个label来说,我们有两种方法给他添加响应函数,

      1、把这个label加入menu,这样可以很简单的添加回掉函数,这种方法很通用,就不细说了。

      2、另一种就是使用触摸点击来给这个label添加响应函数。

      首先,需要添加一个aftercapture函数,在这个函数里面呢,将截屏的图片显示出来,具体做法就是重新创建一个scene,将图片放上去,通过导演切换到这个scene。看代码:

    void HelloWorld::afterCaptureScreen(bool issuccess, const std::string &filename) //这个函数参数是固定的,不能写错了
    {
        auto size = Director::getInstance()->getWinSize();
        if (issuccess)
        {
            auto scene = Scene::create();
            auto sp = Sprite::create(filename);
            
            sp->setScale(0.8f);
            sp->setPosition(Vec2(size.width/2, size.height/2));
            scene->addChild(sp);
    
            auto lb = LabelTTF::create();
            lb->setString("capture success!");
            lb->setColor(ccc3 (255, 0, 0));
            lb->setFontSize(40);
            lb->setAnchorPoint(Vec2(0.5f, 1.0f));
            lb->setPosition(Vec2(size.width/2, size.height));
            scene->addChild(lb);
    
            Director::getInstance()->replaceScene(scene);
        }
        else
        {
            auto scene = Scene::create();
    
            auto lb = Label::create();
            lb->setString("Capture Failed");
            lb->setTextColor(ccc4(255, 0, 0, 255));
            lb->setPosition(Vec2(size.width / 2, size.height/2));
            scene->addChild(lb);
    
            Director::getInstance()->replaceScene(scene);
        }
    }

      接下来再添加一个函数,用于在在Capture这个label的touch ended里面调用,代码如下:

    void HelloWorld::capturesc(std::string &filename)
    {
        Director::getInstance()->getTextureCache()->removeTextureForKey(filename); //这里最好加上这句,因为如果你需要重复点击这个按钮进行截屏操作的话,TextureCache里面不清除,会导致截屏失败
        utils::captureScreen(CC_CALLBACK_2(HelloWorld::afterCaptureScreen, this), filename); //在这里调用cocos2d已经实现好的captureScreen函数,将我们写好的aftercapture函数和我们需要的图片名称穿进去,图片名称的初始化必须在这个函数调用之前完成
    }

      最后完成label触摸事件写好就OK了,当然,lambda表达式用上:

    auto *ev = EventListenerTouchOneByOne::create();
        //filename = "capturesc.png"; //filename可以在这里初始化
    
        ev->onTouchBegan = [](Touch* t, Event* e){
            cocos2d::log("touch begin!");
            return true;
        };
    
        ev->onTouchMoved = [](Touch* t, Event* e){};
        ev->onTouchEnded = [&,caplb](Touch* t, Event* e){
            auto pos = t->getLocation();
            auto rect = caplb->getBoundingBox();
            auto cpos = caplb->convertToNodeSpace(pos);
            if (rect.containsPoint (cpos))
            {
                cocos2d::log("caplb is touched!!");
                filename = "scpic.jpg"; //初始化filename,后缀很重要
                caplb->setVisible(false);//将Capture这个label隐藏
                capturesc(filename); //截屏
            }
        };

    这段代码写在HelloWord的init函数里面。

      这样就完成了,截屏操作,相对于2.x的截屏好像简单了,这个就仁者见仁智者见智了。在2.x版本里面的截屏操作需要注意的是再创建Render的时候,需要传入渲染颜色深度,否则会导致visit函数渲染时无法正确进行各个对象之间的遮挡关系计算,看下最后的效果图:

      

         那么最后呢,可能截屏并不是我们的最终目的,可能为了游戏的宣传,我们还需要给这张截图添上游戏的宣传边框,这时候,我们就需要在截图之后再次创建一个场景scene,将宣传边框和截图摆好位置,再次截屏,这样就得到一张完整的游戏宣传截图,可以拿来分享到其他社交软件平台上。

      

  • 相关阅读:
    jQuery Validate 插件
    本地存储 web storage
    ajax简介及JS写原生ajax
    swiper插件简介及用法
    JavaScript中的string对象及方法
    javascript数组中的方法
    面向对象
    logging模块具体补充
    模块补充
    内置函数总结
  • 原文地址:https://www.cnblogs.com/leisc/p/4203842.html
Copyright © 2020-2023  润新知