众所周知,Cocos2d-x是一款不错的开源引擎,但是在Cocos2d-x中直接使用中文是无法正确显示的。比如下面的情况:

  解决这个问题常用的有三种方法:1.通过转换为UTF-8编码来显示。2.使用iconv库来解决。3。使用解析xml或者json文件来解决。这里推荐使用第三种方法来解决,因为比较简单方便,还能支持I18N国际化。下面我们来一一详细了解一下每种解决方案的具体实现:

一、通过转换为UTF-8编码的方式显示出来,建立一个方法用于转换中文到对应的UTF-8编码,具体代码如下:

 char *HelloWorld::FontToUTF8(const char* font){
int len = MultiByteToWideChar(CP_ACP,,font,-,NULL,);
wchar_t *wstr = new wchar_t[len+];
memset(wstr,,len+);
MultiByteToWideChar(CP_ACP,,font,-,wstr,len);
len = WideCharToMultiByte(CP_UTF8,,wstr,-,NULL,,NULL,NULL);
char *str = new char[len+];
memset(str,,len+);
WideCharToMultiByte(CP_UTF8,,wstr,-,str,len,NULL,NULL);
if(wstr)delete[] wstr;
return str;
}

函数的使用方法如下:

 auto label = Label::creat(HelloWorld::FontToUTF8("不如跳舞"),"Arial",);
label->setPosition(,);
this->addChild(label);

这种方法仅仅依靠代码实现而不不需要额外的设置,但是效果并不是很稳定,容易产生某些错误或者依然乱码,因此不推荐该方法。

二、使用iconv库来显示中文

首先在创建好的cocos2d-x项目中搜索包含了iconv的文件名,然后把文件iconv.h的路径引入,如:

#include  "cocos2d\external\win32-specific\icon\include\iconv.h"

然后在项目中创建一个GBKToUTF8方法来实现编码的转换:

 int HelloWorld::GBKToUTF8(std::string &gbkStr,const char* toCode,const char* formCode){
iconv_t iconvH;
iconvH = iconv_open(formCode,toCode);
if(iconvH == ){
return -;
}
const char* strChar = gbkStr.c_str();
const char** pin = &strChar;
size_t strLength = gbkStr.length();
char *outbuf = (char*) malloc(strLength*);
char *pBuff = outbuf;
memset(outbuf,,strLength*);
size_t outLength = strLength*;
if(- == iconv(iconvH,pin,&strLength,&outbuf,&outLength)){
iconv_close(iconvH);
return -;
}
gbkStr = pBuff;
iconv_close(iconvH);
return ;
}

函数的使用方法如下:

 //在场景中加入中文标签
std::string hello = "不如跳舞";
GBKToUTF8(hello,"gb2312","utf-8");
CCLabelTTF *label1 = CCLabelTTF::create(hello.c_str(),"Arial",);
label->setPosition(,);
this->addChild(label);

不过Android平台上的Cocos2d-x并没有提供相应的库,这就需要开发者自行将iconv库引入到项目中,然后编译。

由于前两种方法都比较复杂而且不稳定,因此推荐使用第三种方法(读取xml文件或者json文件的方法显示中文)。

三、读取外部xml或者Json文件显示中文

  1.xml方法

  使用xml解析中文十分的简单,首先我们需要准备一个xml文件。如下所示: 

 <dict>
<key>string1</key>
<string>欢迎学习cocos2dx</string>
<key>string2</key>
<string>使用XML显示中文</string>
<key>string3</key>
<string>key与string标签中的内容是对应的</string>
</dict>

  在xml文件中,<key>和<string>两个标签要保持一一对应的关系。这样就可以通过对key标签中的内容索引到对应的中文内容,从而显示中文字符。

  需要注意的是保存此xml文件的时候编码格式要使用UTF-8(可以使用notepad++或者sublimeText之类的软件完成)。

  之后我们就可以解析xml文件来读取中文啦:

     //创建词典类实例,将xml文件加载到词典中
