最近研究了一下像素级的触摸处理,有时候我们用一个不规则的图形作为一个按钮,这个不规则的图形是一张矩形的png图片,很可能图片的实际有效的显示内容只占整个png图片的很小一部分,剩下的大部分都是png图片的透明区域,我们想把这部分透明区域过滤掉,实现一个触摸到真实的内容才会有按钮响应的效果。
刚开始试图通过CCSprite直接获取到纹理的像素信息,但是Cocos2d-x并没有给我们提供直接通过CCSprite获取像素信息的接口,研究了几个网上的Demo,发现通过使用RenderTexture重绘可以实现这一效果,下面把代码贴出来。
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
|
#include"HelloWorldScene.h"
#include"SimpleAudioEngine.h"
using
namespace
cocos2d;
CocosDenshion;
CCScene*HelloWorld::scene()
{
//'scene'isanautoreleaSEObject
CCScene*scene=CCScene::create();
//'layer'isanautoreleaSEObject
HelloWorld*layer=HelloWorld::create();
//addlayerasachildtoscene
scene->addChild(layer);
//returnthescene
return
scene;
}
bool
HelloWorld::init()
{
if
(!CCLayer::init()){
return
false
;
}
this
->setTouchEnabled(
true
);
->m_imgMan=CCSprite::create(
"man.png"
);
->m_imgMan->setPosition(ccp(400,200));
->addChild(
->m_imgMan,1);
->m_pRenderTexture=CCRenderTexture::create(
->m_imgMan->getContentSize().width,
->m_imgMan->getContentSize().height,kCCTexture2DPixelFormat_RGBA8888);
->m_pRenderTexture->ignoreAnchorPointForPosition(
);
->m_pRenderTexture->setPosition(ccp(400,200));
->m_pRenderTexture->setAnchorPoint(CCPointZero);
->m_pRenderTexture,1);
;
}
HelloWorld::ccTouchBegan(cocos2d::CCTouch*pTouch,cocos2d::CCEvent*pEvent){
isTouched=
;
CCPointtouchPoint=pTouch->getLocationInView();
CCPointglPoint=CCDirector::sharedDirector()->convertToGL(touchPoint);
(
->m_imgMan->boundingBox().containsPoint(glPoint)){
ccColor4Bcolor4B={0,0};
CCPointnodePos=
->m_imgMan->convertTouchToNodeSpace(pTouch);
unsigned
int
x=nodePos.x;
y=
->m_imgMan->getContentSize().height-nodePos.y;
CCPointpoint=
->m_imgMan->getPosition();
//开始准备绘制
->m_pRenderTexture->begin();
//绘制使用的临时精灵,与原图是同一图片
CCSprite*pTempSpr=CCSprite::createWithSpriteFrame(
->m_imgMan->displayFrame());
pTempSpr->setPosition(ccp(pTempSpr->getContentSize().width/2,pTempSpr->getContentSize().height/2));
//绘制
pTempSpr->visit();
//结束绘制
->m_pRenderTexture->end();
//通过画布拿到这张画布上每个像素点的信息,封装到CCImage中
CCImage*pImage=
->m_pRenderTexture->newCCImage();
//获取像素数据
char
*data_=pImage->getData();
*pixel=(unsigned
*)data_;
pixel=pixel+(y*(
)pTempSpr->getContentSize().width)*1+x*1;
//R通道
color4B.r=*pixel&0xff;
//G通道
color4B.g=(*pixel>>8)&0xff;
//B通过
color4B.b=(*pixel>>16)&0xff;
//Alpha通道,我们有用的就是Alpha
color4B.a=(*pixel>>24)&0xff;
CCLOG(
"当前点击的点的:alpha=%d"
,color4B.a);
(color4B.a>50){
;
}
else
{
;
}
//绘制完成后清理画布的内容
->m_pRenderTexture->clear(0,0);
}
->m_pLabTips){
->m_pLabTips->removeFromParentAndCleanup(
);
->m_pLabTips=NULL;
}
isTouched;
}
void
HelloWorld::ccTouchEnded(cocos2d::CCTouch*pTouch,cocos2d::CCEvent*pEvent){
->m_pLabTips){
);
->m_pLabTips=NULL;
}
->m_pLabTips=CCLabelTTF::create(
"点击到非透明的像素点"
"Courier"
->m_pLabTips->setPosition(ccp(300.0f,100.0f));
->m_pLabTips->setColor(ccYELLOW);
->m_pLabTips,1);
}
HelloWorld::registerWithTouchDispatcher(){
CCDirector::sharedDirector()->getTouchDispatcher()->addTargetedDelegate(
);
}
|
当点击到了有色点时,我让屏幕上显示黄字提示,并观察打印日志信息:
当点击到了透明的黑色区域时,屏幕上不显示任何文字,观察打印日志信息:
实现的原理:我通过点击的时候把图片进行重绘,重绘的过程中,可以通过RenderTexture也就是画布,把整个画布上的像素点信息全部拿到,我让绘制的内容和画布的大小是一样的,所以就能保证画布上的每一个像素点就是我想要绘制的图片的像素点,然后通过判断像素点的alpha通道值,来确定这个点是否是透明色的,如果是透明色则不做触摸响应。
原文链接:https://www.f2er.com/cocos2dx/340042.html