当前位置:网站首页>[cocos2d-x] erasable layer:erasablelayer

[cocos2d-x] erasable layer:erasablelayer

2022-06-23 06:00:00 linchaolong

explain


ErasableLayer Is an erasable Layer, Can achieve similar eraser 、 Scraping and other effects . The principle is realized through color mixing . See this article for color blending >> Click to see <<.

Test environment :cocos2d-x3.3、cocos2d-x3.5


Source code


#ifndef __ERASABLELAYER_H__
#define __ERASABLELAYER_H__

#include "cocos2d.h"

USING_NS_CC;

// http://blog.csdn.net/linchaolong
//  Erasable Layer
class ErasableLayer :public Layer
{
public:
	//  establish ErasableLayer
	//1. mask 
	//2. Eraser ( It can be Sprite Or the path of the texture )
	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);

	//  Restore 
	void clear();
	//  Erasable 
	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, erasa))
	{
		ret->autorelease();
		return ret;
	}
	delete ret;
	return nullptr;
}

ErasableLayer* ErasableLayer::create(Node* 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());

	//  Set the color blending mode 
	BlendFunc erasaBf = { GL_ZERO, GL_ONE_MINUS_SRC_ALPHA }; // Source factor : The value is 0, The color of the eraser is transparent ; Objective factors : Target color transparency minus source color transparency 
	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));

	//  Touch event 
	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;
	}
	
	//  Set source color alpha The value is the maximum , Target color alpha Value minus the source color alpha After the value, it will be 0 了 , The mixed effect becomes transparent , In this way, the eraser effect is realized .
	erasa_->setOpacity(255);

	//  to update RenderTexture
	rt_->begin();
	
	//  draw 
	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()));
}


//  Invoke the sample 

	//  mask 
	auto maskLayer = LayerColor::create(Color4B(0,0,255,200));
	maskLayer->setContentSize(sprite->getContentSize());

	//  Create erasable Layer
	auto layer = ErasableLayer::create(maskLayer, "eraser.png");
	layer->setPosition(Vec2(visibleSize.width / 4, visibleSize.height / 4));
	this->addChild(layer);

Here you create a blue LayerColor, And erase the Layer.

原网站

版权声明
本文为[linchaolong]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/174/202206230421394891.html