久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

移動開發(fā)之淺析cocos2d

 勤奮不止 2013-08-29

移動開發(fā)之淺析cocos2d-x的中文支持問題

  題記:這陣子一直在學(xué)習(xí)cocos2d-x,,其跨平臺的特性確實(shí)讓人舒爽,引擎的框架概念也很成熟,,雖然相應(yīng)的第三方工具略顯單薄,,但也無愧是一件移動開發(fā)的利器啊,,有興趣的朋友有時(shí)間就多了解一下吧 :)

  使用引擎的過程中遇到的問題很多,中文支持便是一例,,雖然問題本身并不復(fù)雜,,但是網(wǎng)上的相關(guān)資料都比較簡單零散,自己搗鼓了幾下,,覺得有必要的整理一下,,以此稍稍方便一下遇到相似問題的朋友,也算是自己的一點(diǎn)點(diǎn)學(xué)習(xí)總結(jié),,可惜自己水平有限,,講的不當(dāng)甚至錯誤的地方請細(xì)心的朋友不吝指出,俗話說的好嘛:貽笑大方事小,,誤人子弟事大也 :)

  一不就是用用setlocale嘛,,簡單!

  之前自己并未深入過C/C++對于多字符編碼的支持問題,,但也算是嘗試過一些相關(guān)的示例程序,,譬如這個(gè)中文版的HelloWorld

#include <cstdio>

#include <clocale>

using namespace std;

int main()

{

    // first we have to set the locale

    setlocale(LC_ALL, "chs");

    // then we use wprintf to output the Chinese string

    wprintf(L"%ls\n", L"世界,,你好");

    // that's all :)

    return 0;

}

  程序的邏輯很簡單,,使用setlocale設(shè)置地域信息,然后使用wprintf輸出對應(yīng)的中文信息,,一切似乎都非常簡單自然,。(注:如果使用GCC編譯上述代碼時(shí),需要將源文件類型改為UTF-8格式,,否則會提示解碼錯誤,,這是GCC的一個(gè)源文件限制)

  類似的,這里也有一個(gè)相同功能的C++程序:

#include <iostream>

using namespace std;

int main()

{

    // first we have to set the output stream locale

    wcout.imbue(locale("chs"));

    // then we use wcout to output the Chinese string

    wcout << L"世界,你好" << endl;

    // that's all :)

    return 0;

}

  代碼的原理部分與之前的代碼如出一轍,,在此不再贅述,,不過比較令我費(fèi)解的是這段代碼在CodeBlocks+MinGW4.4.1環(huán)境下,運(yùn)行時(shí)會引起崩潰(由wcout.imbue(locale("chs"))這行代碼引起),,具體原因沒有細(xì)究,,似乎是GCC的一個(gè)BUG,如有朋友了解,,請不吝告知,,多謝 :)

  關(guān)于以上問題的更多的一些信息可以在這里找到。

  好了,,小小嘗試了一下之后,,就讓我們開始整一整cocos2d-x中的中文了,巧的是cocos2d-x開發(fā)包(有興趣的朋友可以從這里下載)的示例程序中恰好也有一個(gè)HelloWorld,,那么事不宜遲,,就讓我們將這個(gè)程序修改為中文界面吧 :)

  二char 或者 wchar_t,這是一個(gè)問題

  首先讓我們來看看cocos2d-x中原始的HelloWorld里涉及到的文本輸出代碼是哪些(如果你從未接觸過cocos2d,,推薦先熟悉一下其中的基本概念,,網(wǎng)上優(yōu)秀的入門教程很多,譬如這里):

     /////////////////////////////

// 3. add your codes below...

// add a label shows "Hello World"

// create and initialize a label

    CCLabelTTF* pLabel = CCLabelTTF::labelWithString("Hello World", "Arial", 24);

// ask director the window size

CCSize size = CCDirector::sharedDirector()->getWinSize();

// position the label on the center of the screen

pLabel->setPosition( ccp(size.width / 2, size.height - 50) );

// add the label as a child to this layer

this->addChild(pLabel, 1);

  注釋都很明了,,大致意思便是創(chuàng)建一個(gè)CCLabelTTF,,然后設(shè)置對應(yīng)位置,并加入場景的child隊(duì)列,,就這樣~~~在此給張示意例圖:

  OK,,到此我們的當(dāng)前任務(wù)已經(jīng)非常明顯了,就是要將圖中所示的“Hello World”改為“你好世界”,,就是這么簡單 :)

  簡單,,讓我們首先來一次最直接的修改:

    /////////////////////////////

