最近研究了一下透明图片的点击事件即png图片中透明区域的点击。当时用j2me的时候,记得设置个值就可以处理是像素点击还是图片点击,不对,是碰撞检测。看了看jdk,它处理了像素,处理如下:
- public void handlesinglepixel(int x, int y, int pixel) {
- int alpha = (pixel >> 24) & 0xff;
- int red = (pixel >> 16) & 0xff;
- int green = (pixel >> 8) & 0xff;
- int blue = (pixel ) & 0xff;
- // Deal with the pixel as necessary...
- }
复制代码
这时候使用的像素格式是ARGB。
- bool CCTexture2D::initPremultipliedATextureWithImage(CCImage *image, unsigned int width, unsigned int height)
-
- {
-
- unsigned char* tempData = image->getData();
-
- this->setFDImageData(tempData);
-
- unsigned int* inPixel32 = NULL;
-
- unsigned char* inPixel8 = NULL;
-
- unsigned short* outPixel16 = NULL;
-
- bool hasAlpha = image->hasAlpha();
-
- CCSize imageSize = CCSizeMake((float)(image->getWidth()), (float)(image->getHeight()));
-
- CCTexture2DPixelFormat pixelFormat;
-
- size_t bpp = image->getBitsPerComponent();
-
- // compute pixel format
-
- if(hasAlpha)
-
- {
-
- pixelFormat = g_defaultAlphaPixelFormat;
-
- }
-
- else
-
- {
-
- if (bpp >= 8)
-
- {
-
- pixelFormat = kCCTexture2DPixelFormat_RGB888;
-
- }
-
- else
-
- {
-
- pixelFormat = kCCTexture2DPixelFormat_RGB565;
-
- }
-
- }
-
- // Repack the pixel data into the right format
-
- unsigned int length = width * height;
-
- if (pixelFormat == kCCTexture2DPixelFormat_RGB565)
-
- {
-
- if (hasAlpha)
-
- {
-
- // Convert "RRRRRRRRRGGGGGGGGBBBBBBBBAAAAAAAA" to "RRRRRGGGGGGBBBBB"
-
- tempData = new unsigned char[width * height * 2];
-
- outPixel16 = (unsigned short*)tempData;
-
- inPixel32 = (unsigned int*)image->getData();
-
- for(unsigned int i = 0; i < length; ++i, ++inPixel32) { *outPixel16++ = ((((*inPixel32 >> 0) & 0xFF) >> 3) << 11) | // R ((((*inPixel32 >> 8) & 0xFF) >> 2) << 5) | // G ((((*inPixel32 >> 16) & 0xFF) >> 3) << 0); // B } } else { // Convert "RRRRRRRRRGGGGGGGGBBBBBBBB" to "RRRRRGGGGGGBBBBB" tempData = new unsigned char[width * height * 2]; outPixel16 = (unsigned short*)tempData; inPixel8 = (unsigned char*)image->getData();
-
- for(unsigned int i = 0; i < length; ++i) { *outPixel16++ = (((*inPixel8++ & 0xFF) >> 3) << 11) | // R (((*inPixel8++ & 0xFF) >> 2) << 5) | // G (((*inPixel8++ & 0xFF) >> 3) << 0); // B } } } else if (pixelFormat == kCCTexture2DPixelFormat_RGBA4444) { // Convert "RRRRRRRRRGGGGGGGGBBBBBBBBAAAAAAAA" to "RRRRGGGGBBBBAAAA" inPixel32 = (unsigned int*)image->getData();
-
- tempData = new unsigned char[width * height * 2];
-
- outPixel16 = (unsigned short*)tempData;
-
- for(unsigned int i = 0; i < length; ++i, ++inPixel32) { *outPixel16++ = ((((*inPixel32 >> 0) & 0xFF) >> 4) << 12) | // R ((((*inPixel32 >> 8) & 0xFF) >> 4) << 8) | // G ((((*inPixel32 >> 16) & 0xFF) >> 4) << 4) | // B ((((*inPixel32 >> 24) & 0xFF) >> 4) << 0); // A } } else if (pixelFormat == kCCTexture2DPixelFormat_RGB5A1) { // Convert "RRRRRRRRRGGGGGGGGBBBBBBBBAAAAAAAA" to "RRRRRGGGGGBBBBBA" inPixel32 = (unsigned int*)image->getData();
-
- tempData = new unsigned char[width * height * 2];
-
- outPixel16 = (unsigned short*)tempData;
-
- for(unsigned int i = 0; i < length; ++i, ++inPixel32) { *outPixel16++ = ((((*inPixel32 >> 0) & 0xFF) >> 3) << 11) | // R ((((*inPixel32 >> 8) & 0xFF) >> 3) << 6) | // G ((((*inPixel32 >> 16) & 0xFF) >> 3) << 1) | // B ((((*inPixel32 >> 24) & 0xFF) >> 7) << 0); // A } } else if (pixelFormat == kCCTexture2DPixelFormat_A8) { // Convert "RRRRRRRRRGGGGGGGGBBBBBBBBAAAAAAAA" to "AAAAAAAA" inPixel32 = (unsigned int*)image->getData();
-
- tempData = new unsigned char[width * height];
-
- unsigned char *outPixel8 = tempData;
-
- for(unsigned int i = 0; i < length; ++i, ++inPixel32) { *outPixel8++ = (*inPixel32 >> 24) & 0xFF; // A
-
- }
-
- }
-
- if (hasAlpha && pixelFormat == kCCTexture2DPixelFormat_RGB888)
-
- {
-
- // Convert "RRRRRRRRRGGGGGGGGBBBBBBBBAAAAAAAA" to "RRRRRRRRGGGGGGGGBBBBBBBB"
-
- inPixel32 = (unsigned int*)image->getData();
-
- tempData = new unsigned char[width * height * 3];
-
- unsigned char *outPixel8 = tempData;
-
- for(unsigned int i = 0; i < length; ++i, ++inPixel32) { *outPixel8++ = (*inPixel32 >> 0) & 0xFF; // R
-
- *outPixel8++ = (*inPixel32 >> 8) & 0xFF; // G
-
- *outPixel8++ = (*inPixel32 >> 16) & 0xFF; // B
-
- }
-
- }
-
- initWithData(tempData, pixelFormat, width, height, imageSize);
-
- if (tempData != image->getData())
-
- {
-
- delete [] tempData;
-
- }
-
- m_bHasPremultipliedAlpha = image->isPremultipliedAlpha();
-
- return true;
-
- }
复制代码
那么,在2dx中,我们也是可以这么处理的,首先看纹理中的一个函数: 这里面针对kCCTexture2DPixelFormat_RGB888像素格式的图片进行了这么的处理:
- *outPixel8++ = (*inPixel32 >> 0) & 0xFF; // R
-
- *outPixel8++ = (*inPixel32 >> 8) & 0xFF; // G
-
- *outPixel8++ = (*inPixel32 >> 16) & 0xFF; // B
复制代码
那么,我们就可以考虑在点击事件中处理这个透明区域的问题了,began事件如下:
- bool FDPixelSprite::ccTouchBegan(cocos2d::CCTouch *pTouch, cocos2d::CCEvent *pEvent)
-
- {
-
- if (this->isContainTouchLocation(pTouch) ) {
-
- ccColor4B c = {0, 0, 0, 0};
-
- CCSize winSize = CCDirector::sharedDirector()->getWinSize();
-
- CCPoint touchPoint = pTouch->getLocationInView();
-
- CCSize cSize = this->getContentSize();
-
- CCPoint pos(this->getPositionX() - cSize.width/2,winSize.height-this->getPositionY()- cSize.height/2);
-
- CCPoint localPoint = ccp(touchPoint.x - pos.x,
-
- touchPoint.y -pos.y);
-
- unsigned int x = localPoint.x, y = localPoint.y;
-
- unsigned char *data_ = this->getTexture()->getFDImageData();
-
- unsigned int *pixel = (unsigned int *)data_;
-
- pixel = pixel + (y * (int)this->getContentSize().width)* 1 + x * 1;
-
- c.r = *pixel & 0xff;
-
- c.g = (*pixel >> 8) & 0xff;
-
- c.b = (*pixel >> 16) & 0xff;
-
- c.a = (*pixel >> 24) & 0xff;
-
- if (c.a == 0) {
-
- CCLog("firedragonpzy:ccTouchBegan");
-
- return false;
-
- }else
-
- {
-
- return true;
-
- }
-
- }
-
- return false;
-
- }
复制代码
处理原理: 获取点击的像素,判断当前的a值是否为0,若为0,则是透明区域。 注意点: 图片的坐标原点在图片的左上角,这里大家需要做一下坐标的转化,把点击屏幕的坐标转化为相对于图像左上角的坐标即可。 关于图像,它的颜色表示分为:R、G、B、A四部分,各占八位。 代码中:*pixel >> (n)bit,为了得到单独的red,green,blue,alpha值,具体得到什么,目前不是很清楚,貌似什么进制【时间原因,改日谈……】不过可以给大家提供个例子。 网上例子(jdk): 比如大红色用整数表示就是00 FF 00 00 pixel >> somebits是为了得到单独的alpha,red,green,blue值 右移24与255与操作得到alpha 16位得到red…… 如果不& 0xff的话,上面的int green = (pixel >> 8) & 0xff; 得到的green值是FF 00 也就是65280,当然就不是我们要得到值 与操作是为了把高位削去!!!! 【因为pixel是一个整数 图像的表示分四部分:alpha值,red,green,blue 每一个值占一个字节,一个字节有8位二进制】 求解释……欢迎拍砖…… 推荐阅读:http://www.cocos2d-x.org/boards/6/topics/3472 注意啦,注意啦,下面还有个赠送篇、、、、【产生赠送篇的缘由:一群友说如果设置了锚点,怎么处理啊,那代码起不是不对了,所以我又产生了赠送篇,不过使用精灵的时候,基本都是以(0.5,0.5)为锚点,我开始没考虑这问题是源于这,呵呵,假设你锚点不是(0.5,0.5)旋转什么的可能就……效果不好。不过既然有不是CCPointZero的需求,我就写了支持不同锚点的FDPixelSprite,不过建议大家使用针对锚点为(0.5,0.5)的,效率高……】 现在贴出我的FDPixelSprite,大家可以直接使用此精灵处理含有透明区域图片的点击问题: FDPixelSprite.h
- //
-
- // FDPixelSprite.h
-
- // PixelDemo
-
- //
-
- // Created by firedragonpzy on 13-2-19.
-
- //
-
- //
-
- #ifndef __PixelDemo__FDPixelSprite__
-
- #define __PixelDemo__FDPixelSprite__
-
- #include "cocos2d.h"
-
- USING_NS_CC;
-
- class FDPixelSprite : public CCSprite, public CCTargetedTouchDelegate {
-
- public:
-
- FDPixelSprite();
-
- virtual ~FDPixelSprite();
-
- void onEnter();
-
- void onExit();
-
- static FDPixelSprite* create( const char *pszFileName );
-
- CCRect atlasRect();
-
- bool isContainTouchLocation(CCTouch *pTouch);
-
- bool ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent);
-
- void ccTouchMoved(CCTouch *pTouch, CCEvent *pEvent);
-
- void ccTouchEnded(CCTouch *pTouch, CCEvent *pEvent);
-
- CC_SYNTHESIZE(const char*, m_pName,Name);
-
- };
-
- #endif /* defined(__PixelDemo__FDPixelSprite__) */
复制代码
FDPixelSprite.cpp
- //
-
- // FDPixelSprite.cpp
-
- // PixelDemo
-
- //
-
- // Created by firedragonpzy on 13-2-19.
-
- //
-
- //
-
- #include "FDPixelSprite.h"
-
- FDPixelSprite::FDPixelSprite()
-
- {}
-
- FDPixelSprite::~FDPixelSprite()
-
- {}
-
- FDPixelSprite* FDPixelSprite::create(const char *pszFileName)
-
- {
-
- FDPixelSprite *sprite = new FDPixelSprite();
-
- if (sprite && sprite->initWithFile(pszFileName)) {
-
- sprite->setName(pszFileName);
-
- sprite->autorelease();
-
- return sprite;
-
- }
-
- CC_SAFE_DELETE(sprite);
-
- sprite = NULL;
-
- return NULL;
-
- }
-
- void FDPixelSprite::onEnter()
-
- {
-
- CCSprite::onEnter();
-
- CCDirector::sharedDirector()->getTouchDispatcher()->addTargetedDelegate(this, 0, true);
-
- }
-
- void FDPixelSprite::onExit()
-
- {
-
- CCSprite::onExit();
-
- CCDirector::sharedDirector()->getTouchDispatcher()->removeDelegate(this);
-
- }
-
- bool FDPixelSprite::ccTouchBegan(cocos2d::CCTouch *pTouch, cocos2d::CCEvent *pEvent)
-
- {
-
- if (this->isContainTouchLocation(pTouch) ) {
-
- ccColor4B c = {0, 0, 0, 0};
-
- CCSize winSize = CCDirector::sharedDirector()->getWinSize();
-
- CCPoint touchPoint = pTouch->getLocationInView();
-
- CCSize cSize = this->getContentSize();
-
- CCPoint pos(this->getPositionX() - cSize.width/2,winSize.height-this->getPositionY()- cSize.height/2);
-
- CCPoint localPoint = ccp(touchPoint.x - pos.x,
-
- touchPoint.y -pos.y);
-
- unsigned int x = localPoint.x, y = localPoint.y;
-
- unsigned char *data_ = this->getTexture()->getFDImageData();
-
- unsigned int *pixel = (unsigned int *)data_;
-
- pixel = pixel + (y * (int)this->getContentSize().width)* 1 + x * 1;
-
- c.r = *pixel & 0xff;
-
- c.g = (*pixel >> 8) & 0xff;
-
- c.b = (*pixel >> 16) & 0xff;
-
- c.a = (*pixel >> 24) & 0xff;
-
- if (c.a == 0) {
-
- CCLog("firedragonpzy:ccTouchBegan");
-
- return false;
-
- }else
-
- {
-
- return true;
-
- }
-
- }
-
- return false;
-
- }
-
- void FDPixelSprite::ccTouchMoved(cocos2d::CCTouch *pTouch, cocos2d::CCEvent *pEvent)
-
- {
-
- CCPoint pos = this->getPosition();
-
- CCPoint sub = pTouch->getDelta();
-
- this->setPosition(ccpAdd(pos, sub));
-
- }
-
- void FDPixelSprite::ccTouchEnded(cocos2d::CCTouch *pTouch, cocos2d::CCEvent *pEvent)
-
- {
-
- CCLog("firedragonpzy:ccTouchEnded");
-
- }
-
- CCRect FDPixelSprite::atlasRect()
-
- {
-
- CCSize cSize = this->getContentSize();
-
- return CCRectMake(-cSize.width/2, -cSize.height/2, cSize.width, cSize.height);
-
- }
-
- bool FDPixelSprite::isContainTouchLocation(cocos2d::CCTouch *pTouch)
-
- {
-
- return this->atlasRect().containsPoint(convertTouchToNodeSpaceAR(pTouch));
-
- }
复制代码
————————————–赠送篇———————————————- 为什么产生赠送篇 ,上面已经解释的很清楚了,不废话了,开门见山: 改为适配不同锚点需要改动两个地方: (一):区域的判断:
- CCRect FDPixelSprite::atlasRect()
-
- {
-
- CCSize cSize = this->getContentSize();
-
- CCPoint point = this->getAnchorPointInPoints();
-
- return CCRectMake( -point.x, -point.y, cSize.width,cSize.height);
-
- }
复制代码
(二)相对于图片像素的转化
- bool FDPixelSprite::ccTouchBegan(cocos2d::CCTouch *pTouch, cocos2d::CCEvent *pEvent)
-
- {
-
- if (this->isContainTouchLocation(pTouch) ) {
-
- ccColor4B c = {0, 0, 0, 0};
-
- CCSize winSize = CCDirector::sharedDirector()->getWinSize();
-
- CCPoint touchPoint = pTouch->getLocationInView();
-
- CCSize cSize = this->getContentSize();
-
- CCPoint point =this->getAnchorPointInPoints();
-
- point = ccp(cSize.width - point.x,cSize.height- point.y);
-
- CCPoint pos(this->getPositionX() - point.x,winSize.height-this->getPositionY()- point.y);
-
- CCPoint localPoint = ccp(touchPoint.x - pos.x,
-
- touchPoint.y -pos.y);
-
- unsigned int x = localPoint.x, y = localPoint.y;
-
- unsigned char *data_ = this->getTexture()->getFDImageData();
-
- unsigned int *pixel = (unsigned int *)data_;
-
- pixel = pixel + (y * (int)this->getContentSize().width)* 1 + x * 1;
-
- c.r = *pixel & 0xff;
-
- c.g = (*pixel >> 8) & 0xff;
-
- c.b = (*pixel >> 16) & 0xff;
-
- c.a = (*pixel >> 24) & 0xff;
-
- if (c.a == 0) {
-
- CCLog("firedragonpzy:ccTouchBegan----------");
-
- return false;
-
- }else
-
- {
-
- return true;
-
- }
-
- }
-
- return false;
-
- }
|