Cocos2d-x像素级触摸处理

最近研究了一下像素级的触摸处理,有时候我们用一个不规则的图形作为一个按钮,这个不规则的图形是一张矩形的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;  
using  namespace  CocosDenshion;  
   
CCScene* HelloWorld::scene()  
{  
     // 'scene' is an autorelease object  
     CCScene *scene = CCScene::create();  
       
     // 'layer' is an autorelease object  
     HelloWorld *layer = HelloWorld::create();  
   
     // add layer as a child to scene  
     scene->addChild(layer);  
   
     // return the scene  
     return  scene;  
}  
   
bool  HelloWorld::init()  
{  
     if  (!CCLayer::init()){  
         return  false ;  
     }  
       
     this ->setTouchEnabled( true );  
   
     this ->m_imgMan = CCSprite::create( "man.png" );  
     this ->m_imgMan->setPosition(ccp(400, 200));  
     this ->addChild( this ->m_imgMan, 1);  
       
     this ->m_pRenderTexture = CCRenderTexture::create( this ->m_imgMan->getContentSize().width,  this ->m_imgMan->getContentSize().height, kCCTexture2DPixelFormat_RGBA8888);  
     this ->m_pRenderTexture->ignoreAnchorPointForPosition( true );  
     this ->m_pRenderTexture->setPosition(ccp(400, 200));  
     this ->m_pRenderTexture->setAnchorPoint(CCPointZero);  
     this ->addChild( this ->m_pRenderTexture, 0, 1);  
   
       
     return  true ;  
}  
   
bool  HelloWorld::ccTouchBegan(cocos2d::CCTouch *pTouch, cocos2d::CCEvent *pEvent) {  
       
     bool  isTouched =  false ;  
       
     CCPoint touchPoint = pTouch->getLocationInView();  
     CCPoint glPoint = CCDirector::sharedDirector()->convertToGL(touchPoint);  
   
   
     if  ( this ->m_imgMan->boundingBox().containsPoint(glPoint)) {  
       
         ccColor4B color4B = {0, 0, 0, 0};  
           
         CCPoint nodePos =  this ->m_imgMan->convertTouchToNodeSpace(pTouch);  
         unsigned  int  x = nodePos.x;  
         unsigned  int  y =  this ->m_imgMan->getContentSize().height - nodePos.y;  
           
         CCPoint point =  this ->m_imgMan->getPosition();  
         //开始准备绘制  
         this ->m_pRenderTexture->begin();  
         //绘制使用的临时精灵,与原图是同一图片  
         CCSprite* pTempSpr = CCSprite::createWithSpriteFrame( this ->m_imgMan->displayFrame());  
         pTempSpr->setPosition(ccp(pTempSpr->getContentSize().width / 2, pTempSpr->getContentSize().height / 2));  
         //绘制  
         pTempSpr->visit();  
         //结束绘制  
         this ->m_pRenderTexture->end();  
         //通过画布拿到这张画布上每个像素点的信息,封装到CCImage中  
         CCImage* pImage =  this ->m_pRenderTexture->newCCImage();  
         //获取像素数据  
         unsigned  char * data_ = pImage->getData();  
         unsigned  int  *pixel = (unsigned  int  *)data_;  
         pixel = pixel + (y * ( int )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);  
           
         if  (color4B.a > 50) {  
             isTouched =  true ;  
         else  {  
             isTouched =  false ;  
         }  
           
         //绘制完成后清理画布的内容  
         this ->m_pRenderTexture->clear(0, 0, 0, 0);  
     }  
       
       
     if  ( this ->m_pLabTips) {  
         this ->m_pLabTips->removeFromParentAndCleanup( true );  
         this ->m_pLabTips = NULL;  
     }  
       
     return  isTouched;  
}  
   
   
void  HelloWorld::ccTouchEnded(cocos2d::CCTouch *pTouch, cocos2d::CCEvent *pEvent) {  
       
     if  ( this ->m_pLabTips) {  
         this ->m_pLabTips->removeFromParentAndCleanup( true );  
         this ->m_pLabTips = NULL;  
     }  
       
     this ->m_pLabTips = CCLabelTTF::create( "点击到非透明的像素点" "Courier" , 30);  
     this ->m_pLabTips->setAnchorPoint(CCPointZero);  
     this ->m_pLabTips->setPosition(ccp(300.0f, 100.0f));  
     this ->m_pLabTips->setColor(ccYELLOW);  
     this ->addChild( this ->m_pLabTips, 1);  
   
}  
   
void  HelloWorld::registerWithTouchDispatcher() {  
     CCDirector::sharedDirector()->getTouchDispatcher()->addTargetedDelegate( this , CCLayer::getTouchPriority(),  false );  
}


当点击到了有色点时,我让屏幕上显示黄字提示,并观察打印日志信息:

1405906740364611.png

1405906772674450.png


当点击到了透明的黑色区域时,屏幕上不显示任何文字,观察打印日志信息:

1405906789928147.png

1405906811473941.png


实现的原理:我通过点击的时候把图片进行重绘,重绘的过程中,可以通过RenderTexture也就是画布,把整个画布上的像素点信息全部拿到,我让绘制的内容和画布的大小是一样的,所以就能保证画布上的每一个像素点就是我想要绘制的图片的像素点,然后通过判断像素点的alpha通道值,来确定这个点是否是透明色的,如果是透明色则不做触摸响应。


来源网址:http://blog.csdn.net/oktears/article/details/37993871


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值