如何在 Cocos2dx 中为进度计时器的精灵添加标签?

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

本文关键字:计时器 精灵 添加 加标签 Cocos2dx      更新时间:2023-10-16

我正试图让一个ProgressTimer与一个小时候有LabelSprite一起工作。似乎只有Sprite,没有一个子项被用作进度条的精灵。

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

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

我已经简要地研究了使用 RenderTexture 来创建纹理并将其传递到精灵中并从那里开始工作,但除了看到更模糊的颠倒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 或自定义命令构建自己的精灵+标签进度计时器。标签基本上是精灵批处理中的一组精灵。不过,这将需要一些工作。

要使用 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 的问题在于,我相信它期望计划的更新运行,因此它实际上不会渲染任何内容,除非您在导演的渲染器上调用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);

纹理前精灵上的大多数方法(例如锚点和翻转锚点)似乎并不重要。位置确实如此。

请注意,如果您在调用 setPercent 一次后setSprite进度计时器,则需要将其设置为另一个值,然后再次设置,以便更新内部精灵/纹理。我认为这是一个错误,所以要小心。

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

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);

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