Cocos2dx_可擦除Layer

前端之家收集整理的这篇文章主要介绍了Cocos2dx_可擦除Layer前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
#ifndef __ERASABLELAYER_H__
#define __ERASABLELAYER_H__

#include "cocos2d.h"

USING_NS_CC;

// http://blog.csdn.net/linchaolong
// 可擦除的Layer
class ErasableLayer :public Layer
{
public:
	// 创建ErasableLayer
	//1.遮罩层
	//2.橡皮擦(可以是Sprite或者纹理的路径)
	static ErasableLayer* create(const char* layerPath,const char* erasaPath);
	static ErasableLayer* create(Node *layer,Sprite* erasa);
	static ErasableLayer* create(Node *layer,const char* erasaPath);
	static ErasableLayer* create(const char* layerPath,Sprite* erasa);

	// 还原
	void clear();
	// 是否可擦除
	void setErasable(bool);

	bool onTouchBegan(Touch* touch,Event  *event);
	void onTouchesMoved(Touch* touch,Event *event);
	void onTouchEnded(Touch* touch,Event  *event);
protected:
	ErasableLayer();
	~ErasableLayer();

	bool init(Node *layer,Sprite* erasa);
	void tick(float);
private:
	Node* layer_;
	Sprite* erasa_;
	bool isErasable_;
	RenderTexture* rt_;
};

#endif
#include "ErasableLayer.h"

ErasableLayer::ErasableLayer() :isErasable_(true)
{
}

ErasableLayer::~ErasableLayer()
{
	CC_SAFE_RELEASE(layer_);
	CC_SAFE_RELEASE(erasa_);
}
 
ErasableLayer* ErasableLayer::create(const char* layerPath,const char* erasaPath)
{
	CCSprite* layer = CCSprite::create(layerPath);
	CCSprite* erasa = CCSprite::create(erasaPath);

	ErasableLayer* ret = new ErasableLayer;
	if (ret->init(layer,erasa))
	{
		ret->autorelease();
		return ret;
	}
	delete ret;
	return nullptr;
}

ErasableLayer* ErasableLayer::create(Node* layer,Sprite* erasa)
{

	ErasableLayer* ret = new ErasableLayer;
	if (ret->init(layer,const char* erasaPath)
{
	CCSprite* erasa = CCSprite::create(erasaPath);
	ErasableLayer* ret = new ErasableLayer;
	if (ret->init(layer,erasa))
	{
		ret->autorelease();
		return ret;
	}
	delete ret;
	return nullptr;
}

ErasableLayer* ErasableLayer::create(const char* layerPath,Sprite* erasa)
{
	CCSprite* layer = CCSprite::create(layerPath);

	ErasableLayer* ret = new ErasableLayer;
	if (ret->init(layer,erasa))
	{
		ret->autorelease();
		return ret;
	}
	delete ret;
	return nullptr;
}

bool ErasableLayer::init(Node *layer,Sprite* erasa)
{
	if (!Layer::init())
	{
		return false;
	}

	layer_ = layer;
	erasa_ = erasa;

	layer_->retain();
	erasa_->retain();

	this->setContentSize(layer_->getContentSize());

	// 设置颜色混合模式
	BlendFunc erasaBf = { GL_ZERO,GL_ONE_MINUS_SRC_ALPHA }; //源因子:值为0,橡皮擦颜色为透明;目标因子:目标颜色透明度减去源颜色的透明度
	erasa_->setBlendFunc(erasaBf);

	auto size = layer_->getContentSize();
	rt_ = RenderTexture::create(size.width,size.height);
	rt_->setAnchorPoint(Vec2(0,0));
	rt_->setPosition(Vec2(size.width/2,size.height/2));
	this->addChild(rt_);

	clear();

	schedule(CC_SCHEDULE_SELECTOR(ErasableLayer::tick));

	// 触摸事件
	auto listener = EventListenerTouchOneByOne::create();
	listener->onTouchBegan = CC_CALLBACK_2(ErasableLayer::onTouchBegan,this);
	listener->onTouchMoved = CC_CALLBACK_2(ErasableLayer::onTouchesMoved,this);
	listener->onTouchEnded = CC_CALLBACK_2(ErasableLayer::onTouchEnded,this);
	_eventDispatcher->addEventListenerWithSceneGraPHPriority(listener,this);
	listener->setSwallowTouches(false);

	return true;
}

void ErasableLayer::tick(float)
{
	if (!isErasable_)
	{
		return;
	}
	
	// 设置源颜色alpha值为最大值,目标颜色alpha值减去源颜色alpha值后就为0了,混合出来的效果就变透明了,这样就实现了橡皮擦效果了。
	erasa_->setOpacity(255);

	// 更新RenderTexture
	rt_->begin();
	
	// 绘制
	erasa_->visit();

	rt_->end();
}

void ErasableLayer::clear()
{
	layer_->setAnchorPoint(Vec2(0,0));
	layer_->setPosition(Vec2(0,0));

	rt_->begin();
	layer_->visit();
	rt_->end();
}

void ErasableLayer::setErasable(bool flag)
{
	isErasable_ = flag;
}

bool ErasableLayer::onTouchBegan(Touch* touch,Event  *event)
{
	erasa_->setPosition(this->convertToNodeSpace(touch->getLocation()));
	return true;
}

void ErasableLayer::onTouchesMoved(Touch* touch,Event  *event)
{
	erasa_->setPosition(this->convertToNodeSpace(touch->getLocation()));
}

void ErasableLayer::onTouchEnded(Touch* touch,Event  *event)
{
	erasa_->setPosition(this->convertToNodeSpace(touch->getLocation()));
}

猜你在找的Cocos2d-x相关文章