微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

cocos2dx实现手动选取区域截图

使用的方法是:RenderTexture渲染纹理+对当前场景的层Layer施加位移(先改后还)。
全屏截图可以使用以前的方法 RenderTexture渲染纹理,
也可以使用cocos2d::utils::captureScreen方法来完成。
保存下截图文件的话,还是需要使用到RenderTexture的savetoFile方法
(鄙人新手一枚,如有好的方法,或者认为我这样做存在问题的,请多多指教,在此谢过了!)

代码如下:

Screen.h

#ifndef _SCREEN_H_
#define _SCREEN_H_
#include "cocos2d.h"
USING_NS_CC;
class ScreenScene :public Layer
{
public:
    static Scene* createScene();
    virtual bool init();
    CREATE_FUNC(ScreenScene);
    void menuCloseCallback(Ref *pSender);
    bool onTouchBegan(Touch *touch,Event *event);
    void onTouchEnded(Touch *touch,Event *event);
    void afterCaptured(bool success,std::string fileName);
    //屏幕截图
    void screenShoot(Size size);
private:
    //触摸起始点与结束点
    Vec2 _startPos,_endPos;
};
#endif

Screen.cpp

#include "Screen.h"
Scene* ScreenScene::createScene()
{
    auto scene = Scene::create();
    auto layer = ScreenScene::create();
    scene->addChild(layer,0,11);
    return scene;
}

bool ScreenScene::init()
{
    if (!Layer::init())
    {
        return false;
    }
    //获取视图
    auto visibleSize = Director::getInstance()->getVisibleSize();
    //添加背景图片
    auto bgSprite = Sprite::create("HelloWorld.png");
    bgSprite->setScale(visibleSize.width / bgSprite->getContentSize().width,visibleSize.height / bgSprite->getContentSize().height);
    bgSprite->setPosition(visibleSize.width / 2,visibleSize.height / 2);
    this->addChild(bgSprite);

    //添加关闭按钮
    auto closeItem = MenuItemImage::create(
        "Closenormal.png","CloseSelected.png",CC_CALLBACK_1(ScreenScene::menuCloseCallback,this));

    closeItem->setPosition(visibleSize.width - closeItem->getContentSize().width / 2,closeItem->getContentSize().height / 2);
    // create menu,it's an autorelease object
    auto menu = Menu::create(closeItem,nullptr);
    menu->setPosition(Vec2::ZERO);
    this->addChild(menu,1);

    auto touchListener = EventListenerTouchOneByOne::create();
    touchListener->onTouchBegan = CC_CALLBACK_2(ScreenScene::onTouchBegan,this);
    touchListener->onTouchEnded = CC_CALLBACK_2(ScreenScene::onTouchEnded,this);
    _eventdispatcher->addEventListenerWithSceneGraPHPriority(touchListener,this);

    //this->setPosition(-20,-20);
    return true;
}

void ScreenScene::menuCloseCallback(Ref *pSender)
{
    _director->end();
}

bool ScreenScene::onTouchBegan(Touch *touch,Event *event)
{
    //获取起始点
    auto nodeLocation = this->convertToNodeSpace(touch->getLocation());
    _startPos = nodeLocation;
    return true;
}


void ScreenScene::onTouchEnded(Touch *touch,Event *event)
{
    auto visibleSize = _director->getVisibleSize();
    auto origin = Director::getInstance()->getVisibleOrigin();
    //获得结束点
    _endPos = this->convertToNodeSpace(touch->getLocation());
    //定义一个划取大小的渲染纹理
    auto shootSize = Size(MIN(abs(_startPos.x - _endPos.x),visibleSize.width),MIN(abs(_startPos.y - _endPos.y),visibleSize.height));
    auto renderTexture = RenderTexture::create(shootSize.width,shootSize.height);
    //获取当前场景
    auto currentScene = _director->getRunningScene();
    //获取左下点
    auto LeftDownPoint = Vec2(MAX(MIN(_startPos.x,_endPos.x),0),MAX(MIN(_startPos.y,_endPos.y),0));
    auto offset = Vec2(0,0) - LeftDownPoint;
    //位移
    currentScene->getChildByTag(11)->setPosition(offset);

    renderTexture->beginWithClear(0.0f,0.0f,0.0f);
    currentScene->visit();
    renderTexture->end();

    //还原
    //这里不设置延迟的话,由于前后时间的问题,会导致截图出现大的偏差。
    auto delay = DelayTime::create(0.001f);
    auto callfunc = CallFunc::create([=]{
        //不让其还原的时候闪烁一下
        Director::getInstance()->pause();
        currentScene->getChildByTag(11)->setPosition(0,0);
        Director::getInstance()->resume();
    });
    this->runAction(Sequence::create(delay,callfunc,nullptr));

    //这个path是截图保存的路径。
    auto path = FileUtils::getInstance()->getWritablePath();
    renderTexture->savetoFile("ScreenShoot5201314.png",Image::Format::PNG);
    return;

    //这个是截取全屏的,因为上面已经return了,所以不会执行到这
    //可以把上面全部注释掉,就能够看到效果了。
    utils::captureScreen(CC_CALLBACK_2(ScreenScene::afterCaptured,this),"newScreenShoot.png");
    return;
}

//捕获之后
void ScreenScene::afterCaptured(bool success,std::string fileName)
{
    auto visibleSize = _director->getVisibleSize();
    if (success)
    {
        //先在中间显示,然后慢慢淡出,移除。当然还是将截图保存下来了
        auto shootSprite = Sprite::create(fileName);
        shootSprite->setScale(0.25);
        shootSprite->setPosition(visibleSize.width / 2,visibleSize.height / 2);
        this->addChild(shootSprite,1,1);
        screenShoot(shootSprite->getContentSize());
        auto delay = DelayTime::create(1.0f);
        auto fadeOut = FadeOut::create(2.0f);
        auto callFunc = CallFunc::create([=]{shootSprite->removeFromParent(); log("the sprite has removed from his parentNode!"); });
        shootSprite->runAction(Sequence::create(delay,fadeOut,callFunc,nullptr));

    }
    else
    {
        log("capture screen Failed!");
    }
}

void ScreenScene::screenShoot(Size size)
{
    auto visibleSize = _director->getVisibleSize();

    auto renderTexture = RenderTexture::create(size.width,size.height,Texture2D::PixelFormat::RGBA8888);
    auto shootSprite = this->getChildByTag(1);
    renderTexture->beginWithClear(0,0);
    shootSprite->visit();
    renderTexture->end();
    //这个path是截图保存的路径。
    auto path = FileUtils::getInstance()->getWritablePath();
    renderTexture->savetoFile("newScreenShoot.png",Image::Format::PNG);
    return;
}

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

相关推荐