cocos2d-x像素级触摸处理
cocos2d-x像素级触摸处理
piggybear 发表于3年前
cocos2d-x像素级触摸处理
  • 发表于 3年前
  • 阅读 9
  • 收藏 1
  • 点赞 0
  • 评论 0

新睿云服务器60天免费使用,快来体验!>>>   

最近研究了一下像素级的触摸处理,有时候我们用一个不规则的图形作为一个按钮,这个不规则的图形是一张矩形的png图片,很可能图片的实际有效的显示内容只占整个png图片的很小一部分,剩下的大部分都是png图片的透明区域,我们想把这部分透明区域过滤掉,实现一个触摸到真实的内容才会有按钮响应的效果。

刚开始试图通过CCSprite直接获取到纹理的像素信息,但是cocos2d-x并没有给我们提供直接通过CCSprite获取像素信息的接口,研究了几个网上的Demo,发现通过使用RenderTexture重绘可以实现这一效果,下面把代码贴出来。

[cpp]  view plain copy
  1. #include "HelloWorldScene.h"  
  2. #include "SimpleAudioEngine.h"  
  3.   
  4. using namespace cocos2d;  
  5. using namespace CocosDenshion;  
  6.   
  7. CCScene* HelloWorld::scene()  
  8. {  
  9.     // 'scene' is an autorelease object  
  10.     CCScene *scene = CCScene::create();  
  11.       
  12.     // 'layer' is an autorelease object  
  13.     HelloWorld *layer = HelloWorld::create();  
  14.   
  15.     // add layer as a child to scene  
  16.     scene->addChild(layer);  
  17.   
  18.     // return the scene  
  19.     return scene;  
  20. }  
  21.   
  22. bool HelloWorld::init()  
  23. {  
  24.     if (!CCLayer::init()){  
  25.         return false;  
  26.     }  
  27.       
  28.     this->setTouchEnabled(true);  
  29.   
  30.     this->m_imgMan = CCSprite::create("man.png");  
  31.     this->m_imgMan->setPosition(ccp(400, 200));  
  32.     this->addChild(this->m_imgMan, 1);  
  33.       
  34.     this->m_pRenderTexture = CCRenderTexture::create(this->m_imgMan->getContentSize().width, this->m_imgMan->getContentSize().height, kCCTexture2DPixelFormat_RGBA8888);  
  35.     this->m_pRenderTexture->ignoreAnchorPointForPosition(true);  
  36.     this->m_pRenderTexture->setPosition(ccp(400, 200));  
  37.     this->m_pRenderTexture->setAnchorPoint(CCPointZero);  
  38.     this->addChild(this->m_pRenderTexture, 0, 1);  
  39.   
  40.       
  41.     return true;  
  42. }  
  43.   
  44. bool HelloWorld::ccTouchBegan(cocos2d::CCTouch *pTouch, cocos2d::CCEvent *pEvent) {  
  45.       
  46.     bool isTouched = false;  
  47.       
  48.     CCPoint touchPoint = pTouch->getLocationInView();  
  49.     CCPoint glPoint = CCDirector::sharedDirector()->convertToGL(touchPoint);  
  50.   
  51.   
  52.     if (this->m_imgMan->boundingBox().containsPoint(glPoint)) {  
  53.       
  54.         ccColor4B color4B = {0, 0, 0, 0};  
  55.           
  56.         CCPoint nodePos = this->m_imgMan->convertTouchToNodeSpace(pTouch);  
  57.         unsigned int x = nodePos.x;  
  58.         unsigned int y = this->m_imgMan->getContentSize().height - nodePos.y;  
  59.           
  60.         CCPoint point = this->m_imgMan->getPosition();  
  61.         //开始准备绘制  
  62.         this->m_pRenderTexture->begin();  
  63.         //绘制使用的临时精灵,与原图是同一图片  
  64.         CCSprite* pTempSpr = CCSprite::createWithSpriteFrame(this->m_imgMan->displayFrame());  
  65.         pTempSpr->setPosition(ccp(pTempSpr->getContentSize().width / 2, pTempSpr->getContentSize().height / 2));  
  66.         //绘制  
  67.         pTempSpr->visit();  
  68.         //结束绘制  
  69.         this->m_pRenderTexture->end();  
  70.         //通过画布拿到这张画布上每个像素点的信息,封装到CCImage中  
  71.         CCImage* pImage = this->m_pRenderTexture->newCCImage();  
  72.         //获取像素数据  
  73.         unsigned char* data_ = pImage->getData();  
  74.         unsigned int *pixel = (unsigned int *)data_;  
  75.         pixel = pixel + (y * (int)pTempSpr->getContentSize().width) * 1 + x * 1;  
  76.         //R通道  
  77.         color4B.r = *pixel & 0xff;  
  78.         //G通道  
  79.         color4B.g = (*pixel >> 8) & 0xff;  
  80.         //B通过  
  81.         color4B.b = (*pixel >> 16) & 0xff;  
  82.         //Alpha通道,我们有用的就是Alpha  
  83.         color4B.a = (*pixel >> 24) & 0xff;  
  84.           
  85.         CCLOG("当前点击的点的: alpha = %d", color4B.a);  
  86.           
  87.         if (color4B.a > 50) {  
  88.             isTouched = true;  
  89.         } else {  
  90.             isTouched = false;  
  91.         }  
  92.           
  93.         //绘制完成后清理画布的内容  
  94.         this->m_pRenderTexture->clear(0, 0, 0, 0);  
  95.     }  
  96.       
  97.       
  98.     if (this->m_pLabTips) {  
  99.         this->m_pLabTips->removeFromParentAndCleanup(true);  
  100.         this->m_pLabTips = NULL;  
  101.     }  
  102.       
  103.     return isTouched;  
  104. }  
  105.   
  106.   
  107. void HelloWorld::ccTouchEnded(cocos2d::CCTouch *pTouch, cocos2d::CCEvent *pEvent) {  
  108.       
  109.     if (this->m_pLabTips) {  
  110.         this->m_pLabTips->removeFromParentAndCleanup(true);  
  111.         this->m_pLabTips = NULL;  
  112.     }  
  113.       
  114.     this->m_pLabTips = CCLabelTTF::create("点击到非透明的像素点""Courier", 30);  
  115.     this->m_pLabTips->setAnchorPoint(CCPointZero);  
  116.     this->m_pLabTips->setPosition(ccp(300.0f, 100.0f));  
  117.     this->m_pLabTips->setColor(ccYELLOW);  
  118.     this->addChild(this->m_pLabTips, 1);  
  119.   
  120. }  
  121.   
  122. void HelloWorld::registerWithTouchDispatcher() {  
  123.     CCDirector::sharedDirector()->getTouchDispatcher()->addTargetedDelegate(this, CCLayer::getTouchPriority(), false);  
  124. }  
当点击到了有色点时,我让屏幕上显示黄字提示,并观察打印日志信息:



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



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



  • 打赏
  • 点赞
  • 收藏
  • 分享
共有 人打赏支持
粉丝 3
博文 237
码字总数 37552
×
piggybear
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
* 金额(元)
¥1 ¥5 ¥10 ¥20 其他金额
打赏人
留言
* 支付类型
微信扫码支付
打赏金额:
已支付成功
打赏金额: