一、文件操作
游戏中其实不需要什么复杂的文件读写操作,FileUtils类主要的功能:设置加载、保存文件的所在路径。
1、文件内容读取
获得二进制数据(getDataFromFile)、获得字符串内容(getStringFromFile)、获得压缩包里面内容(getFileDataFromZip)
2、文件查找
搜索路径(setSearchPaths)、子区分路径用来设置搜索顺序(setSearchResolutionsOrder)
根据文件名返回全路径(fullPathForFilename)、根据关系文件路径获得全路径名(fullPathFromRelativeFile)
3、文件判断
文件是否存在(isFileExist)、是否是绝对路径(isAbsolutePath)、文件失败是否显示提示信息框(setPopupNotify/isPopupNotify)
4、文件写入
getWritablePath
5、例子
void TestResolutionDirectories::onEnter()
{
FileUtilsDemo::onEnter();
auto sharedFileUtils = FileUtils::getInstance();
std::string ret;
//清除以前的缓存
sharedFileUtils->purgeCachedEntries();
_defaultSearchPathArray = sharedFileUtils->getSearchPaths();
std::vector<std::string> searchPaths = _defaultSearchPathArray;
searchPaths.insert(searchPaths.begin(), "Misc");
//设置总的搜索路径,并且会清除掉以前的内容,他能同时添加相对路径与绝对路径
//如果是相对路径,他会自动补齐为绝对路径,但是是默认的资源路径。
sharedFileUtils->setSearchPaths(searchPaths);
//设置搜索资源路径顺序,文件名相同时根据资源顺序优先搜索
_defaultResolutionsOrderArray = sharedFileUtils->getSearchResolutionsOrder();
std::vector<std::string> resolutionsOrder = _defaultResolutionsOrderArray;
resolutionsOrder.insert(resolutionsOrder.begin(), "resources-ipadhd");
resolutionsOrder.insert(resolutionsOrder.begin()+1, "resources-ipad");
resolutionsOrder.insert(resolutionsOrder.begin()+2, "resources-widehd");
resolutionsOrder.insert(resolutionsOrder.begin()+3, "resources-wide");
resolutionsOrder.insert(resolutionsOrder.begin()+4, "resources-hd");
resolutionsOrder.insert(resolutionsOrder.begin()+5, "resources-iphone");
//3.x里面可以使用c++标准std::string(string)或者使用引擎的String
sharedFileUtils->setSearchResolutionsOrder(resolutionsOrder);
for( int i=1; i<7; i++) {
auto filename = String::createWithFormat("test%d.txt", i);
//根据文件名得到此文件的全路径,如果文件名相同的怎么办?
//他有搜索目录顺序,也就是上面的resolutionsOrder里面的顺序,查到一个就结束了,
//不会在往下面查了。
ret = sharedFileUtils->fullPathForFilename(filename->getCString());
log("%s -> %s", filename->getCString(), ret.c_str());
}
}
二、字库
ttf:TTF(TrueTypeFont)是Apple公司和Microsoft公司共同推出的字体文件格式,随着windows的流行,已经变成最常用的一种字体文件表示方式。
fnt:图字库,首先介绍一下图字是怎么来的?其实这个很早很早了,记得80后在95年开始玩DOS下的仙剑奇侠传的时候,那些令人难忘的中文对话吧!
DOS下做游戏,使用的是C语言,不要说写字了,很多复杂的操作甚至涉及驱动。那时候绘图就是利用将图片中的像素取出来后绘制在屏幕上,所以处
理游戏中的中文, 就只有把这些文字的像素预先写到BMP或二进制文件中, 然后读取出来再设置屏幕像素以实现。后来进入DDRAW的时代,可以使用
WINDOWS系统中的字库来写字了, 把DDRAW的后台表面进行LOCK,取出其DC,然后用GDI将文字写到其DC上, 这种做法后面也延续了很久, 但GDI进行
TextOut的效率非常慢,你要是想像梦幻西游一样满屏写了,那得卡死,解决方案是什么?还是图字。专业的游戏开发者会将所用到的字都预处理生成
到一张图片中,通过一个编码与纹理UV对应文件来进行纹理UV的获取后做为顶点的UV值然后进行绘制,有也的在每一帧中实时的将需要的字使用DDRAW
写字的方法绘制到相应的纹理上然后使用文字编码与纹理UV对应信息来进行绘制,这样效率就提高很多了。目前比较流行的做法是使用一张png图片来
存储用到的文字,一个.fnt文件来存储文字图片说明信息。
windows上可以使用BMFont工具自己制作fnt文件,链接:BMFont使用及介绍
我们可以随便打开一个fnt的文件,看里面的内容:
第一行是对字体的介绍。
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 :外边距,就是相临边缘的距离。
第二行是对应所有字贴图的公共信息
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像素防止粘在一起。
通过上面这些信息,引擎可以通过编码找到相应的文字并取出对应的纹理块。
下面看看使用例子:
//------------------ttf字体的使用方法----------------------
//内容,设置字体(就是文件名字),字体大小
auto top = LabelTTF::create(pFont, pFont, 24);
//内容,字体,字体大小,所占大小(标签大小),文本水平方向对齐方式,文本垂直垂直方向对齐方式
auto left = LabelTTF::create("alignment left", pFont, fontSize,
blockSize, TextHAlignment::LEFT, verticalAlignment[vAlignIdx]);
//------------------fnt字体的使用方法----------------------
//内容,字体,间隔,对齐方式,偏移
auto leftBMF = LabelBMFont::create("alignment left BMF", "fonts/bitmapFontTest.fnt", 0, TextHAlignment::LEFT, Vec2(0,0));
//设置letf的zorder值比leftcolor大,让其显示在上面
this->addChild(leftColor, -1, kTagColor1);
this->addChild(left, 0, kTagLabel1);
this->addChild(leftBMF, 0, kTagLabel1);
对于LabelTTF(其他的一样,像LabelBMFont、LabelAtlas等)里面有很多create接口,里面有一个参数 const Size& dimensions 我们需要特别
注意下他默认值为Size(0,0);表示自己计算宽度与高度,如果设置成Size(width, 0)就只自己计算高度,别的类似,如果dimensions设置过小,
就会截取显示部分内容,如果要换行可以直接在文本内容里面使用"\n",例如:"huang\nzhifei"这样就会显示
huang
zhifei
auto ttf1 = LabelTTF::create("Alignment 1\nnew line", "Helvetica", 12,
Size(245, 32), TextHAlignment::CENTER);
这两例子本身比较简单,这里只是抛砖引玉一下,后续做到项目时会用到的很多,到时候在来详细分析。
本文介绍了C++中文件操作的常见方法,包括FileUtils类的使用,如读取二进制数据、字符串内容,文件路径处理,以及文件判断和写入操作。此外,还探讨了游戏开发中的字库概念,特别是fnt格式图字库的由来和作用,以及如何使用BMFont工具创建fnt文件。

3022

被折叠的 条评论
为什么被折叠?



