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

前言

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

探究问题

setOpacity


class CC_DLL ParticleSystemQuad : public ParticleSystem

class CC_DLL ParticleSystem : public Node, public TextureProtocol, public PlayableProtocol

我们首先查看了粒子的类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);
        }
    }
}
  • CCNode.h
virtual void updateColor() {}

首先我们找到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;
    }
}
  • 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);
        }
    }
}

我们在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
    {
       ......
    }
}
  • 新代码
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
    {
       ......
    }
}

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

推送

  • Github
https://github.com/KingSun5

结语

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

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值