zoukankan      html  css  js  c++  java
  • 【Cocos2d-x游戏开发】解决Cocos2d-x中文乱码的三种方法

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

                                                                      

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

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

     1 char *HelloWorld::FontToUTF8(const char* font){
     2     int len = MultiByteToWideChar(CP_ACP,0,font,-1,NULL,0);
     3     wchar_t *wstr = new wchar_t[len+1];
     4     memset(wstr,0,len+1);
     5     MultiByteToWideChar(CP_ACP,0,font,-1,wstr,len);
     6     len = WideCharToMultiByte(CP_UTF8,0,wstr,-1,NULL,0,NULL,NULL);
     7     char *str = new char[len+1];
     8     memset(str,0,len+1);
     9     WideCharToMultiByte(CP_UTF8,0,wstr,-1,str,len,NULL,NULL);
    10     if(wstr)delete[] wstr;
    11     return str;
    12 }

    函数的使用方法如下:

    1 auto label = Label::creat(HelloWorld::FontToUTF8("不如跳舞"),"Arial",36);
    2 label->setPosition(320,300);
    3 this->addChild(label);

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

    二、使用iconv库来显示中文

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

    #include  "cocos2dexternalwin32-specificiconincludeiconv.h"

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

     1 int HelloWorld::GBKToUTF8(std::string &gbkStr,const char* toCode,const char* formCode){
     2     iconv_t iconvH;
     3     iconvH = iconv_open(formCode,toCode);
     4     if(iconvH == 0){
     5         return -1;
     6     }
     7     const char* strChar = gbkStr.c_str();
     8     const char** pin = &strChar;
     9     size_t strLength = gbkStr.length();
    10     char *outbuf = (char*) malloc(strLength*4);
    11     char *pBuff = outbuf;
    12     memset(outbuf,0,strLength*4);
    13     size_t outLength = strLength*4;
    14     if(-1 == iconv(iconvH,pin,&strLength,&outbuf,&outLength)){
    15         iconv_close(iconvH);
    16         return -1;
    17     }
    18     gbkStr = pBuff;
    19     iconv_close(iconvH);
    20     return 0;
    21 }

    函数的使用方法如下:

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

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

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

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

      1.xml方法

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

    1 <dict>  
    2     <key>string1</key>  
    3     <string>欢迎学习cocos2dx</string>  
    4     <key>string2</key>  
    5     <string>使用XML显示中文</string>  
    6     <key>string3</key>  
    7     <string>key与string标签中的内容是对应的</string> 
    8 </dict>  

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

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

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

     1     //创建词典类实例,将xml文件加载到词典中
     2     auto *chnStrings = Dictionary::createWithContentsOfFile("CHN_Strings.xml");
     3     //通过xml文件中的key获取value
     4     const char *str1 = ((String*)chnStrings->objectForKey("string1"))->getCString();
     5     //创建一个标签显示出来
     6     auto* label1 = Label::create(str1, "Arial", 36);
     7     label1->setPosition(320,270);
     8     addChild(label1);
     9 
    10     const char *str2 = ((String*)chnStrings->objectForKey("string2"))->getCString();
    11     auto* label2 = Label::create(str2, "Arial", 36);
    12     label2->setPosition(320, 180);
    13     addChild(label2);
    14 
    15     const char *str3 = ((String*)chnStrings->objectForKey("string3"))->getCString();
    16     auto* label3 = Label::create(str3, "Arial", 36);
    17     label3->setPosition(320, 90);
    18     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/ 。解压之后我们只需要保留其中的srclib_json和

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

      

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

     1 std::string ReadJson::getString(std::string name){
     2     Json::Reader reader;
     3     Json::Value root;
     4 
     5     std::string data = FileUtils::getInstance()->getStringFromFile("language.json");
     6 
     7     if (reader.parse(data, root, false) == true)
     8     {
     9         return root[name].asCString();
    10     }
    11 }

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

      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中的字段了。比如:

      

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

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

      

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

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

  • 相关阅读:
    做项目时写的数据库操作类。SqlHelper.cs(三)
    写的登录三层结构demo(工厂模式)
    在GridView中进行排序
    微信小程序 POST请求
    mysql replace into用法详细说明
    ThinkPHP Where 条件中使用表达式
    Google发转码工具 可将安卓程序转至iOS
    IOS笔记 本地化多语言支持
    persits.jpeg 水印组件
    PHP 数组操作
  • 原文地址:https://www.cnblogs.com/msxh/p/5588775.html
Copyright © 2011-2022 走看看