- 问题的提出
使用Cocos2d进行游戏开发时如果想显示中文字符会乱码,或者显示不了的情况。网上说是因为编码的问题——“VS默认源文件的字符集是多字节字符集,既本地化语言字符集,如果你用的系统是中文系统,简体中文,默认字符集是GBK,源码是不包含非ASCLL码。要让其在win32上正常显示,就需要将其转成UTF-8。”于是又搜索了半天终于发现了两种可以解决这个问题的办法。本人亲测可行。
【PS:博主的开发平台为vs2012 +cocos2dx 3.6】
方法一:使用第三方库iconv.h
先引用一段百度百科的解释:
「 头文件"“iconv.h”,iconv命令可以将一种已知的字符集文件转换成另一种已知的字符集文件。它的作用是在多种国际编码格式之间进行文本内码的转换。 」
既然它的作用是在多种国际编码格式之间进行文本内码的转换,那我们就可以在这个库的基础上编写自己的函数把GBK转换为UTF-8啦!!而且iconv.h这个头文件是可以在cocos的文件夹里找到的(由此看来官方也是提倡这种解决办法的??),我的路径是F:\cocos2d-x-3.6\external\win32-specific\icon\include,2.x的版本则应该是cocos2dx\platform\third_party\win32\iconv
事不宜迟,下面附上源代码:
GBKToUTF8.h
<pre name="code" class="cpp">#ifndef _GBKTOUTF8_H_ #define _GBKTOUTF8_H_ #include "cocos2d.h" //包含这个头文件,iconv库是一个字符集转换的开源的库,cocos2dx支持的编码是UTF-8, //在win32下使用的编码是GB2312,所以要转化一下,才能显示中文 #include "iconv.h" //记住附加依赖项libiconv.lib或者使用以下的代码 #pragma comment(lib,"libiconv.lib") //就是一个函数没有分装成类 int GBKToUTF8(std::string & gbkStr,const char* toCode,const char* fromCode); #endif
GBKToUTF8.cpp
<pre name="code" class="cpp">#include "GBKToUTF8.h" //以下函数是从网上copy的,试了一下可以解决问题 int GBKToUTF8(std::string & gbkStr,const char* fromCode,const char* toCode) { iconv_t iconvH; //这个函数调用的作用是将formCode的编码转换成toCode的编码,我们一般调用的时候是GB2312 UTF-8 //因为系统又的编码支持有的不支持所以就有可能返回0 iconvH = iconv_open(toCode,fromCode); //如果返回值为0代表不可以转化 if (iconvH == 0) { return -1; } //将string类型转化为char *类型 const char* strChar = gbkStr.c_str(); //以下是基础不说了 const char** pin =&strChar; size_t strLength = gbkStr.length(); char* outbuf = (char*)malloc(strLength*4); char* pBuff = outbuf; //这里GB2312和UTF-8的位数是1:4不明白,知道的人说一下 memset(outbuf,strLength*4); size_t outLength =strLength*4; //第二个参数表示转化前字符的地址,以后的参数分别是转化前字符的长度,转化后的存储地址,转化后的长度 if (-1 == iconv(iconvH,pin,&strLength,&outbuf,&outLength)) { free(pBuff); iconv_close(iconvH); return -1; } gbkStr = pBuff; iconv_close(iconvH); return 0; }
使用方法:
这里以HelloWorldScene.cpp为例:
<pre name="code" class="cpp">#include "HelloWorldScene.h" #include "GBKToUTF8.h" USING_NS_CC; Scene* HelloWorld::createScene() { auto scene = Scene::create(); auto layer = HelloWorld::create(); scene->addChild(layer); return scene; } bool HelloWorld::init() { if ( !Layer::init() ) { return false; } Size visibleSize = Director::getInstance()->getVisibleSize(); // 此处开始为测试函数的代码 std::string str = "中文版的HelloWorld"; GBKToUTF8(str,"GB2312","UTF-8"); CCLabelTTF * label = CCLabelTTF::create(str.c_str(),"/fonts/方正静蕾简体.ttf",50); ttf3->setPosition(ccp(visibleSize.width/2,visibleSize.height/2)); this->addChild(label); return true; }
运行结果:
如果编译出现找不到iconv.h的可以看这里:http://www.jb51.cc/article/p-bgnqaowb-uz.html
方法二:制作字体图集 +LabelBMFont + xml读取文字
LabelBMFont类来自图片文件,所以其实它的作用就相当于精灵表单,而其中的每一个字符则相当于精灵表单中的单个精灵对象。字符图集其实就是一张大的图片,其中包含了所有要显示的字符以及描述字符在图集中位置的坐标数据。这种字符图集的格式为.fnt,制作它们需要一个工具:Bitmap Font Generator【点击可下载】。默认安装即可。
下面看看如何使用该工具:
1.准备好需要的文本
打开记事本,创建一个文本文件,写入你希望使用的文字,注意,在保存的使用要选择 UTF-8 格式。
2. 设定字体
Options->Fontsettings,在Font那里选择你想要的字体,其他可以不用修改。
3. 选择需要的字符
Edit->Select chars from file,选择刚刚创建的文本文件。
加载好后我们会发现需要显示的字符已经被选中。
4. 导出图片
Options->Save bitmap font as…
下面来看看导出的对话框
Padding,文字的内边框,或者理解为文字的周边留空要多大 做后期样式时这个属性很重要,需要预留空间来给描边、发光等特效使用 比如我预计我的样式要加一个2px的边框,然后加一个右下角2px的投影效果,所以我设定了padding:2px 4px 4px 2px
BitDepth,必须32位,否则没有透明层
Presets,字体初始化的预设的颜色通道设定,也就是说字体的初始颜色设定是什么样的,建议都用白色字,可以直接设定为White text with alpha,即白色字透明底。
Font descript,字体描述文件,可以使用text或者xml 也就是fnt文件格式
Textures,纹理图片格式,果断png。
成功后会生成两个文件,分别是png和fnt,把它们赋值到项目的Resources文件夹下,再在该文件夹新建一个xml文件。
格式如下:
<?xml version="1.0" encoding="utf-8" ?> <plist version="1.0"> <dict> <key>char</key> <string>hello</string> <key>chinese</key> <string>你好,世界!</string> </dict> </plist>
每个key指对应一个string,待会儿的代码需要用到。
最后就是使用了,也是以HelloWorldScene.cpp为例:
#include "HelloWorldScene.h" USING_NS_CC; Scene* HelloWorld::createScene() { auto scene = Scene::create(); auto layer = HelloWorld::create(); scene->addChild(layer); return scene; } bool HelloWorld::init() { if ( !Layer::init() ) { return false; } Size visibleSize = Director::getInstance()->getVisibleSize(); // 此处开始为测试代码 Dictionary* dic = Dictionary::createWithContentsOfFile("word.xml"); // 这里用到的chinese指就是xml里的key值,其对应的就是字符串“你好,世界!” String* strChinese = (String*)dic->objectForKey("chinese"); LabelBMFont* bmFont = LabelBMFont::create(strChinese->getCString(),"word.fnt"); bmFont->setPosition(visibleSize.width/2,visibleSize.height/2); addChild(bmFont); return true; }
运行结果:
参考文章:
cocos2d-x中添加显示文字的三种方式 LabelTTF、LabelBMFont和 LabelAtlas
原文链接:https://www.f2er.com/cocos2dx/341996.html