auto *chnStrings = Dictionary::createWithContentsOfFile("CHN_Strings.xml");
//通过xml文件中的key获取value
const char *str1 = ((String*)chnStrings->objectForKey("string1"))->getCString();
//创建一个标签显示出来
auto* label1 = Label::create(str1, "Arial", );
label1->setPosition(,);
addChild(label1); const char *str2 = ((String*)chnStrings->objectForKey("string2"))->getCString();
auto* label2 = Label::create(str2, "Arial", );
label2->setPosition(, );
addChild(label2); const char *str3 = ((String*)chnStrings->objectForKey("string3"))->getCString();
auto* label3 = Label::create(str3, "Arial", );
label3->setPosition(, );
addChild(label3);

  这样中文就可以正确的显示出来了。

  

  2.Json方法

  Json的方法和xml大同小异,而且更简单,首先我们同样准备一个json文件,命名为language.json:

  

{
"start":"开始游戏",
"setting":"设置",
"exitGame":"退出游戏",
"info":"马三小伙儿",
"restart":"重新开始",
"win":"游戏胜利",
"returnMenu":"返回主菜单",
"bgMusic":"背景音乐",
"effectMusic":"音效音量"
}

  然后我们使用Jsoncpp库来读取json文件,jsoncpp可以到这里去下载:https://sourceforge.net/projects/jsoncpp/ 。解压之后我们只需要保留其中的src\lib_json和

include\json下的文件,并将其放在项目的Classess\json目录下。或者图省事可以直接下载我这个配置好的json目录 (提取码:40bb)。最后把json库导入到我们的cocos2d-x项目中。如图:

  

  为了方便使用和修改我们这里创建一个ReadJson类,这个类里面只有一个静态的std::string ReadJson::getString(std::string name)方法,用来读取json信息:

 std::string ReadJson::getString(std::string name){
Json::Reader reader;
Json::Value root; std::string data = FileUtils::getInstance()->getStringFromFile("language.json"); if (reader.parse(data, root, false) == true)
{
return root[name].asCString();
}
}

  一步步解释一下函数中的内容:

  Json::Reader 这个类是用来解析json文件的;

  Json::Value   这个类代表了json的一段数据;

  FileUtils::getInstance()->getStringFromFile("language.json") 这个函数用来加载一个json文件,其返回值是一个字符串;

  调用reader(Json::Reader类型)的parse函数开始解析json文件,解析的结果会保存在root对象中(Json::Value类型),读取它的值很简单,就像普通的数组使用索引一样,比如root["id"]。然后还可以根据值的类型进行转换,例如:root["name"].asCString();

  我们直接在程序中直接调用这个类的静态函数就可以方便的读取json中的字段了。比如:

  

 //开始游戏按钮
auto start_button = Button::create("button.png");
start_button->setScale();
//调用ReadJson的getString()方法
start_button->setTitleText(ReadJson::getString("start"));
start_button->setTitleFontName("微软雅黑");
start_button->setTitleFontSize();
start_button->setPosition(Vec2(visibleSize.width / , visibleSize.height*0.7));
this->addChild(start_button);

  这样中文也可以正常的显示出来了。

  

  总结上面的三种方法,无疑是第三种方法最方便和稳定了。而且使用解析xml或者json还有另外的优势就可以很方便地支持国际化。在游戏中设置一个语言选择按钮,然后根据选项来决定加载哪个xml或者json文件,这样可以很方便的快捷的切换游戏语言。

作者:马三小伙儿
出处:http://www.cnblogs.com/msxh/p/5588775.html
请尊重别人的劳动成果,让分享成为一种美德,欢迎转载。另外,文章在表述和代码方面如有不妥之处,欢迎批评指正。留下你的脚印,欢迎评论!

