说明
ErasableLayer是一个可擦除的Layer,可实现类似橡皮擦、刮奖等效果。原理是通过颜色混合实现的。关于颜色混合可查看这篇文章
>>点击查看<<。
测试环境:cocos2d-x3.3、cocos2d-x3.5
源码
#ifndef __ERASABLELAYER_H__
#define __ERASABLELAYER_H__
#include "cocos2d.h"
USING_NS_CC;
// http://blog.youkuaiyun.com/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, 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());
// 设置颜色混合模式
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()));
}
// 调用示例
// 遮罩层
auto maskLayer = LayerColor::create(Color4B(0,0,255,200));
maskLayer->setContentSize(sprite->getContentSize());
// 创建可擦除的Layer
auto layer = ErasableLayer::create(maskLayer, "eraser.png");
layer->setPosition(Vec2(visibleSize.width / 4, visibleSize.height / 4));
this->addChild(layer);
这里创建了一个蓝色的LayerColor,并擦除该Layer。
本文介绍了Cocos2d-x中创建可擦除Layer的方法,通过ErasableLayer类实现交互式的擦除功能,允许用户在游戏或应用中动态清除特定内容。
1798

被折叠的 条评论
为什么被折叠?



