粒子系统是非常方便使用的一个功能,有时候能节省大量的资源且保有很不错的效果,在使用cocos的粒子系统的时候发现一个问题,粒子只能通过参数内startColor和endColor来控制粒子开始到结束的透明度,通过设置粒子setOpacity或者父节点的透明度,粒子并不会有任何变化,透明没有变化
class CC_DLL ParticleSystemQuad : public ParticleSystem
class CC_DLL ParticleSystem : public Node, public TextureProtocol, public PlayableProtocol
我们首先查看了粒子的类CCParticleSystemQuad和其父类CCParticleSystem,我们发现都没有setOpacity,而CCParticleSystem方法是继承Node的,所以直接用的是Node的setOpacity方法
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);
}
}
}
virtual void updateColor() {}
首先我们找到setOpacity干了什么,通过代码我们发现setOpacity给_displayedOpacity设置了我们传入的值,然后调用了updateCascadeOpacity方法
在在updateCascadeOpacity方法内调用了updateColor方法内调用了updateColor方法,并且遍历执行了子节点的updateCascadeOpacity方法
updateColor方法是一个空的虚函数,用于子类被继承
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;
}
}
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的情况下,整体粒子透明度就会随当前节点或父节点的透明度变化而变化
https://github.com/KingSun5
若是觉得博主的文章写的不错,不妨关注一下博主,点赞一下博文,另博主能力有限,若文中有出现什么错误的地方,欢迎各位评论指摘。
QQ交流群:806091680(Chinar)
该群为CSDN博主Chinar所创,推荐一下!我也在群里!
本文属于原创文章,转载请著名作者出处并置顶!!