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);
结果: