當纔開始接觸cocos2dx的來講,要實現中文的顯示,那麼他們就回到網上查,固然方法也不少。這裏就總結幾個,而後介紹怎麼封裝實現國際化。json
先聲明一個很重要的內容:xcode
cocos2dx 的label之類(包括全部的字符串,好比CCLog)的建立,須要傳入一個const char* 即string,這裏指望的是以"UTF-8"的編碼形式構成的字符串。也就是運行期間他的數據時UTF-8編碼的。緩存
因此不少人直接在vs裏面寫CClog(「中文」);的時候控制檯輸出實際上是亂碼的,由於vs默認不是使用utf8編碼的形式,因此不能直接用的。函數
可是xCode是能夠的,CClog(「中文」);在xCode裏面輸出的就是中文。由於xcode是使用utf8編碼。工具
因此咱們要顯示中文,測試
解決方案1:把含有中文的文件另存爲utf8格式,便可解決(這個我沒測試過);this
可是就很麻煩,固然能夠把全部的文字定義成變量,放到一個頭文件裏面,那麼要改編碼的就只有一個頭文件了,這樣看起來稍微優雅了點。可是仍是很不爽,不能實現國際化。編碼
其實直接把文字寫在代碼裏面是一件很不值得推崇的方式(固然圖簡便仍是能夠的,但你須要知道他之後會帶來的麻煩會很大),咱們應該把文字獨立出來,不跟咱們的代碼參合,就像Android的string.xml同樣(是否是一下點醒了你?)。spa
因而解決方案2:.net
咱們把全部的文字寫到一個配置文件裏面,咱們程序直接根據key就獲取到了utf8的文字,無論當前的源文件是否是utf8的格式的,由於他們再也不相干了。請慢慢往下面看。
對於配置文件,我選擇json格式(爲何選擇json,沒緣由,就喜歡json,乾淨利落)。
下面給出例子:
個人json的中文配置文檔:
裏面就是簡單的json格式的配置文檔(關於不懂json的,我後面會寫一篇json的解析的文章,目前先無論,或者大家也能夠用其餘的格式,好比xml,這樣cocos2dx已經有解析方案了,原理是同樣的)。
下面就是咱們json解析和使用的代碼了(LFString.h和cpp):
#pragma once
#include <string>
#include "json/json.h"
#include "LFFileUtiles.h"
#include <map>
using namespace std;
/**
* 字符串工具,是中文字符的鍵值對
*/
class LFStrings
{
public:
static bool init();
static string getValue(string _key);
static bool haveValue(string _key);
private:
static bool parseFile(string relativePath);
static map<string,string> data;
};
------cpp
#include "LFStrings.h"
#define ROOT_PATH "config/"
#define FILE_MAIN "strings.txt"
// 所支持的標籤
#define LABLE_KEY "key"
#define LABLE_VALUE "value"
#define LABLE_INCLUDE "include"
map<string,string> LFStrings::data;
// 用於緩存已經解析了的文件
static map<string,int> paresedFile;
bool LFStrings::init()
{
data.clear();
paresedFile.clear();
return parseFile(FILE_MAIN);
}
bool LFStrings::parseFile(string relativePath)
{
// 看是否已經解析過了
if (paresedFile.find(relativePath) != paresedFile.end())
{
CCLog("Waring : %s --> file[%s] is pared over before or is in parsing now ,do you include it again???",__FUNCTION__,relativePath.c_str());
return true;
}
paresedFile.insert(pair<string, int>(relativePath,0));
string path = string(ROOT_PATH)+relativePath;
CCLog("%s parsing file [%s] ....",__FUNCTION__,path.c_str());
Json::Reader reader;
Json::Value root;
unsigned long size;
const char* doc = LFFileUtiles::getLFFileUtiles()->readResourceFile(path,&size);
if (size == 0)
{
CCLog("%s ----> file [%s] have no content.",__FUNCTION__,path.c_str());
return true;
}
if (doc == NULL)
{
CCLog("%s ----> doc is NULL , open Error!",__FUNCTION__,path.c_str());
return false;
}
if (!reader.parse(doc,root))
{
CCLog("%s ----> reader.parse failed! [%s]",__FUNCTION__,path.c_str());
CCLog(doc);
delete [] doc;
CCAssert(false,"");
return false;
}
//CCLog(doc);
Json::Value _strings= root["strings"];
if (!_strings.isNull() && _strings.isArray())
{
int _stringNum = _strings.size();
for (int i=0;i<_stringNum;i++)
{
Json::Value onePair = _strings[i];
// 校驗
if(!onePair[LABLE_KEY].isNull() && onePair[LABLE_VALUE].isNull())
{
CCLog("Error : %s there is no %s for %s [%s]",__FUNCTION__,LABLE_VALUE,LABLE_KEY,onePair[LABLE_KEY].asCString());
CCAssert(false,"key 和 value 沒有配對");
continue;
}
if(!onePair[LABLE_VALUE].isNull() && onePair[LABLE_KEY].isNull())
{
CCLog("Error : %s there is no %s for %s [%s]",__FUNCTION__,LABLE_KEY,LABLE_VALUE,onePair[LABLE_VALUE].asCString());
CCAssert(false,"key 和 value 沒有配對");
continue;
}
//有include
if (!onePair[LABLE_INCLUDE].isNull())
{
string file = onePair[LABLE_INCLUDE].asString();
if (!parseFile(file))
{
CCLog("Error : %s parse file %s faild",__FUNCTION__,file.c_str());
return false;
}
}
// 解析鍵值對
if (!onePair[LABLE_KEY].isNull() && !onePair[LABLE_VALUE].isNull())
{
string _key = onePair[LABLE_KEY].asString();
string _value = onePair[LABLE_VALUE].asString();
if (haveValue(_key))
{
CCLog("Waring : %s --> the key [%s] in file[%s] is already used before,we will ignore this key and value[%s]!",__FUNCTION__,_key.c_str(),path.c_str(),_value.c_str());
continue;
}
data.insert(pair<string, string>(_key,_value));
}
}
}
return true;
}
string LFStrings::getValue(string _key)
{
map<string, string>::iterator iter;
//若是map中沒有要查找的數據,它返回的迭代器等於end函數返回的迭代器;
iter = data.find(_key);
if(iter != data.end())
{
return iter->second;
}
CCLog("Waring : LFStrings::getValue --> _key[%s] is not found!",_key.c_str());
return "";
}
bool LFStrings::haveValue(string _key)
{
map<string, string>::iterator iter;
//若是map中沒有要查找的數據,它返回的迭代器等於end函數返回的迭代器;
iter = data.find(_key);
return iter != data.end();
}
使用方法很簡單,遊戲啓動的時候調用:
// 初始化
LFStrings::init();
他就會找Resource下面的config下面的string.txt文件,進行初始化。
每次要用中文的時候直接:LFStrings::getValue(「biaoti」);// 取得標題字符串
便可。這樣就輕鬆實現中文了,之後直接配置,修改就是了。
最後一個問題,怎麼實現國際化:
需呀稍微修改下LFStrings類,直接讓他解析不一樣的配置文件就是了,其餘的全部代碼就不用改。就能夠實現語言的動態切換了。
明白了吧?