提问人:Josh Hardman 提问时间:12/4/2020 更新时间:12/5/2020 访问量:158
为什么当我在 Android 设备上运行 cocos2dx 游戏时,使用 UTF-8 字符串的 ui::Text 组件的渲染受到限制?
Why is the rendering of ui::Text components which use UTF-8 strings being limited when I run my cocos2dx game on an android device?
问:
我正在cocos2dx游戏引擎上用C++开发游戏。我主要在 win32 平台上测试它,但最近在 android 上尝试了它。当我这样做时,我发现事情没有按预期运行。如果您想知道,我正在三星 Galaxy S8.0.0 上的 Android Oreo (7) 上运行 apk。
我注意到的第一件事是,一些在 win32 上渲染的组件没有在 android 上渲染。
我试图更好地理解为什么会这样,但经过几天的在线帮助板、源代码和教程的挖掘,我没有发现任何特别有希望的东西。
下面是一个问题的示例:
我有一个cocos2d::Scene,它有许多ui::Text组件,可以显示一些文本。如果初始化 ui::Text 组件时没有任何 UTF-8 字符,则它们似乎没有问题。
但是,如果它们使用 UTF-8 字符初始化,则有些会呈现,有些则不会。即使在使用 jni 调试器运行 adb 后,我也没有找到任何有用的错误消息,程序继续运行。
下面是一些示例代码:
using namespace cocos2d;
Scene* MainMenuScene::createScene()
{
return MainMenuScene::create();
}
bool MainMenuScene::init()
{
if ( !Scene::init() )
{
return false;
}
auto visibleSize = Director::getInstance()->getVisibleSize();
auto ichi = ui::Text::create(u8"一", "fonts/rounded-mgenplus-1c-black.ttf", 24);
auto ni = ui::Text::create(u8"二", "fonts/rounded-mgenplus-1c-black.ttf", 24);
auto san = ui::Text::create(u8"三", "fonts/rounded-mgenplus-1c-black.ttf", 24);
auto yon = ui::Text::create(u8"四", "fonts/rounded-mgenplus-1c-black.ttf", 24);
auto go = ui::Text::create(u8"五", "fonts/rounded-mgenplus-1c-black.ttf", 24);
auto roku = ui::Text::create(u8"六", "fonts/rounded-mgenplus-1c-black.ttf", 24);
auto nana = ui::Text::create(u8"七", "fonts/rounded-mgenplus-1c-black.ttf", 24);
auto hachi = ui::Text::create(u8"八", "fonts/rounded-mgenplus-1c-black.ttf", 24);
auto kyuu = ui::Text::create(u8"九", "fonts/rounded-mgenplus-1c-black.ttf", 24);
auto ichi_h = ui::Text::create(u8"いち", "fonts/rounded-mgenplus-1c-black.ttf", 24);
auto ni_h = ui::Text::create(u8"に", "fonts/rounded-mgenplus-1c-black.ttf", 24);
auto san_h = ui::Text::create(u8"さん", "fonts/rounded-mgenplus-1c-black.ttf", 24);
auto yon_h = ui::Text::create(u8"よん", "fonts/rounded-mgenplus-1c-black.ttf", 24);
auto go_h = ui::Text::create(u8"ご", "fonts/rounded-mgenplus-1c-black.ttf", 24);
auto roku_h = ui::Text::create(u8"ろく", "fonts/rounded-mgenplus-1c-black.ttf", 24);
auto nana_h = ui::Text::create(u8"なな", "fonts/rounded-mgenplus-1c-black.ttf", 24);
auto hachi_h = ui::Text::create(u8"はち", "fonts/rounded-mgenplus-1c-black.ttf", 24);
auto kyuu_h = ui::Text::create(u8"きゅう", "fonts/rounded-mgenplus-1c-black.ttf", 24);
auto ichi_k = ui::Text::create(u8"イチ", "fonts/rounded-mgenplus-1c-black.ttf", 24);
auto ni_k = ui::Text::create(u8"ニ", "fonts/rounded-mgenplus-1c-black.ttf", 24);
auto san_k = ui::Text::create(u8"サン", "fonts/rounded-mgenplus-1c-black.ttf", 24);
auto yon_k = ui::Text::create(u8"ヨン", "fonts/rounded-mgenplus-1c-black.ttf", 24);
auto go_k = ui::Text::create(u8"ゴ", "fonts/rounded-mgenplus-1c-black.ttf", 24);
auto roku_k = ui::Text::create(u8"ロク", "fonts/rounded-mgenplus-1c-black.ttf", 24);
auto nana_k = ui::Text::create(u8"ナナ", "fonts/rounded-mgenplus-1c-black.ttf", 24);
auto hachi_k = ui::Text::create(u8"ハチ", "fonts/rounded-mgenplus-1c-black.ttf", 24);
auto kyuu_k = ui::Text::create(u8"キュウ", "fonts/rounded-mgenplus-1c-black.ttf", 24);
auto layout = ui::Layout::create();
layout->setLayoutType(ui::Layout::Type::HORIZONTAL);
layout->setPosition(Vec2(0, visibleSize.height));
auto layout_kan = ui::Layout::create();
layout_kan->setLayoutType(ui::Layout::Type::VERTICAL);
layout_kan->setContentSize(Size(2 * kyuu_h->getContentSize().width, visibleSize.height));
auto layout_h = ui::Layout::create();
layout_h->setLayoutType(ui::Layout::Type::VERTICAL);
layout_h->setContentSize(Size(2 * kyuu_h->getContentSize().width, visibleSize.height));
auto layout_k = ui::Layout::create();
layout_k->setLayoutType(ui::Layout::Type::VERTICAL);
layout_k->setContentSize(Size(2 * kyuu_h->getContentSize().width, visibleSize.height));
layout_kan->addChild(ichi);
layout_kan->addChild(ni);
layout_kan->addChild(san);
layout_kan->addChild(yon);
layout_kan->addChild(go);
layout_kan->addChild(roku);
layout_kan->addChild(nana);
layout_kan->addChild(hachi);
layout_kan->addChild(kyuu);
layout_h->addChild(ichi_h);
layout_h->addChild(ni_h);
layout_h->addChild(san_h);
layout_h->addChild(yon_h);
layout_h->addChild(go_h);
layout_h->addChild(roku_h);
layout_h->addChild(nana_h);
layout_h->addChild(hachi_h);
layout_h->addChild(kyuu_h);
layout_k->addChild(ichi_k);
layout_k->addChild(ni_k);
layout_k->addChild(san_k);
layout_k->addChild(yon_k);
layout_k->addChild(go_k);
layout_k->addChild(roku_k);
layout_k->addChild(nana_k);
layout_k->addChild(hachi_k);
layout_k->addChild(kyuu_k);
layout->addChild(layout_kan);
layout->addChild(layout_h);
layout->addChild(layout_k);
this->addChild(layout);
return true;
}
下面是 win32 上的样子:
这是在 android 上的样子:
ui::Text 组件的实例化顺序似乎会影响渲染组件的数量,而渲染的优先级似乎取决于实例化的顺序。但是,偶尔会显示稍后实例化的 ui::Text,而之前实例化的 ui::Text 不会显示。
以下是我按以下顺序实例化相同的 ui::Text 组件时发生的情况:
auto ichi = ui::Text::create(u8"一", "fonts/rounded-mgenplus-1c-black.ttf", 24);
auto ni = ui::Text::create(u8"二", "fonts/rounded-mgenplus-1c-black.ttf", 24);
auto san = ui::Text::create(u8"三", "fonts/rounded-mgenplus-1c-black.ttf", 24);
auto yon = ui::Text::create(u8"四", "fonts/rounded-mgenplus-1c-black.ttf", 24);
auto go = ui::Text::create(u8"五", "fonts/rounded-mgenplus-1c-black.ttf", 24);
auto roku = ui::Text::create(u8"六", "fonts/rounded-mgenplus-1c-black.ttf", 24);
auto nana = ui::Text::create(u8"七", "fonts/rounded-mgenplus-1c-black.ttf", 24);
auto hachi = ui::Text::create(u8"八", "fonts/rounded-mgenplus-1c-black.ttf", 24);
auto kyuu = ui::Text::create(u8"九", "fonts/rounded-mgenplus-1c-black.ttf", 24);
auto ichi_k = ui::Text::create(u8"イチ", "fonts/rounded-mgenplus-1c-black.ttf", 24);
auto ni_k = ui::Text::create(u8"ニ", "fonts/rounded-mgenplus-1c-black.ttf", 24);
auto san_k = ui::Text::create(u8"サン", "fonts/rounded-mgenplus-1c-black.ttf", 24);
auto yon_k = ui::Text::create(u8"ヨン", "fonts/rounded-mgenplus-1c-black.ttf", 24);
auto go_k = ui::Text::create(u8"ゴ", "fonts/rounded-mgenplus-1c-black.ttf", 24);
auto roku_k = ui::Text::create(u8"ロク", "fonts/rounded-mgenplus-1c-black.ttf", 24);
auto nana_k = ui::Text::create(u8"ナナ", "fonts/rounded-mgenplus-1c-black.ttf", 24);
auto hachi_k = ui::Text::create(u8"ハチ", "fonts/rounded-mgenplus-1c-black.ttf", 24);
auto kyuu_k = ui::Text::create(u8"キュウ", "fonts/rounded-mgenplus-1c-black.ttf", 24);
auto ichi_h = ui::Text::create(u8"いち", "fonts/rounded-mgenplus-1c-black.ttf", 24);
auto ni_h = ui::Text::create(u8"に", "fonts/rounded-mgenplus-1c-black.ttf", 24);
auto san_h = ui::Text::create(u8"さん", "fonts/rounded-mgenplus-1c-black.ttf", 24);
auto yon_h = ui::Text::create(u8"よん", "fonts/rounded-mgenplus-1c-black.ttf", 24);
auto go_h = ui::Text::create(u8"ご", "fonts/rounded-mgenplus-1c-black.ttf", 24);
auto roku_h = ui::Text::create(u8"ろく", "fonts/rounded-mgenplus-1c-black.ttf", 24);
auto nana_h = ui::Text::create(u8"なな", "fonts/rounded-mgenplus-1c-black.ttf", 24);
auto hachi_h = ui::Text::create(u8"はち", "fonts/rounded-mgenplus-1c-black.ttf", 24);
auto kyuu_h = ui::Text::create(u8"きゅう", "fonts/rounded-mgenplus-1c-black.ttf", 24);
这是在 android 上的样子:
其他可能相关的信息:
- 增加其他 ui 组件的数量似乎会减少 呈现的 UTF-8 初始化 ui::Text 组件的数量。
- 呈现的 ui:Text 组件和未呈现的组件 对于一组代码块似乎保持一致。换言之, GUI 输出似乎不会随不同代码的不同而变化 运行。
- 不使用 UTF-8 字符串的 ui::text 组件似乎不是 受影响,并始终显示。
- 从字符串中删除 u8 前缀会得到相同的结果 android(缺少组件,但渲染的组件显示为 预期),并导致字符由 ???' 表示开启 win32的。
- 当我在 win32 上编译时,没有这样的问题,所有 ui::Text 无论使用哪个字符集,都会显示组件。
- 我专门使用日语字符(包括汉字、平假名 和片假名),但据推测这是所有 UTF-8 的问题 字符。
我想知道为什么会发生这种情况,以及我能做些什么来规避它而不诉诸黑客。
我将继续深入研究文档和源代码,以尝试更好地理解问题的根源,但我感觉这可能与 Android 受保护的内部结构有关。咳咳。
到目前为止,我一直在阅读 android 关于 JNI、NDK 和 OpenGL 的文档,并尽可能地浏览所有可能相关的 cocos2dx 和 android 类。我还通读了与字符串和语言环境相关的 C++ 编程部分,但似乎如果不绕过 cocos2dx 框架,我就无法做很多事情。
我想知道这个问题是否可能是由某些 JNI 限制或缓冲错误引起的。或者,这可能与版本控制或硬件有关。也许这与在调试模式下运行的应用程序有关?另外,我知道 Java 在内部使用 UTF-16 作为其字符串,所以我想这也可能在某个地方扔了一个扳手......
答:
这个问题似乎源于 Cocos2dx 游戏引擎中的几个错误。请参阅评论中发布的 Github 问题以获取修复。
评论