【Cocos2d-x游戏开发】解决Cocos2d-x中文乱码的三种方法的更多相关文章

  1. 解决swfupload上传控件文件名中文乱码问题 三种方法 flash及最新版本11.8.800.168

    目前比较流行的是使用SWFUpload控件,这个控件的详细介绍可以参见官网http://demo.swfupload.org/v220/index.htm 在使用这个控件批量上传文件时发现中文文件名都 ...

  2. 解决jmeter中文乱码的三种方法

    1.在Jmeter中的Http请求中,在内容编码后填入“utf-8”. 2.在本地文件存储Jmeter的bin目录下,修改jmeter.properties文件. (1)用记事本打开jmeter.pr ...

  3. asp.net中URL参数传值中文乱码的三种解决办法

    在做Asp.Net开发的时候,参数传递中文时,经常会遇到页面乱码的问题,下面是在网上收集的相关资料,请大家参考: 解决的方法一般有3种: 1.设置web.config文件 <system.web ...

  4. eclipse解决properties文件中文乱码(两种方试)

    第一种:大多数网上搜到的情况(不靠谱) 第一步:windows-->properties-->General-->Content Types-->text(如下图) 第二步:p ...

  5. 解决php中文乱码的两种方法

    第一种是添加html标签变为如下格式: <html> <head> <meta http-equiv="Content-Type" content=& ...

  6. Java Web开发: Tomcat中部署项目的三种方法

    web开发,在tomcat中部署项目的方法: 可以参考http://m.blog.csdn.net/blog/u012516903/15741727 定义$CATALINA_HOME指的是Tomcat ...

  7. 解决Coursera视频无法观看的三种方法(亲测有效)

      ​   最近在coursera上课时出现了视频黑屏,网页缓冲,无法观看等问题,经过查询发现很多人也有同样的问题.对于不同的原因,一般来说解决方法也不同.这里有三种办法,大家可以挨个尝试,肯定有一个 ...

  8. 解决MongoDB磁盘IO问题的三种方法

    1.使用组合式的大文档 我们知道MongoDB是一个文档数据库,其每一条记录都是一个JSON格式的文档.比如像下面的例子,每一天会生成一条这样的统计数据: { metric: "conten ...

  9. URL传参中文乱码的一种解决方法

    中文乱码是由于,发送和接收方使用的编码解码格式不一致导致,以下是关于url传参解决中文乱码的一种方法,最后根据各种编码格式尝试解码,发现正确的解码格式 string strQueryString = ...

随机推荐

  1. poj1988(并查集)

    题目链接:http://poj.org/problem?id=1988 题意:有n个箱子,初始时每个箱子单独为一列: 接下来有p行输入,M, x, y 或者 C, x: 对于M,x,y:表示将x箱子所 ...

  2. php数组的创建及操作

    //数组的创建 //1 $usernames = array('李彦宏','周宏伟','马云','俞敏洪','李开复'); echo $usernames; //array,打印类型 echo '&l ...

  3. Volley学习总结

    本文主要包括以下内容 volly基本操作(String与Json类型) volly图片操作 自定义volly volly源码分析 Volley简单易用,在性能方面也进行了大幅度的调整,它的设计目标就是 ...

  4. JavaScript的内置对象和浏览器对象

    在javascript中对象通常包括两种类型:内置对象和浏览器对象,此外,用户还可以自定义对象. 对象包含两个要素:1.用来描述对象特性的一组数据,也就是若干变量,通常称为属性.2.用来操作对象特性的 ...

  5. windows  远程桌面命令 mstsc

    win+R------>mstsc: 弹出: 目标机必开远程

  6. Python内置的HTTP协议服务器SimpleHTTPServer

    [root@ok 6FE5-D831]# python -m SimpleHTTPServer 一条命令,HTTP服务就搭起来了!!! 方便朋友下载,自己的文件!!

  7. 攻城狮在路上(伍)How tomcat works(四)Tomcat的默认连接器

     在第4章中将通过剖析Tomcat4的默认连接器的代码,讨论需要什么来创建一个真实的Tomcat连接器.     注意:本章中提及的“默认连接器”是指Tomcat4的默认连接器.即使默认的连机器已经被 ...

  8. bzoj 1415 期望+记忆化搜索 ****

    aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAAdkAAAIfCAIAAACzfDFhAAAgAElEQVR4nOy9bVwTW57vm5fnhed+Pn

  9. 初识RPC协议

    什么是rpc框架 先回答第一个问题:什么是RPC框架? 如果用一句话概括RPC就是:远程调用框架(Remote Procedure Call) 那什么是远程调用? 通常我们调用一个php中的方法,比如 ...

  10. 第十篇:扩展SOUI的控件及绘图对象(ISkinObj)

    尽管SOUI已经内置了大部分常用的控件,很显然内置控件很难满足各种应用的形式各异的需求. 因此只有提供足够的扩展性才能满足真实应用场景. 除了将系统尽可能的组件化外,SOUI在控件自绘(SWindow ...