// 3. add your codes below...

// add a label shows "Hello World"

// create and initialize a label

    CCLabelTTF* pLabel = CCLabelTTF::labelWithString(L"你好世界", "Arial", 24);

// ask director the window size

CCSize size = CCDirector::sharedDirector()->getWinSize();

// position the label on the center of the screen

pLabel->setPosition( ccp(size.width / 2, size.height - 50) );

// add the label as a child to this layer

this->addChild(pLabel, 1);

  想法雖然美好,可惜編譯器無情的抱怨了:沒有對應(yīng)的調(diào)用接口……讓我們來看一下labelWithString這個(gè)靜態(tài)函數(shù)的聲明:

  /** creates a CCLabelTTF from a fontname, alignment, dimension and font size */

  static CCLabelTTF * labelWithString(const char *label, const CCSize& dimensions, CCTextAlignment alignment, const char *fontName, float fontSize);

  /** creates a CCLabelTTF from a fontname and font size */

  static CCLabelTTF * labelWithString(const char *label, const char *fontName, float fontSize);

  我們暫時(shí)不用細(xì)究labelWithString的第一個(gè)重載版本,,其實(shí)現(xiàn)了字體顯示的更多細(xì)節(jié)控制,,我們目前關(guān)心的是在源程序中我們調(diào)用的第二個(gè)版本,非常明顯的一點(diǎn)便是其第一個(gè)文本參數(shù),,是一個(gè)常量char指針,,而我們之前做的簡單修改,實(shí)際上是傳入了一個(gè)常量wchar_t指針,,自然便出現(xiàn)了重載函數(shù)不存在的情況……那么接下來我們應(yīng)該如何做呢,?將wchar_t強(qiáng)制轉(zhuǎn)換為char類型,恐怕沒有這么簡單,,考慮ASCII字符A,,其相應(yīng)的wchar_t內(nèi)容編碼可能是這樣的0x00|0x41,,將其強(qiáng)制轉(zhuǎn)換為char之后,其相應(yīng)內(nèi)容其實(shí)并沒有改變,,傳給labelWithString只是相當(dāng)于一個(gè)空字符串而已……那么讓我們來修改labelWithString以讓他支持wchar_t的調(diào)用或者自己動手?jǐn)U展類似的接口,,誠然,以上方案都是可行的,,但是都不是那么簡潔……

  唉,char 或者 wchar_t,,這是一個(gè)問題啊~~~

  三擁抱UTF-8

  其實(shí),,我們還有更簡單的方案,那就是使用UTF-8編碼,,在此讓我簡單的引用一段維基百科上關(guān)于UTF-8的簡介:

  UTF-88-bit Unicode Transformation Format)是一種針對Unicode的可變長度字符編碼定長碼),,也是一種前綴碼。它可以用來表示Unicode標(biāo)準(zhǔn)中的任何字符,,且其編碼中的第一個(gè)字節(jié)仍與ASCII相容,,這使得原來處理ASCII字符的軟件無須或只須做少部份修改,即可繼續(xù)使用,。 

  看到了UTF-8編碼的重要特性之一嗎:與ASCII兼容,!這就是我們想要的 :) 那么事不宜遲,讓我們馬上動手將L“你好世界”轉(zhuǎn)換為UTF-8編碼,,并傳入labelWithString試一試吧:

  等等,,在轉(zhuǎn)碼之前也許你會問:不管UTF-8本身的編碼方式如何,之前我們硬編碼進(jìn)程序中的L“你好世界”這幾個(gè)字符原來是什么編碼呢,?如果我們連原始編碼都不了解,,談何轉(zhuǎn)碼一說呢?呵呵,,你說的非常正確,!只可惜關(guān)于C++中使用什么編碼方式存儲多字節(jié)字符并沒有統(tǒng)一規(guī)定,各個(gè)編譯器期間都有區(qū)別,,可能是UTF-16,,可能是UTF-32,當(dāng)然,,也有可能是UTF-8(這種情況下強(qiáng)制轉(zhuǎn)換就可行了,,盡管仍然很Ugly……),不過幸運(yùn)的是,,Win32API WideCharToMultiByte為我們屏蔽了這些復(fù)雜性,,讓我們馬上來試一試:

