cocos2dx实现橡皮擦效果 cocos2dx实现橡皮擦效果以及判断是否擦除完毕
Gemini_Dong 人气:0首先修改HelloWorld.h文件
#ifndef __HELLOWORLD_SCENE_H__ #define __HELLOWORLD_SCENE_H__ #include "cocos2d.h" #include "cocos-ext.h" USING_NS_CC_EXT; USING_NS_CC; class HelloWorld : public cocos2d::Layer { public: // there's no 'id' in cpp, so we recommend returning the class instance pointer static cocos2d::Scene* createScene(); // Here's a difference. Method 'init' in cocos2d-x returns bool, instead of returning 'id' in cocos2d-iphone virtual bool init(); // a selector callback void menuCloseCallback(cocos2d::Ref* pSender); // implement the "static create()" method manually CREATE_FUNC(HelloWorld); void myUpdate(float dt);//不断判断是否全部擦除 void onTouchesMoved(const std::vector<Touch*>& touches, Event* event); bool myIsDataClear(RenderTexture *pRenderTexture);//是否完全擦除 bool myIsDataClearInRect(RenderTexture *pRenderTexture,int x,int y,int width ,int height);//某个区域是否完全擦除 Sprite *sprFore; RenderTexture *renderTexture; Vector<Sprite*> _brushs; }; #endif // __HELLOWORLD_SCENE_H__
然后修改HelloWorld.cpp文件
#include "HelloWorldScene.h" USING_NS_CC; Scene* HelloWorld::createScene() { // 'scene' is an autorelease object auto scene = Scene::create(); // 'layer' is an autorelease object auto layer = HelloWorld::create(); // add layer as a child to scene scene->addChild(layer); // return the scene return scene; } // on "init" you need to initialize your instance bool HelloWorld::init() { if ( !Layer::init() ) { return false; } Size visibleSize = Director::getInstance()->getVisibleSize(); Vec2 origin = Director::getInstance()->getVisibleOrigin(); auto closeItem = MenuItemImage::create( "CloseNormal.png", "CloseSelected.png", CC_CALLBACK_1(HelloWorld::menuCloseCallback, this)); closeItem->setPosition(Vec2(origin.x + visibleSize.width - closeItem->getContentSize().width/2 , origin.y + closeItem->getContentSize().height/2)); auto menu = Menu::create(closeItem, NULL); menu->setPosition(Vec2::ZERO); this->addChild(menu, 1); auto label = Label::createWithTTF("Test Eraser", "fonts/Marker Felt.ttf", 24); label->setPosition(Vec2(origin.x + visibleSize.width/2, origin.y + visibleSize.height - label->getContentSize().height)); this->addChild(label, 1); sprFore = Sprite::create("HelloWorld.png"); sprFore->setPosition(Vec2(visibleSize / 2) + origin); sprFore->retain(); renderTexture = RenderTexture::create(visibleSize.width, visibleSize.height, Texture2D::PixelFormat::RGBA8888); renderTexture->setContentSize(visibleSize); renderTexture->retain(); this->addChild(renderTexture); renderTexture->setPosition(Vec2(visibleSize / 2) + origin); renderTexture->beginWithClear(0, 0, 0, 0); sprFore->visit(); renderTexture->end(); auto listener = EventListenerTouchAllAtOnce::create(); listener->onTouchesMoved = CC_CALLBACK_2(HelloWorld::onTouchesMoved, this); _eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this); //不断判断是否擦除完毕 schedule(schedule_selector(HelloWorld::myUpdate), 0.5f); return true; } void HelloWorld::menuCloseCallback(Ref* pSender) { #if (CC_TARGET_PLATFORM == CC_PLATFORM_WP8) || (CC_TARGET_PLATFORM == CC_PLATFORM_WINRT) MessageBox("You pressed the close button. Windows Store Apps do not implement a close button.","Alert"); return; #endif Director::getInstance()->end(); #if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS) exit(0); #endif } void HelloWorld::myUpdate(float dt) { if (myIsDataClear(renderTexture) == true) { log("image is clear !"); } if (myIsDataClearInRect(renderTexture,300,200,50,50) == true) { log("image in rect is clear !"); } } void HelloWorld::onTouchesMoved(const std::vector<Touch*>& touches, Event* event) { auto touch = touches[0]; auto start = touch->getLocation(); auto end = touch->getPreviousLocation(); // begin drawing to the render texture renderTexture->begin(); // for extra points, we'll draw this smoothly from the last position and vary the sprite's // scale/rotation/offset float distance = start.getDistance(end); if (distance > 1) { int d = (int)distance; _brushs.clear(); for (int i = 0; i < d; ++i) { //橡皮擦 auto sprite = CCSprite::create("red.png");//主要根据图片定义橡皮擦的形状 BlendFunc blendFunc; blendFunc.src = GL_ZERO; blendFunc.dst = GL_ONE_MINUS_SRC_ALPHA; sprite->setBlendFunc(blendFunc); sprite->setScale(1.8f); renderTexture->addChild(sprite); _brushs.pushBack(sprite); } for (int i = 0; i < d; i++) { float difx = end.x - start.x; float dify = end.y - start.y; float delta = (float)i / distance; _brushs.at(i)->setPosition(Vec2(start.x + (difx * delta), start.y + (dify * delta))); _brushs.at(i)->visit(); } } // finish drawing and return context back to the screen renderTexture->end(); } bool HelloWorld::myIsDataClear(RenderTexture *pRenderTexture) { bool m_bEraserOk = false; Image* image = new Image(); image = pRenderTexture->newImage(true); int m = 3; if (image->hasAlpha()) { m = 4; } unsigned char *data_ = image->getData(); int x = 0, y = 0; /// 这里要提醒一点,即Opengl下,其中心点坐标在左上角 for (x = 0; x < pRenderTexture->getContentSize().width; ++x) { for (y = 0; y < pRenderTexture->getContentSize().height; ++y) { //获取每个点的像素点值 unsigned char *pixel = data_ + (x + y * image->getWidth()) * m; // You can see/change pixels' RGBA value(0-255) here ! 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) { m_bEraserOk = false; break; } } //如果改列 有一个点的像素点值不为零 跳出 if (pRenderTexture->getContentSize().height != y) { break; } } //如果所有点的像素点值都为0 则擦除完毕 if (x == pRenderTexture->getContentSize().width && y == pRenderTexture->getContentSize().height) { m_bEraserOk = true; } delete image; return m_bEraserOk; } bool HelloWorld::myIsDataClearInRect(RenderTexture *pRenderTexture, int x, int y, int width, int height) { bool m_bEraserOk = false; Image* image = new Image(); image = pRenderTexture->newImage(true); int m = 3; if (image->hasAlpha()) { m = 4; } int i = 0, j = 0; unsigned char* mdata = (unsigned char*)image->getData(); for (i = 0; i < width; ++i) { for (j = 0; j < height; ++j) { unsigned char *pixel = mdata + (i + x + (image->getHeight() - y - (height - j)) * image->getWidth()) * m; // You can see/change pixels' RGBA value(0-255) here ! 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) { break; } } if (height != j) { break; } } if (i == width && j == height) { m_bEraserOk = true; } return m_bEraserOk; }
看下运行效果
加载全部内容