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会为字符串中有\n的地方换行。所以,我就人为的在其中加入\n。可以写个函数做字符串转换。如果有更好的解决方法欢迎留言告诉我。
    编写一个这样的函数:
  1. std::stringHelloWorld::convertString( std::string str ,int length)
  2. {
  3. unsignedint before =0;
  4. vector<std::string> subStrs;
  5. do
  6. {
  7. subStrs.push_back(str.substr(before,length));
  8. if(before+length >str.size())
  9. {
  10. break;
  11. }
  12. else
  13. {
  14. before = before+length;
  15. }
  16. }while(true);
  17. std::string resultStr;
  18. for(unsignedint i =0;i<subStrs.size();++i)
  19. {
  20. resultStr.append(subStrs[i]).append("\n");
  21. }
  22. resultStr.pop_back();
  23. resultStr.pop_back();
  24. return resultStr;
  25. }

先将字符串按固定长度切成子串,加上\n,并拼起来,最后去掉多余的\n。然后再更改创建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);  

cocos2d-x中CCScale9Sprite的另一种实现的更多相关文章

  1. 如何在cocos2d项目中enable ARC

    如何在cocos2d项目中enable ARC 基本思想就是不支持ARC的代码用和支持ARC的分开,通过xcode中设置编译选项,让支持和不支持ARC的代码共存. cocos2d是ios app开发中 ...

  2. css中的浮动与三种清除浮动的方法

    说到浮动之前,先说一下CSS中margin属性的两种特殊现象 1, 外边距的合并现象: 如果两个div上下排序,给上面一个div设置margin-bottom,给下面一个div设置margin-top ...

  3. C#中实现并发的几种方法的性能测试

    C#中实现并发的几种方法的性能测试 0x00 起因 去年写的一个程序因为需要在局域网发送消息支持一些命令和简单数据的传输,所以写了一个C/S的通信模块.当时的做法很简单,服务端等待链接,有用户接入后开 ...

  4. Hibernate中Java对象的三种状态

                                                                                     Hibernate中Java对象的三种 ...

  5. linux内核分析作业4:使用库函数API和C代码中嵌入汇编代码两种方式使用同一个系统调用

    系统调用:库函数封装了系统调用,通过库函数和系统调用打交道 用户态:低级别执行状态,代码的掌控范围会受到限制. 内核态:高执行级别,代码可移植性特权指令,访问任意物理地址 为什么划分级别:如果全部特权 ...

  6. PHP中获取星期的几种方法

    PHP中获取星期的几种方法   PHP星期几获取代码: 1 date(l); 2 //data就可以获取英文的星期比如Sunday 3 date(w); 4 //这个可以获取数字星期比如123,注意0 ...

  7. CSS中隐藏内容的3种方法及属性值

    CSS中隐藏内容的3种方法及属性值 (2011-02-11 13:33:59)   在制作网页时,隐藏内容也是一种比较常用的手法,它的作用一般有:隐藏文本/图片.隐藏链接.隐藏超出范围的内容.隐藏弹出 ...

  8. JavaScript学习12 JS中定义对象的几种方式

    JavaScript学习12 JS中定义对象的几种方式 JavaScript中没有类的概念,只有对象. 在JavaScript中定义对象可以采用以下几种方式: 1.基于已有对象扩充其属性和方法 2.工 ...

  9. C#中的集合有几种?

    C#中的集合有几种? Array ArrayList List<T> Stack<T> Queue<T> Dictionary<K,V> HashTab ...

随机推荐

  1. 开扒php内核函数,第一篇 bin2hex

    这段时间真的比较有时间,所以自己用c写一下bin2hex啦 写个php的人都知道,这是个比较熟悉的函数吧,没有什么高深,只是把输入的东西以16进制输出吧了 先分析一下,这个函数要怎么写吧,他会有一定的 ...

  2. 高效使用STL

    高效使用STL  参考:http://blog.jobbole.com/99115/ 仅仅是个选择的问题,都是STL,可能写出来的效率相差几倍:熟悉以下条款,高效的使用STL: 当对象很大时,建立指针 ...

  3. TopFreeTheme精选免费模板【20130703】

    今天我们给大家分享13个最新的主题模板,5款WordPress主题,5款Joomla模板,3款OpenCart主题. BowThemes – BT Folio v1.0 Template for Jo ...

  4. geeksforgeeks@ Find sum of different corresponding bits for all pairs (Bit manipulation)

    http://www.practice.geeksforgeeks.org/problem-page.php?pid=387 Find sum of different corresponding b ...

  5. CSRF简单介绍及利用方法-跨站请求伪造

    0x00 简要介绍 CSRF(Cross-site request forgery)跨站请求伪造,由于目标站无token/referer限制,导致攻击者可以用户的身份完成操作达到各种目的.根据HTTP ...

  6. Step By Step(Lua字符串库) (转)

    1. 基础字符串函数:    字符串库中有一些函数非常简单,如:    1). string.len(s) 返回字符串s的长度:    2). string.rep(s,n) 返回字符串s重复n次的结 ...

  7. ACM 中常用的算法有哪些? 2014-08-21 21:15 40人阅读 评论(0) 收藏

    ACM 中常用的算法有哪些?作者: 张俊Michael 网络上流传的答案有很多,估计提问者也曾经去网上搜过.所以根据自己微薄的经验提点看法. 我ACM初期是训练编码能力,以水题为主(就是没有任何算法, ...

  8. Codeforces 161 D. Distance in Tree (树dp)

    题目链接:http://codeforces.com/problemset/problem/161/D 题意: 给你一棵树,问你有多少对点的距离为k. 思路: dp[i][j]表示离i节点距离为j的点 ...

  9. CCF 201312-2 ISBN号码 (水题)

    问题描述 每一本正式出版的图书都有一个ISBN号码与 之对应,ISBN码包括9位数字.1位识别码和3位分隔符,其规定格式如“x-xxx-xxxxx-x”,其中符号“-”是分隔符(键盘上的减号),最后 ...

  10. UI进阶 文件管理器(NSFileManager)文件对接器(NSFileHandle)

    一.文件管理器与文件连接器之间的区别 文件管理器(NSFileManager) 此类主要是对文件进行的操作(创建/删除/改名等)以及文件信息的获取. 文件连接器(NSFileHandle) 此类主要是 ...