cocos2d-x像素級觸摸處理,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);}當點擊到了有色點時,我讓螢幕上顯示黃字提示,並觀察列印日誌資訊:
當點擊到了透明的黑色地區時,螢幕上不顯示任何文字,觀察列印日誌資訊:
實現的原理:我通過點擊的時候把圖片進行重繪,重繪的過程中,可以通過RenderTexture也就是畫布,把整個畫布上的像素點資訊全部拿到,我讓繪製的內容和畫布的大小是一樣的,所以就能保證畫布上的每一個像素點就是我想要繪製的圖片的像素點,然後通過判斷像素點的alpha通道值,來確定這個點是否是透明色的,如果是透明色則不做觸摸響應。
本文由CC原創總結,如需轉載請註明出處:http://blog.csdn.net/oktears/article/details/37993871
cocos2d-x多點觸摸編譯問題
建議在例子基礎上修改工程檔案,可以避免這些錯誤
cocos2d-x中在最上層添加一個新的Layer, 怎把其他層的觸摸全部屏蔽
應該你可以設定這個layer的TouchHandle的swallowsTouches為YES,這樣就吞下了這個touch,其他的層就不再響應了,就CCMenuItem一樣的處理方法,你可以試一下。
希望能協助到你。