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, 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,0,0);
    shootSprite->visit();
    renderTexture->end();
    //这个path是截图保存的路径。
    auto path = FileUtils::getInstance()->getWritablePath();
    renderTexture->saveToFile("newScreenShoot.png", Image::Format::PNG);
    return;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值