cocos2d-x中CCScale9Sprite的另外一種實現

cocos2d 2.0以後加入了一種九宮格的實現,主要做用是用來拉伸圖片,這樣的好處在於保留圖片四個角不變形的同時,對圖片中間部分進行拉伸,來知足一些控件的自適應(PS: 好比包括按鈕,對話框,最直觀的形象就是ios裏的短信氣泡了),這就要求圖片資源的中間部分是純色或者是簡單的漸變了!ios

 

1.cocos2d中九宮格CCScale9Sprite的實現

(1)原理

cocos2d的實現很是巧妙,是經過1個CCSpriteBatchNode和9個CCSprite來實現的,原理很簡單,經過將原紋理資源切割成9部分(PS: 這也是叫九宮格的緣由),根據想要的尺寸,完成如下的三個步驟:微信

a. 保持4個角部分不變形

b. 單向拉伸4條邊(即在4個角兩兩之間的邊,好比上邊,只作橫向拉伸)

c. 雙向拉伸中間部分(即九宮格的中間部分,橫向,縱向同時拉伸,PS:拉伸比例不必定相同)

(PS: 更多原理可參考 http://yannickloriot.com/2011/12/create-buttons-in-cocos2d-by-using-cccontrolbutton/app

(2)實現

CCSpriteBatchNode的資源爲整個的紋理,9個CCSprite對應於紋理的9個部分(根據紋理不一樣,9部分所佔比例會有所不一樣),根據想要的尺寸,將9部分拼裝在一塊兒!函數

(3)優缺點

優勢:思路簡單清晰;使用CCSpriteBatchNode,只須要一次繪製,效率較高this

缺點:內存佔用大,須要1個CCSpriteBatchNode和9個CCSprite對象;不支持CCSpriteBatchNode(若是控件不少,咱們都須要對每一個控件單獨繪製一次,會影響效率)編碼

 

   微信的對話框特色在於它有一個可變大小的底圖陪襯,顯得很是舒服,怎麼實現的呢?先上圖,而後慢慢說:
 
    

二、什麼是九宮格構圖?

    有個概念叫九宮格構圖,說的就是這種會變化背景的狀況。你們都知道圖片是不能夠隨便拉抻的,不管是縮小仍是放大,都會使圖形虛化,影響顯示效果。不能拉抻就進行拼接。這就是這種策略的思路。
    首先它現將一個圖分紅九份:
      
 
    爲了可以看清楚,我進行了縮放。你們也看到了,縮放產生的問題。
    拼接是如何進行的呢?當顯示應該超過圖片原有大小時,四個邊的頂點圖像不會改變,四個邊的中間部分進行拼接,這樣就擴展了圖片的大小。中間空出來的部分由中間來進行拼接。所以這張基礎圖不該該有花紋在上面,否則就會拼亂了。
 

三、編碼九宮格

     原來縮放能夠這麼簡單的實現。並且使人高興的是cocos2d-x已經對這種模型進行封裝,不須要你們本身來寫。下面就動手編碼。
 
更改helloWorld中的init。相信你們都知道是哪裏:
  1. std::string str ="You are lucky as you can choose to love me or not.But for me,I can only choose to love you or more. ";
  2. // Create a label and initialize with string "Hello World".
  3. CCLabelTTF* pLabel =CCLabelTTF::create(str.c_str(),"Arial",24);
  4. CC_BREAK_IF(! pLabel);
  1. pLabel->setColor(ccc3(0,0,0));

pLabel->setAnchorPoint(CCPointZero);CCScale9Sprite* sp = CCScale9Sprite::create("green_edit.png");CCSize extenSize = CCSizeMake(pLabel->getContentSize().width+10,pLabel->getContentSize().height+10);sp->setContentSize(extenSize);sp->addChild(pLabel);pLabel->setPosition( ccpAdd(sp->getPosition(),ccp(4,1)));sp->setPosition(ccp(250,100)); // Add the label to HelloWorld layer as a child layer. this->addChild(sp, 1);spa

  大致說一下。首先建立一個CCLabelTTF。而後取它的大小,做爲九宮格的大小。因爲不但願文字剛恰好貼在邊框顯示,我用一個extenSize將九宮格擴大了一圈。最後將Label添加爲九宮格的子節點。併爲其設定位置。
 
  看起來不錯,不過編譯運行,出現的界面彷佛有些問題:
 
   
 
    是的,沒有自動換行。
 

四、文字換行

    文字換行怎麼辦?有個好消息是CCLabelTTF會爲字符串中有\n的地方換行。因此,我就人爲的在其中加入\n。能夠寫個函數作字符串轉換。若是有更好的解決方法歡迎留言告訴我。
    編寫一個這樣的函數:
  1. std::stringHelloWorld::convertString( std::string str ,int length)
  2. {
  3.  
  4. unsignedint before =0;
  5. vector<std::string> subStrs;
  6. do
  7. {
  8. subStrs.push_back(str.substr(before,length));
  9. if(before+length >str.size())
  10. {
  11. break;
  12. }
  13. else
  14. {
  15. before = before+length;
  16. }
  17. }while(true);
  18. std::string resultStr;
  19. for(unsignedint i =0;i<subStrs.size();++i)
  20. {
  21. resultStr.append(subStrs[i]).append("\n");
  22. }
  23. resultStr.pop_back();
  24. resultStr.pop_back();
  25. return resultStr;
  26. }

   先將字符串按固定長度切成子串,加上\n,並拼起來,最後去掉多餘的\n。而後再更改建立Label那行:orm

  1. CCLabelTTF* pLabel =CCLabelTTF::create(convertString(str,32).c_str(),"Arial",24);

    編譯運行,就能夠了。對象

五、總結

    經過使用CCScale9Sprite這個類,建立一個可變大小的背景,而後建立固定寬度的Label,並將二者關聯。若是想進一步封裝的話,能夠建立一個類將二者做爲一個複合對象,具體可參照以前的文章:    。

 

 

 

CCScale9Sprite* nineGirl = CCScale9Sprite::create("button.png"); 
nineGirl->setContentSize(CCSize(200, 100));  //設置大小
nineGirl->setPosition(ccp(300, 200)); 
 this->addChild(nineGirl);  
 
/* 正常狀態下的按鈕圖片 */ 
 CCScale9Sprite* btnNormal = CCScale9Sprite::create("button.png"); 
 
 /* 點擊狀態下的按鈕圖片 */ 
 CCScale9Sprite* btnDown = CCScale9Sprite::create("buttonHighlighted.png"); 
 
 /* 按鈕標題 */ 
 CCLabelTTF *title = CCLabelTTF::create("Touch Me!3324234", "Marker Felt", 30); 
 
 /* 按鈕的大小會根據標題自動調整 */ 
 CCControlButton* controlBtn = CCControlButton::create(title, btnNormal); 
 
 /* 設置按鈕按下時的圖片 */ 
controlBtn->setBackgroundSpriteForState(btnDown, CCControlStateSelected); 
controlBtn->setPosition(ccp(200, 200)); 
 this->addChild(controlBtn);
相關文章
相關標籤/搜索