cocos2d-x像素级触摸处理

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

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

#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);
}

这里我们把alpha通道的值小于50的像素点都视为同名的点,当点击到了透明的黑色区域时,屏幕上不显示任何文字,点击到有色区域时,观察打印日志信息:


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


本文由CC原创总结,如需转载请注明出处:http://blog.csdn.net/oktears/article/details/37993871


转自:http://blog.csdn.net/oktears/article/details/37993871
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值