cocos2dx 4.0 3.x 标签 (Label) 中使用中文的方法与一些思考 (使用rapidjson)

cocos2dx 4.0 3.x 标签 (Label) 中使用中文的方法与一些思考 (使用rapidjson)

本文是基于cocos2dx 4.0环境 理论上旧版也能使用

0 前言

在cocos2dx中,如需要在 Label 读取中文,直接写进参数里面是不行的,直接不显示。但是官方文档却说

A TTFConfig can also be used for displaying Chinese, Japanese and Korean characters.
TTFConfig 也能用于展示中文,日文,韩文的字符。

网上搜索出来的做法大多都是使用 Dictionary 类的方法读取一个XML文件,这个方法在4.0之前也一直挺好用,直到我升级到4.0之后发现这个类找不到了。粗略的翻了一下,发现我之前用的3.17版本中,这个类已经在 deprecated 也就是弃用文件夹中了,看了下官方的手册,也没有说道如何读取,那就需要另辟蹊径了。

1 一些思考

本小节都是基于我个人的经验和猜测,可能有非常不严谨的地方,如果想看解决方法,直接看下一小节

通过搜索,在这篇文章中提到了将文件保存为utf8格式可以缓解,但是治标不治本,对字符的个数有限制,不然直接不能编译。此时我先想到了用visual code打开visual studio生成的文件,都需要把编码换成gbk。然后我又想到了以前开发qt程序在qt中使用vs编译器和mingw编译器时也有这类毛病。那么我就猜测,createWithTTF是可以使用中文的,只是万恶的编码问题导致c文件中的中文无法被正确编译。我还设想,如果不用visual studio进行开发,而是qt clion之类的,并且不使用vs编译器,会不会就能直接在参数给中文了呢?留给大家尝试了。

总结下来,createWithTTF是可以使用中文的,只是编码问题导致vs的cpp文件中不能使用,那么只需要用任何一种方式读取出字符串便可以了。

2 通过rapidjson

通过搜索,我发现cocos2dx的 external 文件夹中,官方为用户准备了很多非常实用的第三方库,其中就有可以用来读取json的rapidjson,网上一搜,发现在cocos中也有不少人在用,只不过好像没有提及用来读取中文标签。通过第一小节的猜测,我们可以借助它来实现中文标签。其原理就是读取json文件中的中文字符串。

当然,里面貌似也有解析xml的库,或者你想塞个库解析ini都是可以的,我使用rapidjson是感觉他很方便,而且如有用到,还能用于与服务器后端通信。

2-1 开始操作

我这里之作读取的用法,关于写入,请直接在网上搜索rapidjson,他是c语言的库,不限于cocos,任何地方都可以使用。

  1. 我们准备一个json文件 例如这样
{
    "key": "value",
    "array": [
        "1",
        "2"
    ],
    "HelloWorld": {
        "loading": "资源读取中...",
        "chinese": "中文字符串",
        "auth": "Curry"
    }
}
  1. 引入两个头文件#include "json/rapidjson.h" #include "json/document.h" 3.x版本没试过,如果不行试试在路径前面加上external/
  2. 通过cocos读取出文件的所有字符串 然后转换为rapidjson对象
rapidjson::Document JSON::mJsonObj;

//读取出所有字符串
std::string jsonStr = FileUtils::getInstance()->getStringFromFile("json/cn.json");
mJsonObj.Parse<rapidjson::kParseDefaultFlags>(jsonStr.c_str());
if (mJsonObj.HasParseError())
	//出错处理

//读值
if (mJsonObj.HasMember("键名"))
{
	//别的数据类型 int float 也是通过get***来读取
	std::string str = mJsonObj["键名"].GetString();
}

//读对象
if (mJsonObj.HasMember("对象键名"))
	if (mJsonObj["对象名"].IsObject())
	{
		rapidjson::Value subObject = mJsonObj["对象名"];
		//然后再从subObject中读取值即可
	}

//读数组
if (mJsonObj.HasMember("数组键名") && mJsonObj["数组键名"].IsArray()) 
{
	rapidjson::Value arr = mJsonObj["数组键名"];
	for (int i = 0; i < arr.Size(); ++i) 
	{
		rapidjson::Value tmpObj = arr[i];
		//然后再从tmpObj中读取值即可
	}
}
  1. 这样就完成了json的读取 GetString 直接返回了 const char* 放到 label 里就可以了
	auto lblTitle = Label::createWithTTF(mJsonObj["键名"].GetString(), "fonts/normal.ttf", 60);
	lblTitle->setTextColor(Color4B::BLACK);
	lblTitle->setPosition(Vec2(origin.x + visibleSize.width / 2, origin.x + visibleSize.height / 2 - 150));
	addChild(lblTitle, 1);

3 坑

我把这些写成了一个helper类,切换场景时直接通过同一个rapidjson::Document进行处理,发现只要取到了二级对象/数组之后最初的rapidjson::Document已经被改变,应该是指针的问题,可他没有深拷贝操作。所以,当你切换场景时,需要重新Parse一次!

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值