// // 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(); }
时间: 2024-10-09 06:51:21