cocos2d-x 文本框
转载:http://blog.csdn.net/zhanglongit/article/details/8451641
相关几个重要的类的继承关系如下
1.所有文本框必须实现CCLabelProtocol接口
2.CCLableTTF比另外两个文本框渲染慢
TTF(TrueTypeFont)是一种字库名称,是Apple公司和Microsoft公司共同推出的字体文件格式,随着windows的流行,已经变成最常用的一种字体文件表示方式。
CCLabelTTF 每次调用 setString (即改变文字)的时候,一个新的OpenGL纹理将会被创建.。这意味着setString 和创建一个新的标签一样慢。
所以,当你需要频繁的更新它们的时候,尽可能的不用去使用标签对象。 而应该使用CCLabelAtlas或者是CCLabelBMFont
OK, 看下它的使用方法
CCLabelTTF *label = CCLabelTTF::labelWithString("the string", "Marker Felt", 21);
this->addChild(label);
label->setPosition(ccp(100, 100));
label->setString("change string");//修改文字的方法
这个类使用的是系统中的字体,不需要额外往项目文件中添加字体文件。但如果你有自定义的字体也可以加到项目中,如果无法使用,可以查看一下ccConfig.h中的CC_FONT_LABEL_SUPPORT是否enable了。
3.CCLabelBMFont中每个文字相当于一个CCSprite,可以旋转,移动,改变尺寸等
CCLabelBMFont 相当于每次改变只改变了图片坐标,而CCLabelTTF要重新渲染.这个类使用之前,需要添加好字体文件,包括一个图片文件 (**.png) 和一个 字体坐标文件 (**.fnt)。
在 cocos2d-x的示例项目中有现成的,可以先拿过来练习一下,找的时候注意两个文件的名称是相同的,只是扩展名不同。
CCLabelIBMFont *label = CCLabelIBMFont::labelWithString("the string", "font-hd.png");
this->addChild(label);
label->setPosition(ccp(100, 100));
label->setString("change string");
下面是 font-hd.png文件的截图
font-hd.fnt文件定义了 图像文件的名称,以及每个字符对应的位置信息。
这个没办法指定字体的字号,但可以用scale属性进行缩放来调整大小。就当它是sprite,可以简单的实现很炫的文字的动画效果。
4.CCLabelAtlas
如果你用cocos2d-x项目模板创建过项目,那么你已经看过它的效果了,就是左下角显示帧率的数字。
因为帧率一直在变,使用CCLabelTTF的话效率太低,因为只是数字所以也犯不上使用 CCLabelBMFont 加载那么大的文字图像,所以使用这个比较合适。
CCLabelAtlas *label = CCLabelAtlas::labelWithString("12", "fps_images.png", 12, 18, ".");
this->addChild(label);
label->setPosition(ccp(100, 100));
label->setString("34");
在项目文件中,在resourse group里你可以找一下一个叫 fps_images.png的这个图像文件,文件如下:
所以,这个只能显示上面这个12个字符,abcd什么的就不行了。
解释一下参数,
12 就是字符,
fps_images.png就是字符的图像文件(这个只要图像文件就可以了),
12 是每个字符的宽度,
18 是每个字符的高度,这个不能设错,否则显示的时候可能就不对了。
最后一个是起始字符,它是使用这个其实字符来对应字符和图像关系的
5.下面具体分析一下画字的原理(参考一篇博客)
图字,顾名思义,利用图片做为纹理来显示的文字。当下流行的跨平台2D引擎Cocos2d-x和LibGdx也都有对于图字的应用支持,今天我就来为大家讲一讲图字。
首先要介绍一下,图字是怎么来的?其实这个很早很早了,记得80后在95年开始玩DOS下的仙剑奇侠传的时候,那些令人难忘的中文对话吧!DOS下做游戏,使用的是C语言,不要说写字了,很多复杂的操作甚至涉及驱动。那时候绘图就是利用将图片中的像素取出来后绘制在屏幕上,所以处理游戏中的中文,就只有把这些文字的像素预先写到BMP或二进制文件中,然后读取出来再设置屏幕像素以实现。后来进入DDRAW的时代,可以使用WINDOWS系统中的字库来写字了。把DDRAW的后台表面进行LOCK,取出其DC,然后用GDI将文字写到其DC上,这种做法后面也延续了很久,但GDI进行TextOut的效率非常慢,你要是想像梦幻西游一样满屏写了,那得卡死,解决方案是什么?还是图字。专业的游戏开发者会将所用到的字都预处理生成到一张图片中,通过一个编码与纹理UV对应文件来进行纹理UV的获取后做为顶点的UV值然后进行绘制,有也的在每一帧中实时的将需要的字使用DDRAW写字的方法绘制到相应的纹理上然后使用文字编码与纹理UV对应信息来进行绘制,这样效率就提高很多了。目前比较流行的做法是使用一张png图片来存储用到的文字。一个.fnt文件来存储文字图片说明信息。Cocos2d-x和LibGdx中都集成了相关的图字处理类。在世界范围内,也有很多游戏使用了这个方案。在游戏汉化界,了解和掌握图字的原理和修改方法也是很重要的一项工作
我们以Cocos2d-x的tests工程中的LabelTest中的最后一个Label显示“中国”为例来分析一下。
打开Cocos2d-x所在目录下的tests\Resources\fonts目录,找到bitmapFontChinese.png(文字贴图文件)和bitmapFontChinese.fnt(文字图片说明信息文件)
先打开png,我们可以看到它是512×512大小,上面由12行,14列个文字组成。包括有一些汉字,常用字符,数字和字母。它的每个字都是由青色到蓝色的向下渐变。
再用UEdit或记事本打开bitmapFontChinese.fnt,可以看到它的构成,我在这里讲一下。
第一行是对字体的介绍。
1 |
info face="华康海报体W12(P)" size=32 bold=0italic=0 charset="" unicode=0stretchH=100smooth=1 aa=1 padding=0,0,0,0 spacing=1,1
|
解释:
face=”华康海报体W12(P)”:字体为”华康海报体W12(P)”,
size=32:大小为32像素
bold=0 :不加粗
italic=0:不使用斜体
charset=”": charset是编码字符集,这里没有填写值即使用默认,
unicode=0:不使用Unicode
stretchH=100:纵向缩放百分比
smooth=1 :开启平滑
aa=1:开启抗锯齿
padding=0,0,0,0:内边距,文字与边框的空隙。
spacing=1,1 :外边距,就是相临边缘的距离。
第二行是对应所有字贴图的公共信息
1 |
common lineHeight=37 base=28 scaleW=512 scaleH=512pages=1 packed=0
|
解释:
lineHeight=37:行高,如果遇到换行符时,绘制字的位置坐标的Y值在换行后增加的像素值。
base=28 :字的基本大小
scaleW=512 :图片大小
scaleH=512:图片大小
pages=1 :此种字体共用到几张图。
packed=0:图片不压缩
第三行是对应当前字贴图的信息
//第一页,文件名称是”bitmapFontChinese.png”
page id=0 file=”bitmapFontChinese.png”
第四行是当前贴图中所容纳的文字数量
chars count=204
第五行起把当前贴图中所用到的所有文字的编码以及对应在图片上的矩形位置,偏移等列出来
第一个字符编码为32,也就是空格,位置为0,0,宽高为0,0, 绘制到屏幕的相应位置时,像素偏移(0,28),绘制完后相应位置的x往后移15像素再画下一个字符,字的图块在第1页上
char id=32 x=0 y=0 width=0 height=0 xoffset=0 yoffset=28 xadvance=15 page=0 chnl=0
第一个字符编码为汉字”象”,也就是空格,位置为0,0,宽为33,高为36, 绘制到屏幕的相应位置时,像素偏移(0,-1),绘制完后相应位置的x往后移36像素再画下一个字,字的图块在第1页上
char id=35937 x=0 y=0 width=33 height=36 xoffset=0 yoffset=-1 xadvance=36 page=0 chnl=0
char id=26696 x=33 y=0 width=35 height=36 xoffset=-1 yoffset=-1 xadvance=36 page=0 chnl=0
char id=26071 x=68 y=0 width=35 height=36 xoffset=-1 yoffset=-1 xadvance=36 page=0 chnl=0
…
再后面是描述两个字在进行组合绘制时字距调整的相关信息,这里没有要进行间距调整的字组合所以为设-1。对于字组合间距调整可以看此示例图:
kernings count=-1
这个数字代表参与字组合间距调整的字的数量。
如果kernings count大于零,后面会有类似这样的描述:
kerning first=102 second=41 amount=2
也就是’f’与’)’进行组合显示’f)’时,’)’向右移2像素防止粘在一起。
通过上面这些信息,引擎可以通过编码找到相应的文字并取出对应的纹理块。
//Cocos2d-x中LabelBMFontChinese
下面我们来分析一下Cocos2d-x的tests工程中的LabelTest中的最后一个Label,它的类名为CCLabelBMFont.转到其类定义文件CCLabelBMFont.h
1 |
class CC_DLL CCLabelBMFont : public CCSpriteBatchNode, public CCLabelProtocol, public CCRGBAProtocol
|
可以看到其直接派生于三个类,分别是
CCSpriteBatchNode :精灵批次管理类,用于将使用一张图的多个精灵在设置一次纹理的批次里进行绘制,提高渲染的效率。
CCLabelProtocol :文字字串类
CCRGBAProtocol:颜色调节接口类
由简入深,我们先来看一下CCRGBAProtocol,打开CCProtocols.h
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
class CC_DLL CCRGBAProtocol
{ public : //设置颜色 virtual void setColor ( const ccColor3B & color ) = 0 ; //取得颜色 //返回透明度 //设置透明度 //设置是否使用Alpha值设置RGB,如果 //取得是否使用Alpha值设置RGB |
可以看到CCRGBAProtocol类是个纯虚类,只是定义了一些设置获取颜色信息的接口函数。
继续看CCLabelProtocal,明显的,它也是纯虚类,做为存储字符串的接口使用:
1 2 3 4 5 6 7 8 9 |
class CC_DLL CCLabelProtocol
{ public : // 设置文字标签显示的字符串 virtual void setString ( const char *label ) = 0 ; // 返回文字标签显示的字符串 |
最后来分析CCSpriteBatchNode类。它由CCNodet 和 CCTextureProtocal两个类派生而来,CCNode是基础结点类,用于将引擎中所有具有逻辑顺序和父子关系的类组织起来,基于CCNode派生的类均可以互相挂接。CCNode不是本章要详细介绍的内容,就不再详细分析了,看一下CCTextureProtocol,这是一个纹理使用接口类:
1 2 3 4 5 6 7 8 9 |
class CC_DLL CCTextureProtocol : public CCBlendProtocol
{ public : // 返回所使用的2D纹理 virtual CCTexture2D * getTexture ( void ) = 0 ; // 设置使用的2D纹理,并为纹理的使用计数器加1操作 |
很简单,只有两个函数对纹理进行设置和获取,它派生于CCBlendProtocal,这是一个Alpha混合系数设置接口类,用于在开启Alpha混合状态后对Alpha混合的系数进行设置。再来看一下CCBlendProtocal,这是一个混合状态设置接口类:
1 2 3 4 5 6 7 8 9 |
class CC_DLL CCBlendProtocol
{ public : // 为纹理设置使用的混合状态 virtual void setBlendFunc (ccBlendFunc blendFunc ) = 0 ; // 返回为纹理设置的混合状态 |
返回到类CCSpriteBatchNode的定义。我们再来分析CCSpriteBatchNode。之前说了CCSpriteBatchNode是精灵批次管理类,用于将使用一张图的多个精灵在设置一次纹理的批次里进行绘制,提高渲染的效率。既然多个精灵使用一张图,则需要将多个小图块合并在一张图上,这样只要设置使用大图做为纹理,将使用各小图块做为纹理贴图的精灵设置好顶点与UV等数据,就可以绘制出这些精灵了。Cocos2d-x提供了一个类CCTextureAtlas对使用图块的这些精灵所使用的顶点缓冲区进行管理。为了更好的理解CCSpriteBatchNode,我们看一下它的定义和实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 |
#ifndef __CCTEXTURE_ATLAS_H__
#define __CCTEXTURE_ATLAS_H__ //用到的头文件 #include <string> #include "ccTypes.h" #include "CCObject.h" #include "ccConfig.h" //使用Cocos2d命名空间 namespace cocos2d { class CCTexture2D ; //CCTextureAtlas由CCObject派生而来 class CC_DLL CCTextureAtlas : public CCObject { protected : //使用此大图中的图块的精灵对应的三角形索引数组的指针 GLushort *m_pIndices ; #if CC_USES_VBO //如果使用Vertex Buffer Object(VBO:使用显存而非内存存储顶点缓冲数据,大大提高效率),建立VBO句柄数组,第一个元素存顶点数组的句柄,第二个元素存索引数组句柄 GLuint m_pBuffersVBO [ 2 ] ; //标记是否更新需要更新的图块信息。当你新加入了图块或者修改了图块,需要设置为true。 bool m_bDirty ; #endif // CC_USES_VBO // CC_PROPERTY_READONLY宏为类定义变量及增加相应的get函数。 public : //静态函数:从文件中创建纹理,并初始化图块容量 //同上,只是非静态函数。作者提示不能重复调用,否则会造成内存泄漏。 //静态函数:从贴图中创建纹理,并初始化图块容量 //同上,只是非静态函数。作者提示不能重复调用,否则会造成内存泄漏。 //通过索引值找到对应的图块顶点缓冲数据并用新数据修改它,由CCSprite实例对象在变换顶点信息时调用。 //通过索引值找到对应的图块顶点缓冲数据,并在其之前插入一个新的图块。 //通过索引值找到对应的图块顶点缓冲数据,并把它插入另一个图块之前。 //移除指定位置的图块顶点缓冲数据. //清空所有的图块顶点缓冲数据。 //重新设置图块顶点缓冲数组的容量 //绘制指定的图块顶点缓冲 //绘制从指定的图块起后面的N个图块 //绘制所有的图块顶点缓冲 #endif //__CCTEXTURE_ATLAS_H__ |
再看CPP:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 |
#include "CCTextureAtlas.h"
#include "CCTextureCache.h" #include "ccMacros.h" // 纹理头文件 #include <stdlib.h> //使用Cocos2d命名空间 CC_SAFE_FREE (m_pQuads ) #if CC_USES_VBO CC_SAFE_RELEASE (m_pTexture ) ; //静态函数:从文件中创建纹理,并初始化图块容量 return NULL ; // 设置纹理 // 判断是否重复调用 //如果失败,做相应处理 //初始化缓冲区对象 return true ; //初始化索引缓冲 // inverted index. issue #179 //通过索引值找到对应图块的顶点缓冲并用新数据修改它 //先将索引位置之后的数据整体后移一个位置,再用新数据填充索引位置的数据。实现插入操作。 m_pQuads [index ] = *quad ; //设置需要更新m_pBuffersVBO中的VBO数组数据。 //计算要移动的图块数量 // 开始进行移动 unsigned int remaining = (m_uTotalQuads - 1 ) - index ; //将索引图块后的所有图块向前移1个位置即可 //移除所有的顶点缓冲数据 // 重新设置图块顶点缓冲数组的容量 //确保当前绘制的精灵数量最大不能超过容量 if ( tmpIndices ) m_pQuads = NULL ; return true ; //绘制所有的图块顶点缓冲数据 //绘制指定的图块顶点缓冲数据 #define kQuadSize sizeof(m_pQuads[0].bl) //如果使用VBO所进行的渲染设置 //在绘制时如果遇到需要更新标记,则重新将顶点缓冲数据更新到绑定的对象上。 // 对顶点缓冲中的顶点格式进行解释,让显卡知道顶点格式的构成。 //顶点缓冲中哪个是颜色数据 //顶点缓冲中哪个是纹理坐标数据 //按照相应的三角形排列进行渲染 //从显存上卸载绑定的数据 #else // ! CC_USES_VBO //设置OpenGL渲染使用的顶点数据 //设置OpenGL渲染使用的颜色数据 //设置OpenGL渲染使用的纹理坐标数据 //按照相应的三角形排列进行渲染 #endif // CC_USES_VBO } //namespace cocos2d |
清楚了CCTextureAtlas,现在回过头再来看CCSpriteBatchNode。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 |
class CC_DLL CCSpriteBatchNode : public CCNode, public CCTextureProtocol
{ public : //析构 ~CCSpriteBatchNode ( ) ; // 取得纹理图块顶点缓冲管理器。 inline CCTextureAtlas * getTextureAtlas ( void ) { return m_pobTextureAtlas ; } //设置纹理图块顶点缓冲管理器 inline void setTextureAtlas (CCTextureAtlas * textureAtlas ) { //如果当前使用的纹理图块顶点缓冲管理器与要设置的纹理图块顶点缓冲管理器不同,先释放原顶点缓冲管理器,再将当前使用的顶点缓冲管理器指针指向要设置顶点缓冲管理器。 if (textureAtlas ! = m_pobTextureAtlas ) { CC_SAFE_RETAIN (textureAtlas ) ; CC_SAFE_RELEASE (m_pobTextureAtlas ) ; m_pobTextureAtlas = textureAtlas ; } } //取得存放所有使用此图块集的CCSprite指针数组 inline CCArray * getDescendants ( void ) { return m_pobDescendants ; } //静态函数:通过纹理指针按照默认的图块数量29创建一个CCSpriteBatch实例对象。注意:如果游戏运行中图块数量超过这个数值,则数量递增33%以满足需要 static CCSpriteBatchNode * batchNodeWithTexture (CCTexture2D *tex ) ; //静态函数:通过纹理指针按照设定的图块数量创建一个CCSpriteBatch实例对象。 //静态函数:通过图片名称按照默认的图块数量29创建一个CCSpriteBatch实例对象。 //静态函数:通过图片名称按照设定的图块数量创建一个CCSpriteBatch实例对象。 //通过纹理指针和图块数量进行初始化。 //通过索引移除一个子结点,参数doCleanUp决定移除的同时是否对其进行释放。 //重载CCNode的相关函数 protected : private : protected : |
再看CPP:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 |
//加入用到的头文件
#include "CCSpriteBatchNode.h" #include "ccConfig.h" #include "CCSprite.h" #include "effects/CCGrid.h" #include "CCDrawingPrimitives.h" #include "CCTextureCache.h" #include "CCPointExtension.h" //使用cocos2d命名空间 namespace cocos2d { //定义整型常量defaultCapacity做为默认创建的图块数量 const int defaultCapacity = 29 ; //静态函数:通过纹理指针按照默认的图块数量29创建一个CCSpriteBatch实例对象。 return batchNode ; //静态函数:通过图片名称按照设定的图块数量创建一个CCSpriteBatch实例对象。 return batchNode ; //静态函数:通过图片名称按照默认的图块数量29创建一个CCSpriteBatch实例对象 return batchNode ; //通过纹理指针和图块数量进行初始化。注意:这个函数才是真正进行初始化的实现过程。 // 新建一个CCArray实例,将m_pChildren指向它 return true ; //通过纹理文件名和图块数量进行初始化。 // 是基类CCNode虚函数,是每帧会被调用到的函数。 //将子结点重新设置Z顺序。 //将一个CCNode指针从子结点数组中删除,并根所参数决定是否释放元素 // explicit null handling //移除一个指定的CCSprite指针 //绘制当前CCNode // 如果图块集为空直接返回 // 设置ALPHA混合状态 //如果子结点数组不为空 // 如果pobParent return uIndex ; // 判断当前节点是否是pobSprite的父结点,将结果存入bIgnoreParent。 // 如果进行到这一步,已经出错了。打印出错信息。 //将一个CCSprite插入到子节点指针数组的指定位置 //在图块集管理器中新增加一个图块,并指定其索引 // 更新索引 ++i ; // 取得pobSprite的子结点数组 // 取得子结点的数组元素数量,遍历大于当前索引的子结点,向前移一个位置。注意:这个for循环从uIndex开始计数。 // 取得目标精灵的子结点数组,遍历并从当前CCSpriteBatchNode的子结点数组中移除。 //从精灵数据中在图块管理器中插入一个新的图块,注意:并不将精灵放入子结点。 //设置在缓制sprite时更新一下图块信息 //在子结点数组指定位置插入一个新的精灵。注意:并不新建图块。 //遍历子结点数组查看当前Z值应该排在哪个位置。 //基类同名函数 } |
分析这个类的确是费功夫啊,呵呵。继续之前。喝口水先。话说今天听新闻,北京PM2.5浓度又升高了,我可怜的嗓子,担忧中…
走到这里,我们已经了解了CCSpriteBatchNode的作用。其实红孩儿在开发引擎的经历中也有过类似的设计,为了渲染大量相同类型的模型,按照纹理将子模型归类,并将这些纹理进行合并生成大纹理,渲染时设置大纹理就可以渲染出多个不同类型的子模型,如果开启克隆实例,则可以在一个批次内渲出上百个模型。原理相通,目的只有一个,提高渲染效率。
CCLabelBMFont类中关于图字纹理和图块的相关知识我们了解完了,但是我们仍然没有发现Fnt用在哪里,所以我们只理解了一半,现在我们来理解另一半。CCLabelBMFont中使用到一个类CCBMFontConfiguration,它就是用来读取Fnt文件中的文字图片说明信息的。在CCLabelBMFont.h中我们找到它
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
class CC_DLL CCBMFontConfiguration : public CCObject
{ public : //通过map容器对字的编码值和对应的信息做映射 std :: map < unsigned int, ccBMFontDef > * m_pBitmapFontArray ; //FNT文件中的字图块公共项:Height |
太棒了,它对Fnt文件做了全面的解析。马上看CPP他是怎么现实的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 |
初始化全局容器指针为空
CCMutableDictionary <std :: string, CCBMFontConfiguration * > *configurations = NULL ; //全局函数:从Fnt文件中取得一个CCBMFontConfiguration实例对象 CCBMFontConfiguration * FNTConfigLoadFile ( const char *fntFile ) { //创建CCBMFontConfiguration指针变量pRet并置空 CCBMFontConfiguration *pRet = NULL ; //如果容器为空则新建容器 if ( configurations == NULL ) { configurations = new CCMutableDictionary <std :: string, CCBMFontConfiguration * > ( ) ; } //在容器中取得该文件对应的CCBMFontConfiguration std :: string key (fntFile ) ; pRet = configurations - >objectForKey (key ) ; if ( pRet == NULL ) { //如果为空则调用CCBMFontConfiguration静态函数新建一个CCBMFontConfiguration读取文件返回信息结构给pRet pRet = CCBMFontConfiguration :: configurationWithFNTFile (fntFile ) ; //并将其加入容器中 configurations - >setObject (pRet, key ) ; } return pRet ; if ( !pBuffer ) std :: string line ; 通过信息索引存入哈希字典 //先取得id // 取得文件名称 //解析字体介绍信息 // 内边距padding // 在图块中的像素横向位置 // first解析第一个字 // second:解析第二个字 // amount:解析要调整的像素个数,负值向左,正值向右 |
CCBMFontConfiguration类分析完了,CCLabelBMFont就很容易理解了。快马加鞭向前冲哟~
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
class CC_DLL CCLabelBMFont : public CCSpriteBatchNode, public CCLabelProtocol, public CCRGBAProtocol
{ //容量 CC_PROPERTY (GLubyte, m_cOpacity, Opacity ) //颜色 CC_PROPERTY_PASS_BY_REF (ccColor3B, m_tColor, Color ) //是否使用透明度来设置RGB值 CC_PROPERTY ( bool, m_bIsOpacityModifyRGB, IsOpacityModifyRGB ) protected : // 要渲染的字符串 std :: string m_sString ; //使用的设置 CCBMFontConfiguration *m_pConfiguration ; public : //构造函数。 CCLabelBMFont ( ) : m_cOpacity ( 0 ) , m_bIsOpacityModifyRGB ( false ) , m_sString ( "" ) , m_pConfiguration ( NULL ) { } //析构 virtual ~CCLabelBMFont ( ) ; //释放占用的内存 static void purgeCachedData ( ) ; //由一个字符串和字体fnt文件创建图字 bool initWithString ( const char *str, const char *fntFile ) ; //重点函数:根据字符串和字体信息进行纹理图对应 void createFontChars ( ) ; //设置要渲染的字符串 virtual void setString ( const char *label ) ; //取得要渲染的字符串 virtual const char * getString ( void ) ; //设置要渲染的字符串,setString的别名函数 virtual void setCString ( const char *label ) ; //设置锚点 virtual void setAnchorPoint ( const CCPoint & var ) ; //绘制函数 #if CC_LABELBMFONT_DEBUG_DRAW virtual void draw ( ) ; #endif // CC_LABELBMFONT_DEBUG_DRAW private : char * atlasNameFromFntFile ( const char *fntFile ) ; int kerningAmountForFirst ( unsigned short first, unsigned short second ) ; } ; |
CPP文件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 |
//释放占用的内存
void CCLabelBMFont :: purgeCachedData ( ) { //释放文字FNT信息指针 FNTConfigRemoveCache ( ) ; } //静态函数:由一个字符串和字体fnt文件创建图字 // 由参1和参2组成key从哈希表中找到元素的数量。 //计算Char对应的UTF8码的长度 //取得Char对应的UTF8码 //用于获取UTF8下个字符的编码偏移。 static const char * const g_utf8_skip = utf8_skip_data ; //返回取得字符串转换为UTF8后的字符长度 if ( ! (p ! = NULL || max == 0 ) ) if (max < 0 ) p = cc_utf8_next_char (p ) ; while (p - start < max && *p ) /* only do the last len increment if we got a complete return len ; //将Unicode编码字符串p转换为UTF8编码 UTF8_COMPUTE (c, mask, len ) ; return result ; //重点函数:由字符串和字编码纹理块对应信息设置到 CCSize tmpSize = CCSizeZero ; // int longestLine = 0 ; // 最长的一行的宽度 unsigned int quantityOfLines = 1 ; const char * p = m_sString. c_str ( ) ; for ( int i = 0 ; i < utf8len ; ++i ) unsigned int stringLen = cc_wcslen (pUniStr ) ; //遍历所有的字 if (c == '\n' ) //查找是当前字的纹理映射信息结点 //根据上一个字与当前字进行间距调整信息哈希表的查找,返回调整的像素偏移量。 //设置其显示,完全不透明。 // NSLog(@"position.y: %f", fontChar.position.y); // 更新绘制下一个字的横向位置 // 设置是否用透明度设置色彩 fontChar->setIsOpacityModifyRGB(m_bIsOpacityModifyRGB); //如果透明度小于255,设置透明度 //设置当前字符串在屏幕上占用的矩形位置 //LabelBMFont重载基类 CCLabelProtocol的接口函数 //LabelBMFont 重载基类 CCRGBAProtocol 的接口函数 if (m_pChildren && m_pChildren - >count ( ) ! = 0 ) // 设置锚点 //绘制图字标签,Debug模式下手动调用绘制 } |
照例做个总结:
1. 图字的原理:将所要绘制的字绘制到图片上,通过编码取得对应的矩形块UV进行顶点缓冲的设置之后进行绘制。Cocos2d-x提供的两个类非常重要:(1) CCTextureAtlas(2) CCSpriteBatchNode。
2. 图字的组成:一张纹理,一个纹理描述信息文件。缺一不可。要做好图字,必须深入理解图字纹理描述信息文件的格式,可能看Cocos2d-x提供的类: CCBMFontConfiguration,并掌握图字工具的使用。
呃,网上提供了一些图字工具,比较常用的有
Hiero:
cocos2d-x 文本框相关推荐
- 文本框可编辑查看页面
<!DOCTYPE html> <html><head><meta charset="utf-8" /><title>文 ...
- 【kindeditor】KindEditor获取多个textarea文本框的值并判断非空
kindeditor官网:http://kindeditor.net/demo.php 如何获取多个KindEditor中textarea文本框的值,方式很多种(带有HTML标签). var intr ...
- java 限制文本框长度_java中限制文本框输入长度的显示(转载)
我最近在网上看到一篇文章很不错,对于限制文本框输入长度的显示很方便 JAVA不像C#能够有maxLength这个属性对文本框的输入长度进行控制,但也是有办法实现相应的功能的. 写一个MyDocumen ...
- Python Qt GUI设计:QLineEdit和QTextEdit文本框类(基础篇—13)
目录 1.QLineEdit文本框类 2.QTextEdit文本框类 QLineEdit和QTextEdit都是文本框类,QLineEdit类是单行文本框控件,可以输入单行字符串.QTextEdit类 ...
- 解决Vue用v-html、v-text渲染后台富文本框文本内容样式修改问题,用自定义css样式无法渲染出对应效果的问题
举例: 如果您要加载富文本框内容的DOM id是detail 那么就这么写scss样式 #detail {font-size: 14px;text-align: center;&>> ...
- c文本框只能输入数字_VBA代码限制文本框的输入
题记:非常期间,希望大家静下心,多学习有用的知识,多提高自己的水平和能力,这才是正道.适当节制自我的各种欲望,谁都逃不过时间的历练,谁都是命运的行者,谁都是在人生的道路上一步一趋,把生活与工作打理好, ...
- 文本框自动提示_Excel办公小技巧,使用艺术字与文本框,就是那么的简单
Excel中的艺术字同时拥有文字和图形两种对象的属性,不仅可以修改其中的内容,还可以调整形状的大小.设置边框以及内部填充等效果,常在编辑表格标题或者输入一些比较有提示性的文本时使用,在突出关键内容的同 ...
- 简单的文本框输入实时计数
2019独角兽企业重金招聘Python工程师标准>>> 简单的文本框输入实时计数 $(function(){suminput('idea','60');})//记录输入字符方法fun ...
- ppt文本框显示缺字,信息显示不全
1.在文字后面加个空格. 2.重新调整文本框大小 3.不需要打开ppt,而是在图标上右键属性-摘要,把标题.主题.作者等描述全部清空或改成与本机用户一至即可.因为文本框少子是信息不匹配,就像歌曲在mp ...
最新文章
- 微擎 jssdk php文件,微擎register_jssdk分享到朋友功能无法使用的问题及解决办法
- 将信息系学生的计算机文化学,计算机学生论文,关于基于职业岗位的计算机文化基础课教学相关参考文献资料-免费论文范文...
- 《LeetCode力扣练习》第206题 反转链表 Java
- 09-2.部署 dashboard 插件
- 【1】万魂杀MMORPG研发回顾
- .Net开发中的多线程编程总结
- CnGAN:面向跨网用户偏好推荐的生成对抗网络
- jmeter中CSV Data Set Config的使用
- java+2e10_CoreJavaE10V1P3.10 第3章 Java的基本编程结构-3.10 数组(Arrays)
- 暨“与孙鑫老师面对面,畅谈程序人生”专题讲座
- 玲珑3D与几何画板的比较
- autojs开发的ip地址查询工具开源代码免费分享
- CSS3:颜色渐变和重复性渐变
- python pandas处理excel 统计数据_python使用pandas处理excel数据
- Centos7创建CA和申请证书
- 【基于STM32F103+AS608的智能打卡系统】
- mysql创建外键时1025_navicat设置外键报错1025怎么办
- 128-Vue中的事件修饰符-阻止冒泡事件
- XAMPP的下载、安装、配置
- 【推荐】《铁甲钢拳/铁甲机器人》[BD-R/1.1G][中英双字]1024分辨率高清下载
热门文章
- 多线程模拟火车站卖票-继承Thread类
- CAD怎么转换成PDF格式?CAD转PDF教程
- 物流、快递行业实名认证API
- NSIS打包软件报(安装失败)
- jxl去掉excel有效性验证
- centos 6.5 编译php mysql5.6_CentOS 6.5编译安装Nginx+MySQL+PHP
- Pyecharts Geo绘制可视化地图并展示坐标位置
- 利用网易有道在谷歌浏览器进行网页滑词翻译
- 移动硬盘只显示盘符,不显示容量、不能打开、并且会阻塞其他应用
- 编制一个返回值为bool型的函数isPrimer(),用于判断参数是否为素数(是素数返回true,否则false),自编main函数用于测试