• cocos2d-x中CCScale9Sprite的另一种实现


    cocos2d 2.0之后加入了一种九宫格的实现,主要作用是用来拉伸图片,这样的好处在于保留图片四个角不变形的同时,对图片中间部分进行拉伸,来满足一些控件的自适应(PS: 比如包括按钮,对话框,最直观的形象就是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/

    (2)实现

    CCSpriteBatchNode的资源为整个的纹理,9个CCSprite对应于纹理的9个部分(根据纹理不同,9部分所占比例会有所不同),根据想要的尺寸,将9部分拼装在一起!

    (3)优缺点

    优点:思路简单清晰;使用CCSpriteBatchNode,只需要一次绘制,效率较高

    缺点:内存占用大,需要1个CCSpriteBatchNode和9个CCSprite对象;不支持CCSpriteBatchNode(如果控件很多,我们都需要对每个控件单独绘制一次,会影响效率)

      微信的对话框特点在于它有一个可变大小的底图衬托,显得非常舒服,怎么实现的呢?先上图,然后慢慢说:
     
        

    2、什么是九宫格构图?

        有个概念叫九宫格构图,说的就是这种会变化背景的情况。大家都知道图片是不可以随便拉抻的,无论是缩小还是放大,都会使图形虚化,影响显示效果。不能拉抻就进行拼接。这就是这种策略的思路。
        首先它现将一个图分成九份:
          
     
        为了能够看清楚,我进行了缩放。大家也看到了,缩放产生的问题。
        拼接是如何进行的呢?当显示应该超过图片原有大小时,四个边的顶点图像不会改变,四个边的中间部分进行拼接,这样就扩展了图片的大小。中间空出来的部分由中间来进行拼接。因此这张基础图不应该有花纹在上面,不然就会拼乱了。
     

    3、编码九宫格

        原来缩放可以这么简单的实现。而且令人高兴的是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);

      大体说一下。首先创建一个CCLabelTTF。然后取它的大小,作为九宫格的大小。由于不希望文字刚刚好贴在边框显示,我用一个extenSize将九宫格扩大了一圈。最后将Label添加为九宫格的子节点。并为其设定位置。
     
      看起来不错,不过编译运行,出现的界面似乎有些问题:
     
       
     
        是的,没有自动换行。
     

    4、文字换行

        文字换行怎么办?有个好消息是CCLabelTTF会为字符串中有 的地方换行。所以,我就人为的在其中加入 。可以写个函数做字符串转换。如果有更好的解决方法欢迎留言告诉我。
        编写一个这样的函数:
    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(" ");
    22. }
    23. resultStr.pop_back();
    24. resultStr.pop_back();
    25. return resultStr;
    26. }

       先将字符串按固定长度切成子串,加上 ,并拼起来,最后去掉多余的 。然后再更改创建Label那行:

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

        编译运行,就可以了。

    5、总结

        通过使用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);  
  • 相关阅读:
    QT之QRect函数QRect::adjust()函数
    QT 正则表达式(进阶篇)IP,端口号,文件名,非空格字符的匹配,已验证
    QT 正则表达式(基础篇)
    处理不平衡数据的策略
    记录一下ssh,nfs安装步骤
    用户偏好的回归预测推荐
    SVD++分解
    BiasLFM分解
    WALS分解
    ALS分解
  • 原文地址:https://www.cnblogs.com/zhepama/p/3302866.html
Copyright © 2020-2023  润新知