• 【cocos2dx】记录问题,粒子不会通过setOpacity调整整体透明度


    前言

    粒子系统是非常方便使用的一个功能,有时候能节省大量的资源且保有很不错的效果,在使用cocos的粒子系统的时候发现一个问题,粒子只能通过参数内startColor和endColor来控制粒子开始到结束的透明度,通过设置粒子setOpacity或者父节点的透明度,粒子并不会有任何变化,透明没有变化

    探究问题

    setOpacity

    
    class CC_DLL ParticleSystemQuad : public ParticleSystem
    
    class CC_DLL ParticleSystem : public Node, public TextureProtocol, public PlayableProtocol
    
    
    • 1
    • 2
    • 3
    • 4
    • 5

    我们首先查看了粒子的类CCParticleSystemQuad和其父类CCParticleSystem,我们发现都没有setOpacity,而CCParticleSystem方法是继承Node的,所以直接用的是Node的setOpacity方法

    • CCNode.cpp
    void Node::setOpacity(GLubyte opacity)
    {
        _displayedOpacity = _realOpacity = opacity;
        
        updateCascadeOpacity();
    }
    
    void Node::updateDisplayedOpacity(GLubyte parentOpacity)
    {
        _displayedOpacity = _realOpacity * parentOpacity/255.0;
        updateColor();
        
        if (_cascadeOpacityEnabled)
        {
            for(const auto& child : _children)
            {
                child->updateDisplayedOpacity(_displayedOpacity);
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • CCNode.h
    virtual void updateColor() {}
    
    • 1

    首先我们找到setOpacity干了什么,通过代码我们发现setOpacity给_displayedOpacity设置了我们传入的值,然后调用了updateCascadeOpacity方法
    在在updateCascadeOpacity方法内调用了updateColor方法内调用了updateColor方法,并且遍历执行了子节点的updateCascadeOpacity方法
    updateColor方法是一个空的虚函数,用于子类被继承

    updateColor

    • CCLayer
    void LayerColor::updateColor()
    {
        for( unsigned int i=0; i < 4; i++ )
        {
            _squareColors[i].r = _displayedColor.r / 255.0f;
            _squareColors[i].g = _displayedColor.g / 255.0f;
            _squareColors[i].b = _displayedColor.b / 255.0f;
            _squareColors[i].a = _displayedOpacity / 255.0f;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • CCLabel
    void Label::updateColor()
    {
        if (_batchNodes.empty())
        {
            return;
        }
    
        Color4B color4( _displayedColor.r, _displayedColor.g, _displayedColor.b, _displayedOpacity );
    
        // special opacity for premultiplied textures
        if (_isOpacityModifyRGB)
        {
            color4.r *= _displayedOpacity/255.0f;
            color4.g *= _displayedOpacity/255.0f;
            color4.b *= _displayedOpacity/255.0f;
        }
    
        cocos2d::TextureAtlas* textureAtlas;
        V3F_C4B_T2F_Quad *quads;
        for (auto&& batchNode:_batchNodes)
        {
            textureAtlas = batchNode->getTextureAtlas();
            quads = textureAtlas->getQuads();
            auto count = textureAtlas->getTotalQuads();
    
            for (int index = 0; index < count; ++index)
            {
                quads[index].bl.colors = color4;
                quads[index].br.colors = color4;
                quads[index].tl.colors = color4;
                quads[index].tr.colors = color4;
                textureAtlas->updateQuad(&quads[index], index);
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35

    我们在CCParticleSystemQuad和其父类CCParticleSystem内都没有发现对_displayedOpacity的运用或者重写的updateColor,所以我们找一些其他组件来参考一下别的怎么写的
    从其他参考后,大致能看出来了,在最终渲染前,_displayedOpacity会乘上四边形(quads)的四个colors(bl、br、tl、tr)

    解决方案

    在参考其他代码后,可以看出粒子之所以没有跟随自己节点或父节点的透明度变化,主要是因为_displayedOpacity参数没有再设置颜色的时候用上,所以解决方案就很容易了,在设置颜色的时候预乘上_displayedOpacity就好了

    • 旧代码
    void ParticleSystemQuad::updateParticleQuads()
    {
        ......   
        //set color
        if(_opacityModifyRGB)
        {
            ......
            for (int i = 0; i < _particleCount; ++i,++quad,++r,++g,++b,++a)
            {
                GLubyte colorR = *r * *a * 255;
                GLubyte colorG = *g * *a * 255;
                GLubyte colorB = *b * *a * 255;
                GLubyte colorA = *a * 255;
                quad->bl.colors.set(colorR, colorG, colorB, colorA);
                quad->br.colors.set(colorR, colorG, colorB, colorA);
                quad->tl.colors.set(colorR, colorG, colorB, colorA);
                quad->tr.colors.set(colorR, colorG, colorB, colorA);
            }
        }
        else
        {
           ......
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 新代码
    void ParticleSystemQuad::updateParticleQuads()
    {
        ......   
        //set color
        if(_opacityModifyRGB)
        {
            ......
            for (int i = 0; i < _particleCount; ++i,++quad,++r,++g,++b,++a)
            {
                GLubyte colorR = *r * *a * _displayedOpacity;
                GLubyte colorG = *g * *a * _displayedOpacity;
                GLubyte colorB = *b * *a * _displayedOpacity;
                GLubyte colorA = *a * _displayedOpacity;
                quad->bl.colors.set(colorR, colorG, colorB, colorA);
                quad->br.colors.set(colorR, colorG, colorB, colorA);
                quad->tl.colors.set(colorR, colorG, colorB, colorA);
                quad->tr.colors.set(colorR, colorG, colorB, colorA);
            }
        }
        else
        {
           ......
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    如此修改,在opacityModifyRGB被设置为true的情况下,整体粒子透明度就会随当前节点或父节点的透明度变化而变化

    推送

    • Github
    https://github.com/KingSun5
    
    • 1

    结语

    若是觉得博主的文章写的不错,不妨关注一下博主,点赞一下博文,另博主能力有限,若文中有出现什么错误的地方,欢迎各位评论指摘。
    QQ交流群:806091680(Chinar)
    该群为CSDN博主Chinar所创,推荐一下!我也在群里!
    本文属于原创文章,转载请著名作者出处并置顶!!

  • 相关阅读:
    理解Go语言中的GOPATH
    国际物流详解:国际物流有哪些特点?国际物流有哪些优势?
    Smartbi融入“多维建模”能力,满足一站式BI需求
    如何在代码层面提高CPU分支预测效率
    【C语言刷题——Leetcode12道题】带你起飞,飞进垃圾堆
    java毕业设计新闻稿件管理系统Mybatis+系统+数据库+调试部署
    Flutter Hero 实现共享元素转场动画
    [云原生1.]Docker数据管理与Cgroups资源控制管理
    Day9_9 Java学习之Dao层模式与JDBC事务
    2022牛客多校十 E-Reviewer Assignment(匈牙利算法)
  • 原文地址:https://blog.csdn.net/Mr_Sun88/article/details/126601108