眾所周知,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 "cocos2d\external\win32-specific\icon\include\iconv.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/ 。解壓之后我們只需要保留其中的src\lib_json和
include\json下的文件,並將其放在項目的Classess\json目錄下。或者圖省事可以直接下載我這個配置好的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
請尊重別人的勞動成果,讓分享成為一種美德,歡迎轉載。另外,文章在表述和代碼方面如有不妥之處,歡迎批評指正。留下你的腳印,歡迎評論!