// // Eraser.h // Eraser // // Created by students on 16/1/12. // // #ifndef __Eraser__Eraser__ #define __Eraser__Eraser__ #include <stdio.h> #include <cocos2d.h> USING_NS_CC; //pszFileName--精灵文件名, eraserImmediately---是否可以立即擦除 true---可以, false---不能 //drawType---擦除形状, 0---正方形,1---圆形, 2---自定义形状(可用一张图片代替) class Eraser : public Sprite { public: Eraser(); ~Eraser(); static Eraser* create(std::string pszFileName,const bool& eraserImmediately = true,const unsigned int& drawType = 0); virtual bool init(std::string pszFileName,const bool& eraserImmediately = true,const unsigned int& drawType = 0); virtual void onEnter(); virtual void onExit(); public: CC_PROPERTY(bool, isEraser, Eraser);//设置是否可以擦除 CC_PROPERTY(float, drawWidth, DrawWidth);//擦除大小,默认10.F CC_PROPERTY(bool, isEraserOK, EraserOK);//是否擦除完毕 void setDrawStencil(std::string pszFileName); private: void eraserByBlend(Point& point); void eraserByBlend(const Point& point); void eraserByColorMask(); private: void initData(std::string pszFileName,const bool& eraserImmediately = true,const unsigned int& zdrawType = 0); Size spriteSize;//精灵大小 unsigned int drawType;//擦除形状 Point touchPoint;//触摸点 Texture2D* drawTextture;//自定义图片时,设置的擦除图片 RenderTexture* Rtex;//渲染纹理 DrawNode* pEraser;//渲染节点 }; #endif /* defined(__Eraser__Eraser__) */
//
// Eraser.cpp
// Eraser
//
// Created by students on 16/1/12.
//
//
#include "Eraser.h"
Eraser::Eraser()
{
}
Eraser::~Eraser()
{
pEraser->release();
}
Eraser* Eraser::create(std::string pszFileName,const bool& eraserImmediately,const unsigned int& drawType)
{//创建对象
Eraser* pRet = new Eraser();
if (pRet && pRet->init(pszFileName,eraserImmediately,drawType)) {
pRet->autorelease();
return pRet;
}else
{
delete pRet;
pRet = NULL;
return NULL;
}
}
bool Eraser::init(std::string pszFileName,const bool& eraserImmediately,const unsigned int& drawType)
{
if (!Sprite::init()) {
return false;
}
initData(pszFileName,eraserImmediately,drawType);
auto dis = Director::getInstance()->getEventDispatcher();
auto lis = EventListenerTouchOneByOne::create();
lis->onTouchBegan = [this](Touch* touch,Event* event)
{
if (isEraser)
{
Point point = touch->getLocation();
eraserByBlend(-this->getPosition() + point + spriteSize/2.f);
touchPoint = point;
return true;
}
return false;
};
lis->onTouchMoved = [this](Touch* touch,Event* event)
{
if (isEraser)
{
Point point = touch->getLocation();
Point normal = (point-touchPoint).getNormalized();
while(1)
{
if (point.distance(touchPoint) < 1.f)
{
eraserByBlend(-this->getPosition() + point + spriteSize/2.f);
break;
}
touchPoint = touchPoint + normal*1.f;
eraserByBlend(-this->getPosition() + touchPoint + spriteSize/2.f);
}
touchPoint = point;
}
};
dis->addEventListenerWithSceneGraphPriority(lis, this);
return true;
}
void Eraser::initData(std::string pszFileName,const bool& eraserImmediately,const unsigned int& zdrawType)
{
isEraser = eraserImmediately;
drawType = zdrawType;
drawWidth = 10.0f;
auto size = Director::getInstance()->getWinSize();
//设置图片
auto sprite = Sprite::create(pszFileName);
auto scalex = size.width/sprite->getContentSize().width;
auto scaley = size.height/sprite->getContentSize().height;
sprite->setScaleX(scalex);
sprite->setScaleY(scaley);
spriteSize = size;
sprite->setAnchorPoint(Vec2::ZERO);
//渲染纹理
Rtex = RenderTexture::create(spriteSize.width, spriteSize.height);
Rtex->setPosition(Point::ZERO);
this->addChild(Rtex);
//????
Rtex->begin();
sprite->visit();//??
Rtex->end();
//渲染节点
pEraser = DrawNode::create();
setDrawWidth(10.0f);
pEraser->retain();///???
//自定义擦除的图片
drawTextture = new Texture2D;
drawTextture->retain();
}
void Eraser::setDrawStencil(std::string pszFileName)
{
drawTextture = Director::getInstance()->getTextureCache()->addImage(pszFileName);
}
void Eraser::eraserByBlend(Point& point)
{
}
void Eraser::eraserByBlend(const Point& point)
{
switch (drawType) {
case 2:
{
auto drawSprite = Sprite::createWithTexture(drawTextture);
drawSprite->setPosition(point);
BlendFunc blendFunc = {GL_ONE_MINUS_SRC_ALPHA,GL_SRC_ALPHA};
drawSprite->setBlendFunc(blendFunc);
Rtex->begin();
drawSprite->visit();
Rtex->end();
}
break;
default:
{
pEraser->setPosition(point);
BlendFunc blendFunc = {GL_ONE,GL_ZERO};
pEraser->setBlendFunc(blendFunc);
Rtex->begin();
pEraser->visit();
Rtex->end();
}
break;
}
}
void Eraser::eraserByColorMask()
{
Rtex->begin();
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE);
pEraser->visit();
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
Rtex->end();
}
void Eraser::setEraser(bool var)
{
this->isEraser = var;
}
bool Eraser::getEraser()
{
return isEraser;
}
bool Eraser::getEraserOK()
{
isEraserOK = false;
auto image = new Image();
image = Rtex->newImage();
int m = 3;
if (image->hasAlpha()) {
m = 4;
}
unsigned char* data_ = image->getData();
int x = 0,y = 0;
for (x = 0; x<spriteSize.width; ++x) {
for (y = 0; y<spriteSize.height; ++y) {
unsigned char* pixel = data_+(x+y*image->getWidth())*m;
unsigned int r = (unsigned int)*pixel;
unsigned int g = (unsigned int)*(pixel + 1);
unsigned int b = (unsigned int)*(pixel + 2);
unsigned int a = (unsigned int)*(pixel + 3);
if (r != 0 && g!=0 && b!=0 && a!=0) {
isEraserOK = false;
break;
}
}
if (spriteSize.height != y) {
break;
}
}
if (x == spriteSize.width && y == spriteSize.height) {
isEraserOK = true;
}
delete image;
return this->isEraserOK;
}
void Eraser::setEraserOK(bool var)
{
this->isEraser = var;
}
float Eraser::getDrawWidth()
{
return this->drawWidth;
}
void Eraser::setDrawWidth(float var)
{
this->drawWidth = var;
switch (drawType) {
case 0:
{
pEraser->drawDot(Vec2::ZERO, drawWidth, Color4F(0, 0, 0, 0));
}
break;
case 1:
{
float fRadius = drawWidth;
const int nCount = 100;
const float coef = 2.0f*(float)M_PI/nCount;
static Vec2 circle[nCount];
for (unsigned int i=0; i<nCount; i++) {
float rads = i*coef;
circle[i].x = fRadius*cosf(rads);
circle[i].y = fRadius*sinf(rads);
}
pEraser->drawPolygon(circle, nCount, Color4F(0, 0, 0, 0), 0, Color4F(0, 0, 0, 0));
}
break;
case 2:
{
}
break;
default:
break;
}
}
void Eraser::onEnter()
{
Sprite::onEnter();//单点触摸
}
void Eraser::onExit()
{
Sprite::onExit();
}
原文:http://www.cnblogs.com/lsy137/p/5128507.html