inline std::string WideByte2UTF8(const wstring& text)

{

int asciisize = ::WideCharToMultiByte(CP_UTF8, 0, text.c_str(), text.size(), NULL, 0, NULL, NULL);

if (asciisize == ERROR_NO_UNICODE_TRANSLATION ||

asciisize == 0)  

{  

return string();

}

char* resultstring = new char[asciisize];

int convresult = ::WideCharToMultiByte(CP_UTF8, 0, text.c_str(), text.size(), resultstring, asciisize, NULL, NULL);

if (convresult != asciisize)

{  

return string();

}  

std::string buffer(resultstring, convresult);

delete[] resultstring;

return buffer;

}

  

// add a label shows "Hello World"

// create and initialize a label

std::string text = WideByte2UTF8(L"你好世界");

CCLabelTTF* pLabel = CCLabelTTF::labelWithString(text.c_str(), "Arial", 24);

  哈哈,我們的第一步嘗試成功了,,來看一下截圖:

  四還有其他更好的法子嗎,?

  上面的代碼雖然可以完成任務(wù),,但是用到了平臺特有的API,對于像cocos2d-x這般旨在跨平臺的引擎而言,,其實(shí)并不能算作很好的解決方案,,那么我們還有什么其他法子嗎?

  1.wcstombs/mbstowcs怎么樣,?

  其實(shí)C函數(shù)庫中存在類似于WideCharToMultiByte的函數(shù),,他們就是wcstombs/mbstowcs,讓我們馬上來試一試:

//! convert wide string to string

inline std::string WStr2Str(const std::wstring& ws)

{

std::string curLocale = setlocale(LC_ALL, NULL); // get current locale

setlocale(LC_ALL, "chs");

const wchar_t* tSource = ws.c_str();

size_t tDsize = 2 * ws.size() + 1;

char* tDest = new char[tDsize];

memset(tDest,0,tDsize);

wcstombs(tDest,tSource,tDsize);

std::string result = tDest;

delete[] tDest;

setlocale(LC_ALL, curLocale.c_str());

return result;

}

// add a label shows "Hello World"

// create and initialize a label

std::string text = WStr2Str(L"你好世界");

CCLabelTTF* pLabel = CCLabelTTF::labelWithString(text.c_str(), "Arial", 24);

 

  不幸的是以上方案失敗了:

  

  失敗的原因其實(shí)很簡單,,wcstombs是根據(jù)當(dāng)前設(shè)置的locale進(jìn)行轉(zhuǎn)換,,由于此處我們設(shè)置的locale是“chs”,所以裝換的過程是根據(jù)GBK編碼進(jìn)行的(就簡體中文而言),,并非是我們理想中的UTF-8,,自然得不到我們期望的結(jié)果,那么為什么我們此處不設(shè)置localeUTF-8呢,,這是因?yàn)椋?/span>Windows CRT 不支持~~~(唉……),,但是我們至此可以找到一個(gè)這種方案:通過條件編譯實(shí)現(xiàn)對應(yīng)函數(shù)的裝換,即在Win32平臺上調(diào)用WideCharToMultiByte,,其他支持UTF-8 locale平臺則調(diào)用wcstombs,,嗯哼,貌似這個(gè)方案部分做到了跨平臺的特性(對于那些不支持UTF-8 locale的非Win32平臺還是不行~~~) :)

  2. Boost提供的 utf8_codecvt_facet 怎么樣,?

  Boost中提供的utf8_codecvt_facet可以完成類似的UTF-8編碼轉(zhuǎn)換,,可惜作為標(biāo)準(zhǔn)IO庫中codecvt 的一個(gè)擴(kuò)展,與string/wstring協(xié)作時(shí)并不是那么直觀,,有興趣的朋友可以試上一試,,個(gè)人感覺不是特別好 :(

  3. 第三庫如何?

  其實(shí)cocos2d-x的開發(fā)包內(nèi)置了用于編碼轉(zhuǎn)換的iconv庫,,我們可以嘗試一下,,當(dāng)然,更加重量級的還有ICU,,如果你有興趣的也可以研習(xí)一番,,在此我們便就近試一下iconv吧:

bool IConvConvert(const char *from_charset, const char *to_charset, const char *inbuf, int inlen, char *outbuf, int outlen) 

{

    iconv_t cd = iconv_open(to_charset, from_charset);

if (cd == 0) return false;

const char **pin = &inbuf;

char **pout = &outbuf;

memset(outbuf,0,outlen);

size_t ret = iconv(cd,pin,(size_t *)&inlen,pout,(size_t *)&outlen);

iconv_close(cd);

return ret == (size_t)(-1) ? false : true;

}

std::string IConvConvert_GBKToUTF8(const std::string& str)

{

const char* textIn = str.c_str();

char textOut[256];

bool ret = IConvConvert("gb2312", "utf-8", textIn, strlen(textIn),textOut, 256);

return ret ? string(textOut) : string();

}

// add a label shows "Hello World"

// create and initialize a label

std::string text = IConvConvert_GBKToUTF8("你好世界");

CCLabelTTF* pLabel = CCLabelTTF::labelWithString(text.c_str(), "Arial", 24);

  哈哈,這次我們成功了:

  

  不過iconvGNU許可倒是值得考量一下,,對于一些用戶可能產(chǎn)生困擾,,當(dāng)然如果考慮清楚,并且程序規(guī)模不存在問題時(shí),,我們還是推薦iconv的,,否則cocos2d-x也不會自帶iconv了 :)

  4. 自給自足,豐衣足食

  雖然軟件行業(yè)從不提倡重造車輪,,但是如果你還不滿意上述的各類方法,,那么這也算是一條路子了,,優(yōu)點(diǎn)是夠輕量、夠可控等等,;缺點(diǎn)同樣明顯,,很脆弱、花時(shí)間等等,,當(dāng)然如果你確定考慮清楚了,,那就放手干吧,這里給個(gè)示例示例:

