如何在 Cocos2dx 中为 ProgressTimer 的 Sprite 添加标签?

How to add a Label to a ProgressTimer's Sprite in Cocos2dx?

我正在尝试让 ProgressTimerSprite 一起使用 Label 作为 child。好像只有 children 的 Sprite 和 none 被用作进度条的精灵。

我已经创建了标签,并将其添加到 sprite 中。我将精灵添加到 ProgressTimer 和场景中,因为我想确保它看起来不错。从场景中删除标签并仅将其提供给 ProgressTimer 似乎没有任何不同。

然后我使用 Sprite 创建 ProgressTimer,对其进行配置,然后将其添加到我的场景中。

我已经简要研究了使用 RenderTexture 创建纹理并将其传递到 Sprite 并从那里开始工作,但除了看到颠倒的模糊器之外没有任何进展 mysprite.png

如何让 Sprite 中的 Label 出现在我场景中的 ProgressTimer 中?

//init label
Label* lbl = Label::createWithTTF("My label", "fonts/Marker Felt.ttf", 24);
lbl->setTextColor(Color4B::RED);

//init sprite
Sprite* sprite = Sprite::create("mysprite.png");
sprite->addChild(lbl);

scene->addChild(sprite); //make sure it works normally

auto progress_timer = ProgressTimer::create(sprite);

progress_timer->setScale(1.5);
progress_timer->setPercentage(100);

scene->addChild(progress_timer);

最简单的解决方案是使用现有的 ProgressTimer,并在构建时嵌入您的标签(作为资产资源的一部分),或者如果您想动态更改标签,则使用 RenderTexture。

我见过一些游戏的标签和进度背景始终可见,并且进度条本身会填满。通常当它是一个健康栏或加载时,所以你可能想添加一个背景,这样当进度填满时标签看起来不会很奇怪。

您还可以考虑使用 ClippingNode 或自定义命令构建您自己的 sprite+label 进度计时器。标签基本上是 spritebatch 中的一组 sprite。不过这会有点工作。

要使用 RenderTexture,像这样:

Size size = sprite->getContentSize();

auto rt = RenderTexture::create(size.width, size.height, Texture2D::PixelFormat::RGBA8888);
rt->setAutoDraw(true);
rt->addChild(sprite);
rt->addChild(label);
auto rtSprite = Sprite::createWithTexture(rt->getSprite()->getTexture());
ProgressTimer* progress = ProgressTimer::create(rtSprite);

感谢@SteveTranby 的解决方案,我找到了一个适合我的解决方案。设置 AutoDraw 的问题是我相信它期望计划更新到 运行,所以它实际上不会渲染任何东西,除非你在 director 的渲染器上调用 render,所以我求助于手动绘制到精灵。

我也有失真问题,所以我禁用了抗锯齿并确保我根本没有进行任何缩放。我将锚点设置为 1,1,因为默认值 0,0 会截掉一半图像,然后我还必须翻转图像。我不知道为什么。

//sprite for base layer
auto prog_sprite = Sprite::create("progbar.png");
auto fmt = prog_sprite->getTexture()->getPixelFormat();
auto size = prog_sprite->getContentSize();

auto lbl = Label::createWithTTF("label text", "fontpath, size.height);
lbl->setTextColor(Color4B::RED);

//sprite for label
auto lbl_sprt = Sprite::create();
lbl_sprt->addChild(lbl);
rt = RenderTexture::create(size.width, size.height, fmt);

rt->begin();
//draw base sprite to texture
prog_sprite->getTexture()->setAliasTexParameters();
prog_sprite->setAnchorPoint(Vec2(1, 1));
prog_sprite->setPosition(size.width, size.height);
prog_sprite->visit();

//draw label sprite to texture
lbl_sprt->setAnchorPoint(Vec2(1, 1));
lbl_sprt->setPosition(10, 10);
lbl_sprt->visit();
rt->end();

//create a sprite from the new texture
Texture2D* text2d = rt->getSprite()->getTexture();
text2d->setAliasTexParameters();
auto final_sprite = Sprite::createWithTexture(text2d);
final_sprite->setFlippedY(true);

//create the final progresstimer
this->prog_timer = ProgressTimer::create(final_sprite);

纹理之前精灵上的大多数方法,例如锚点和翻转,似乎都无关紧要。位置确实如此。

请注意,如果您在调用 setPercentage 一次后 setSprite ProgressTimer,则需要将其设置为另一个值,然后再返回,以便内部 sprite/texture 得到更新。我认为这是一个错误,所以要小心。

我最近重新解决了这个问题,并找到了一个实际的解决方案。事实证明,@SteveTranby 一开始不使用 renderTexture 是正确的。

auto lbl = Label::createWithTTF("label string", my_font_name, 25);
lbl->setAnchorPoint(Vec2(0.5f, 0.5f));
auto front_size = my_progress_timer->getContentSize();
lbl->setPosition(Vec2(
    front_size.width/2.0f,
    front_size.height/2.0f
));
lbl->setTextColor(Color4B::BLACK);
my_progress_timer->addChild(lbl);

足以做我想做的事。我不确定为什么这以前不起作用。