小伟哥 遇到一个命题:
按钮透明区域过滤。当点击一个建筑按钮、花的时候不得不想一些方法把点击透明区域过滤掉。
让点击也没有效果滴啦。
开始搜索了半天才有所思路。
在网络上很多贴代码的。
http://blog.csdn.net/lwuit/article/details/40658347
整理后代码如下:
- bool CCMenu::CheckAlphaPoint(CCMenuItem* pChild,const CCPoint& point)
- {
- CCSize winSize = CCDirector::sharedDirector()->getWinSize();
- CCNode* selectSprite = ((CCMenuItemSprite*)pChild)->getSelectedImage();
- CCRenderTexture *renderer = CCRenderTexture::create(winSize.width,winSize.height);
- renderer->begin();
- bool visible = selectSprite->isVisible();
- if (visible) {
- selectSprite->visit();
- }
- else
- {
- selectSprite->setVisible(true);
- selectSprite->visit();
- selectSprite->setVisible(false);
- }
- GLubyte pixelColors[4];
- #if ( CC_TARGET_PLATFORM != CC_PLATFORM_WIN32)
- glReadPixels(point.x,point.y,1,GL_RGBA,GL_UNSIGNED_BYTE,&pixelColors[0]);
- #else
- glReadPixels(point.x,GL_ALPHA,&pixelColors[0]);
- #endif
- int alpha = pixelColors[0];
- CCLOG("----alpha %d",alpha);
- renderer->end();
- if (alpha <= 30)
- {
- return true;
- }
- else
- {
- return false;
- }
- }
上面代码的确在测试工程上面直接简历个ccsprite 活着 menuitem 是可以执行的。
随着UI工具的进步。我们选择了CocoStudio 的 Widget 。方便了你我啊。
但是可但是,把上面的代码贴过来,试了试真心不能用啊。
有些同志,到此放弃了对知识原理的探究。
程序就是苦啊。遇到这样的问题必须往下研究不是?
经过了多重推敲与图纸推测。
后来发现了出现问题的根本原因:
- CCRenderTexture *renderer 渲染后不能得到位置上面的颜色值 为0 00000为什么为0
- visit()好不好使?各种疑惑
- bool Widget::onTouchBegan(CCTouch *touch,CCEvent *unused_event)
- {
- _touchStartPos = touch->getLocation();
- _hitted = isEnabled()
- & isTouchEnabled()
- & hitTest(_touchStartPos)
- & clippingParentAreaContainPoint(_touchStartPos);
- if (!_hitted)
- {
- return false;
- }
- // add yww alpha check
- if (!AlphaTouchCheck(_touchStartPos))
- {
- return false;
- }
- setFocused(true);
- Widget* widgetParent = getWidgetParent();
- if (widgetParent)
- {
- widgetParent->checkChildInfo(0,this,_touchStartPos);
- }
- pushDownEvent();
- return !_touchPassedEnabled;
- }
上面是按键检测的逻辑。
下面是修改过的代码。原理很简单 在widget 里面ccnode节点 节点位置 相对父节点是0. 所以在visit的时候 位置就从0,0 开始了。
我们矫正下改渲染节点的位置。转成屏幕坐标 然后在根据touch 坐标获取当前点击像素的 透明值。
- // yww get alpha touch event check
- bool Button::AlphaTouchCheck(const CCPoint &point)
- {
- bool isTouchClaimed = false;
- if (getAlphaTouchEnable())
- {
- // check claimed touch arena
- CCSize winSize = CCDirector::sharedDirector()->getWinSize();
- CCSprite* selectSprite = (CCSprite*)getVirtualRenderer();
- CCPoint cutPos = selectSprite->getPosition();
- // CCLOG("getAlphaTouchEnable selectSprite X %f,Y %f",cutPos.x,cutPos.y);
- // get screen point
- CCPoint wordpx = selectSprite->getParent()->convertToWorldSpace(cutPos);
- // CCLOG("getAlphaTouchEnable convertToWorldSpace X %f,wordpx.x,wordpx.y);
- selectSprite->setPosition(wordpx);
- CCRenderTexture *renderer = CCRenderTexture::create(winSize.width,winSize.height);
- //selectSprite->addChild(renderer);
- renderer->begin();
- bool visible = selectSprite->isVisible();
- if (visible)
- {
- selectSprite->visit();
- }
- else
- {
- selectSprite->setVisible(true);
- selectSprite->visit();
- selectSprite->setVisible(false);
- }
- GLubyte pixelColors[4];
- #if ( CC_TARGET_PLATFORM != CC_PLATFORM_WIN32)
- glReadPixels(point.x,&pixelColors[0]);
- #else
- glReadPixels(point.x,&pixelColors[0]);
- #endif
- int alpha = pixelColors[0];
- CCLOG("----alpha %d",alpha);
- renderer->end();
- selectSprite->setPosition(cutPos);
- if (alpha <= 20)
- {
- isTouchClaimed = false;
- }
- else
- {
- isTouchClaimed = true;
- }
- // check claimed touch arena
- }
- else
- {
- isTouchClaimed = true;
- }
- return isTouchClaimed;
- }
上面逻辑是 重写了widget 的自定义函数
AlphaTouchCheck
这个根据自己的需求构建结构了。
在lua里面可以提供检测开关 是否对透明纸进行检测咯。
不多往下说了。浪费网络内存咯。