//! convert from wstring to UTF8 using self-coding-converting

inline void WStrToUTF8(std::string& dest, const wstring& src){

dest.clear();

for (size_t i = 0; i < src.size(); i++){

wchar_t w = src[i];

if (w <= 0x7f)

dest.push_back((char)w);

else if (w <= 0x7ff){

dest.push_back(0xc0 | ((w >> 6)& 0x1f));

dest.push_back(0x80| (w & 0x3f));

}

else if (w <= 0xffff){

dest.push_back(0xe0 | ((w >> 12)& 0x0f));

dest.push_back(0x80| ((w >> 6) & 0x3f));

dest.push_back(0x80| (w & 0x3f));

}

else if (sizeof(wchar_t) > 2 && w <= 0x10ffff){

dest.push_back(0xf0 | ((w >> 18)& 0x07)); // wchar_t 4-bytes situation

dest.push_back(0x80| ((w >> 12) & 0x3f));

dest.push_back(0x80| ((w >> 6) & 0x3f));

dest.push_back(0x80| (w & 0x3f));

}

else

dest.push_back('?');

}

}

//! simple warpper

inline std::string WStrToUTF8(const std::wstring& str){

std::string result;

WStrToUTF8(result, str);

return result;

}

// add a label shows "Hello World"

// create and initialize a label

std::string text = WStrToUTF8(L"你好世界");

CCLabelTTF* pLabel = CCLabelTTF::labelWithString(text.c_str(), "Arial", 24);

  情況OK :)

  

  5. 還有其他法子,?

目前我能想到的法子就這么多了,,什么,你還有其他法子,,好吧,盡量曬出來吧,,讓我也開開眼界 :)

五. 最后說幾句

  Cocos2d-x的中文支持到此也算聊完了,,有興趣的朋友可以看看,以上內(nèi)容也算是自己的一些學(xué)習(xí)歷程,,在此一一列出,,希望能給朋友一些借鑒 :)

  That's All :)

部分參考(排名部分先后):

1.http:///questions/148403/utf8-to-from-wide-char-conversion-in-stl 

2.http://www./doc/libs/1_48_0/libs/serialization/doc/codecvt.html 

3.http://www.cnblogs.com/hnrainll/archive/2011/05/07/2039700.html 

4.http://www./software/libiconv/ 

5.http://site./ 

6.http://blog.csdn.net/sjy88813/article/details/6662879 

7.http://www./questions/programming-9/wstring-utf8-conversion-in-pure-c-701084/ 

8.http://zh./wiki/UTF-8 

    本站是提供個(gè)人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,,不代表本站觀點(diǎn),。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,,謹(jǐn)防詐騙,。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊一鍵舉報(bào),。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多