cocos2dx 實現國際化-簡單點就是怎麼用中文

當纔開始接觸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的中文配置文檔:

image(圖片不能放大??)

image

裏面就是簡單的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類,直接讓他解析不一樣的配置文件就是了,其餘的全部代碼就不用改。就能夠實現語言的動態切換了。

 

明白了吧?

相關文章
相關標籤/搜索