cocos2dx 实现橡皮擦效果以及判断何时擦除完毕

来源:互联网 发布:java时间戳精确到秒 编辑:程序博客网 时间:2024/06/05 15:27

首先修改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 instancebool 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 texturerenderTexture->begin();// for extra points, we'll draw this smoothly from the last position and vary the sprite's// scale/rotation/offsetfloat 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 screenrenderTexture->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;}

看下运行效果





0 0
原创粉丝点击