cocos2dx实现橡皮擦效果以及判断是否擦除完毕

时间:2022-05-21 12:22:32

本文实例为大家分享了cocos2dx实现橡皮擦效果,以及判断是否擦除完毕,供大家参考,具体内容如下

首先修改HelloWorld.h文件

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#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文件

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
#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;
}

看下运行效果

cocos2dx实现橡皮擦效果以及判断是否擦除完毕

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持服务器之家。

原文链接:https://blog.csdn.net/u011416077/article/details/45312731