Cocos2d-X遊戲開發
-
文本
cocos2dx中有三個類可以添加文本信息:LabelTTF,LabelBMFont,LabelAtlas。
-
Cocos2d-x中文亂碼:
不能顯示中文
createWithTTF(title, "fonts/Arial.ttf", 24)
原因爲:字體不是中文字體
解決:將字體文件 simhei.ttf (黑體)拷貝到
資源文件夾的fonts文件夾中:
//讀取菜單數據
Dictionary *strings = Dictionary::createWithContentsOfFile("menu.xml");
constchar *title = ((String*)strings->objectForKey("title"))->getCString();
//添加一個文本
autolabel = Label::createWithTTF(title, "fonts/simhei.ttf", 24 * 2);
// 設定文本的位置
label->setPosition(Vec2(origin.x + visibleSize.width / 2,
origin.y + visibleSize.height - label->getContentSize().height));
// 添加文本到圖層
this->addChild(label, 1);
結果:
createWithSystemFont(title, "fonts/Arial.ttf", 24) 可以顯示中文
create(title, "Arial", 24) 可以顯示中文
解決這個問題常用的有三種方法:
-
通過轉換爲UTF-8編碼來顯示。
-
定義:
char *StartLayer::FontToUTF8(constchar* font) {
int len = MultiByteToWideChar(CP_ACP, 0, font, -1, NULL, 0);
wchar_t *wstr = newwchar_t[len + 1];
memset(wstr, 0, len + 1);
MultiByteToWideChar(CP_ACP, 0, font, -1, wstr, len);
len = WideCharToMultiByte(CP_UTF8, 0, wstr, -1, NULL, 0, NULL, NULL);
char *str = newchar[len + 1];
memset(str, 0, len + 1);
WideCharToMultiByte(CP_UTF8, 0, wstr, -1, str, len, NULL, NULL);
if (wstr)delete[] wstr;
return str;
}
-
使用:
LabelTTF *label = LabelTTF::create(StartLayer::FontToUTF8("新遊戲"), "Arial", 24 * 2);
這種方法僅僅依靠代碼實現而不不需要額外的設置,但是效果並不是很穩定,容易產生某些錯誤或者依然亂碼,因此不推薦該方法。
-
使用iconv庫來解決。
-
定義:
首先在創建好的cocos2d-x項目中搜索包含了iconv的文件名,然後把文件iconv.h的路徑引入:
#include"cocos2d\external\win32-specific\icon\include\iconv.h"
然後在項目中創建一個GBKToUTF8方法來實現編碼的轉換:
//編碼轉換,顯示中文
intStartLayer::GBKToUTF8(std::string &gbkStr, constchar* toCode, constchar* formCode) {
iconv_t iconvH;
iconvH = iconv_open(formCode, toCode);
if (iconvH == 0) {
return -1;
}
constchar* strChar = gbkStr.c_str();
constchar** pin = &strChar;
size_t strLength = gbkStr.length();
char *outbuf = (char*)malloc(strLength * 4);
char *pBuff = outbuf;
memset(outbuf, 0, strLength * 4);
size_t outLength = strLength * 4;
if (-1 == iconv(iconvH, pin, &strLength, &outbuf, &outLength)) {
iconv_close(iconvH);
return -1;
}
gbkStr= pBuff;
iconv_close(iconvH);
return 0;
}
-
使用:
std::string str = "新遊戲";
GBKToUTF8(str, "gb2312", "utf-8");
LabelTTF *label = LabelTTF::create(str.c_str(), "Arial", 24 * 2);
不過Android平臺上的Cocos2d-x並沒有提供相應的庫,這就需要開發者自行將iconv庫引入到項目中,然後編譯。
-
使用解析xml或者json文件來解決。
-
xml方法
<?xmlversion="1.0"encoding="utf-8"?>
<dict>
<key>menustart</key>
<string>新遊戲</string>
<key>menuclose</key>
<string>退出</string>
</dict>
在xml文件中,<key>和<string>兩個標籤要保持一一對應的關係。這樣就可以通過對key標籤中的內容索引到對應的中文內容,從而顯示中文字符。需要注意的是保存此xml文件的時候編碼格式要使用UTF-8。
//創建詞典類實例,將xml文件加載到詞典中
auto *chnStrings = Dictionary::createWithContentsOfFile("data.xml");
//通過xml文件中的key獲取value
constchar *str = ((String*)chnStrings->objectForKey("menustart"))->getCString();
//創建文本
LabelTTF *label = LabelTTF::create(str, "Arial", 24 * 2);
-
Json方法
-
同樣準備一個json文件,命名爲data.json:
{
"start":"開始遊戲",
"setting":"設置",
"exitGame":"退出遊戲",
"info":"迅騰偉業",
"restart":"重新開始",
"win":"遊戲勝利",
"returnMenu":"返回主菜單",
"bgMusic":"背景音樂",
"effectMusic":"音效音量"
}
-
引入頭文件:
#include"cocos-ext.h"
#include"json/document.h"
-
在頭文件中定義成員變量:
private:
rapidjson::Document _doc;
rapidjson::Value mDataArray;
void initJsonData(floatdt);
-
讀取JSON數據:
//讀取JSON
std::string filePath = FileUtils::getInstance()->fullPathForFilename("data.json");
std::string contentStr = FileUtils::getInstance()->getStringFromFile(filePath);
log("%s", contentStr.c_str());
//讀取數據到Document對象
_doc.Parse<0>(contentStr.c_str());
//讀取start節點值
std::string str = _doc["start"].GetString();
-
結果:
-
TTF類型標籤
LabelTTF類是通過TTF字體來實現的字體標籤。TTF格式是一種在計算機領域通用的字體格式,可以說是使用最爲廣泛的文字顯示格式。
//讀取數據
Dictionary *strings = Dictionary::createWithContentsOfFile("menu.xml");
constchar *title = ((String*)strings->objectForKey("title"))->getCString();
//添加一個文本
autolabel = LabelTTF::create(title, "fonts/simhei.ttf", 24 * 2);
// 設定文本的位置
label->setPosition(Vec2(origin.x + visibleSize.width / 2,
origin.y + visibleSize.height - label->getContentSize().height));
// 添加文本到圖層
this->addChild(label, 1);
LabelTTF類顯示靜態的標籤文本很方便,但是渲染速度相對較慢,並且缺乏靈活性。
-
BMFont標籤
LabelBMFont來自於圖片文件,所以其實它的作用就相當於精靈表單,而其中的每一個字符則相當於精靈表單中的單個精靈對象。
//讀取數據
Dictionary *strings = Dictionary::createWithContentsOfFile("menu.xml");
constchar *title = ((String*)strings->objectForKey("title"))->getCString();
autolabel = LabelBMFont::create(title, "test.fnt");
label->setPosition(Vec2(origin.x + visibleSize.width / 2,
origin.y + visibleSize.height - label->getContentSize().height));
//執行runAction動作,2秒後放大3倍
label->runAction(ScaleBy::create(2.0f, 3.0f));
this->addChild(label, 1);
LabelBMFont標籤提升了文字的繪製速度,所以,它是速度最快的字體類。
結果:
-
Altas標籤
LabelAtlas是使用圖片作爲文字的一種方式,該類通過plist配置文件的描述來定義。
//第一個參數:顯示的內容:1x,你也許會奇怪爲什麼是1x,因爲使用的png圖必須是連續的,
//因爲程序內部建議連續的scall碼識別的。9的後一位的":",所以要實現x就得用":"代替。
//第二個參數:圖片的名字
//第三個參數:每一個數字的寬 與實際圖片寬相符合
//第四個參數:每一個數字的高 與實際圖片高相符合
//每五個參數:開始字符 左右方向
//1:爲1x ==== 6爲6 ==== :爲x
LabelAtlas* label = LabelAtlas::create("1:", "nums_font.png", 14, 21, '0');
label->setPosition(Point(visibleSize.width / 2, visibleSize.height / 2));
this->addChild(label);
LabelAtlas* label = LabelAtlas::create("3", "num.png", 120, 122, '0');
label->setPosition(Point(visibleSize.width / 2, visibleSize.height / 2));
this->addChild(label);
結果: