2016年12月29日 星期四

1229 cocos2d-x 圖檔 遮罩 使用ClippingRectangleNode

範例
auto clipperNode = ClippingRectangleNode::create();
//設定遮罩位置
auto nodePoint2 = sprHead->convertToNodeSpace(Vec2(LBLobby_LvevlPho.x, G_WinSize.height - LBLobby_LvevlPho.y));
//不用setAnchorPoint 因為node 沒有 AnchorPoint 概念
 clipperNode->setPosition(nodePoint2);  
 sprHead->addChild(clipperNode, 4);  //加入主程式中


    saveNode(LBITEMUP_CLI_LvBlue, clipperNode); //將她額外記錄在Vector 日後直接取出不用TAG
//載入底板
    auto spriteBlue = Sprite::createWithSpriteFrameName(LBLobby_LvevlPho.name);
//依樣設定好位置 這裡不用Vec2::Zero 因為一直會貼錯 所以改為用convertToNodeSpace 計算位置
    nodePoint2 = clipperNode->convertToNodeSpace(Vec2(LBLobby_LvevlPho.x, G_WinSize.height - LBLobby_LvevlPho.y));
    spriteBlue->setAnchorPoint(Vec2::ANCHOR_TOP_LEFT);
    spriteBlue->setPosition(nodePoint2);
    clipperNode->addChild(spriteBlue);

//設定要顯示的部分
    auto NewRect = spriteBlue->getBoundingBox();
    clipperNode->setClippingRegion(Rect(NewRect.origin.x, NewRect.origin.y, NewRect.size.width*0.5, NewRect.size.height));

日後修改方式

//LV BAR 比列0~100%
void PageCommand::ReleaseUI_LvBar(float scale)
{
    auto clipping = dynamic_cast<ClippingRectangleNode*>(getNode(LBITEMUP_CLI_LvBlue));  
    auto sprite = dynamic_cast<Sprite*>(getNode(LBLobby_LvevlPho));
    auto rect = sprite->getBoundingBox().size;
    auto site = clipping->getClippingRegion().origin;
    //float scale = 0.01f*parter;
    clipping->setClippingRegion(Rect(site.x, site.y, rect.width*scale, rect.height));
}

相關參考資料



http://blog.csdn.net/u010010184/article/details/42803971


在Cocos2d-x 的3.3 版本中,添加了一個新類 ClippingRectangleNode,此類與ClippingNode,均有裁剪作用。兩個類做裁剪時有不同的適用背景。區別如下:


  ClippingRectangleNode
  ClippingNode
  裁剪區域
  只能為矩形
  任意圖形
  效率
  高
  低,使用較多時,容易導致低端機掉幀
  適用場景  
  出現數量較多,且對裁剪圖形要求不高時  
  出現數量少,對裁剪區域要求較高時。(例如遊戲新手引導)
  靈活性
  使用簡單,靈活性低
  較為靈活

在使用過程中,發現一個ClippingRectangleNode的bug,該bug導致ClippingRectangleNode或是其上層節點有進行縮放時,會使ClippingRectangleNode的裁剪區域變得異常。
相關代碼如下:
[cpp] view plain copy
  1. void ClippingRectangleNode::onBeforeVisitScissor()  
  2. {  
  3.     if (_clippingEnabled) {  
  4.         glEnable(GL_SCISSOR_TEST);  
  5.           
  6.         float scaleX = _scaleX;  
  7.         float scaleY = _scaleY;  
  8.         Node *parent = this->getParent();  
  9.         while (parent) {  
  10.             scaleX *= parent->getScaleX();  
  11.             scaleY *= parent->getScaleY();  
  12.             parent = parent->getParent();  
  13.         }  
  14.           
  15.         const Point pos = convertToWorldSpace(Point(_clippingRegion.origin.x, _clippingRegion.origin.y));<span style="white-space:pre">   </span>// 將裁剪區域的原點轉為世界坐標系  
  16.         GLView* glView = Director::getInstance()->getOpenGLView();  
  17.         glView->setScissorInPoints(pos.x * scaleX,  
  18.                                    pos.y * scaleY,  
  19.                                    _clippingRegion.size.width * scaleX,  
  20.                                    _clippingRegion.size.height * scaleY);  
  21.   
  22.     }  
  23. }  

開發人員在將裁剪區域的原點正確的轉為世界坐標系之後, 又乘了scaleX 和 scaleY, 這就導致裁剪區域的原點變得不正常了。 (converToWorldSpace在轉換pos時用的變化矩陣已將scale值計算過一次)
修改方法即將
[cpp] view plain copy
  1. glView->setScissorInPoints(pos.x * scaleX,  
  2.                            pos.y * scaleY,  
  3.                            _clippingRegion.size.width * scaleX,  
  4.                            _clippingRegion.size.height * scaleY);  
改為
[cpp] view plain copy
  1. glView->setScissorInPoints(pos.x,  
  2.                            pos.y,  
  3.                            _clippingRegion.size.width * scaleX,  
  4.                            _clippingRegion.size.height * scaleY);  

裁剪區域就正常了。

沒有留言:

張貼留言

cocos2dx-lua 建立滑鼠監聽

重要關鍵字  EVENT_MOUSE_SCROLL addEventListenerWithSceneGraphPriority      if IsPc() then --建立滑鼠監聽         local listener = cc.EventListenerMouse...