cocos2d-x3.7 cclabel文字破碎,异常,变乱

cocos2d-x3.7 cclabel文字破碎,异常,变乱,第1张

概述效果图如下: 无论是按钮(control button),还是普通的label都有小概率出现这种情况。 该问题发现于cocos2d-x3.7 原因: 在3.x中使用ttfconfig创建的label,为了性能是创建了缓存的,字体纹理缓存的大小默认是512*512(不同版本大小可能不一样) //CCFontAtlas.cppconst int FontAtlas::CacheTextureWidt 效果图如下:



无论是按钮(control button),还是普通的label都有小概率出现这种情况。
该问题发现于cocos2d-x3.7

原因:

在3.x中使用ttfconfig创建的label,为了性能是创建了缓存的,字体纹理缓存的大小默认是512*512(不同版本大小可能不一样)

//CCFontAtlas.cppconst int FontAtlas::CacheTextureWIDth = 512;const int FontAtlas::CacheTextureHeight = 512;

v3.7的label继承于batchnode:class CC_DLL Label : public SpriteBatchNode,public LabelProtocol,且有一个存放batchnode数组的成员变量std::vector<SpriteBatchNode*> _batchNodes;,这个数组的第一个元素就是cclabel自己,当一张512*512大小的字体纹理缓存不够用时,会再创建一个,此时就是push_back到这个数组中。该batchnode数组会在绘制使用ttfconfig创建的字体时被使用。
那么,问题主要在于当改变字体大小,或者改变字体,都会调用函数voID Label::setFontAtlas(FontAtlas* atlas,bool distanceFIEldEnabled /* = false */,bool useA8Shader /* = false */),该函数会重置字体的纹理缓存:

voID Label::setFontAtlas(FontAtlas* atlas,bool distanceFIEldEnabled /* = false */,bool useA8Shader /* = false */){    if (atlas == _FontAtlas)    {        FontAtlasCache::releaseFontAtlas(atlas);        return;    }    if (_FontAtlas)    {        FontAtlasCache::releaseFontAtlas(_FontAtlas);        _FontAtlas = nullptr;    }    _FontAtlas = atlas;    if (_textureAtlas)    {        //这里重置了_batchNodes的第一个元素的问题,也就是cclabel自己,        //那么如果之前缓存了多个纹理,即_batchNodes.size>1,        //其他的纹理就还没有被释放!!!        _textureAtlas->setTexture(_FontAtlas->getTexture(0));    }    else    {        SpriteBatchNode::initWithTexture(_FontAtlas->getTexture(0),30);    } //...}

再来看一下_batchNodes添加新的缓存纹理相应的代码:

voID Label::alignText(){    if (_FontAtlas == nullptr || _currentUTF16String.empty())    {        setContentSize(Size::ZERO);        return;    }    _FontAtlas->prepareLetterDeFinitions(_currentUTF16String);    auto& textures = _FontAtlas->getTextures();    //如果上面旧的缓存一直没有释放,    //那么当新的字体纹理缓存创建第二个时,不会被更新!!!    //所以你看到的文字就是错乱的!    if (textures.size() > _batchNodes.size())    {        for (auto index = _batchNodes.size(); index < textures.size(); ++index)        {            auto batchNode = SpriteBatchNode::createWithTexture(textures.at(index));            batchNode->setAnchorPoint(Vec2::ANCHOR_top_left);            batchNode->setposition(Vec2::ZERO);            Node::addChild(batchNode,0,Node::INVALID_TAG);            _batchNodes.push_back(batchNode);        }    }    //.......}

根据上面的分析,其实可以发现,出现的这个BUG的概率是很小的:
1. 首先得用ttfconfig创建一个label,且显示过大量文字,导致创建了第二个缓存纹理
2. 然后更换字体,或者@R_117_6502@大小(setTTFSize)
3. 更改后的label显示过大量文字,导致创建第二个缓存纹理,如果显示了第二个纹理上的文字就会是错乱的。

解决方案:

因为更换字体、@R_117_6502@大小等,都会更换新的纹理(setFontAtlas),那么我们只用在该函数中重置_batchNodes即可:

voID Label::setFontAtlas(FontAtlas* atlas,bool useA8Shader /* = false */){    if (atlas == _FontAtlas)    {        FontAtlasCache::releaseFontAtlas(atlas);        return;    }    if (_FontAtlas)    {        FontAtlasCache::releaseFontAtlas(_FontAtlas);        _FontAtlas = nullptr;    }    _FontAtlas = atlas;    if (_textureAtlas)    {        _textureAtlas->setTexture(_FontAtlas->getTexture(0));    }    else    {        SpriteBatchNode::initWithTexture(_FontAtlas->getTexture(0),30);    }    //issue: text disorder    _batchNodes.clear();    _batchNodes.push_back(this);    //...}
v3.10

github上已经有3.10的代码,看了一下cclabel,已经重构了,label不再继承BatchNode

class CC_DLL Label : public Node,public LabelProtocol,public BlendProtocol

而每一个文字使用:class LabelLetter : public Sprite
看了一下setFontAtlas函数,上述的BUG已经不存在了

voID Label::setFontAtlas(FontAtlas* atlas,bool useA8Shader /* = false */){    if (atlas == _FontAtlas)    {        FontAtlasCache::releaseFontAtlas(atlas);        return;    }    if (_FontAtlas)    {        _batchNodes.clear();  //这里已经重置        FontAtlasCache::releaseFontAtlas(_FontAtlas);        _FontAtlas = nullptr;    }    _FontAtlas = atlas;    //.....}
总结

以上是内存溢出为你收集整理的cocos2d-x3.7 cclabel文字破碎异常变乱全部内容,希望文章能够帮你解决cocos2d-x3.7 cclabel文字破碎,异常,变乱所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/1076316.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-26
下一篇 2022-05-26

发表评论

登录后才能评论

评论列表(0条)

保存