cocos2dx粒子效果的一个有趣的bug
2014-07-23 22:16
211 查看
废话不多说,直入主题。
运行如下代码,效果如下图。
auto ptc = ParticleSun::create();
auto act = Sequence::create(DelayTime::create(2), MoveBy::create(0.1, Vec2(50, 50)), NULL);
ptc->runAction(Repeat::create(act,5));
scene->addChild(ptc);
这是正常情况下的表现,当我们将当前场景放大之后,效果如下
auto ptc = ParticleSun::create();
auto act = Sequence::create(DelayTime::create(2), MoveBy::create(0.1, Vec2(50, 50)), NULL);
ptc->runAction(Repeat::create(act,5));
scene->addChild(ptc);
scene->setScale(1.4f);
粒子的拖尾是喷射出来的,像发射火箭一样。
为什么放大后会出现这样的情况呢?
观察ParticleSystem的update
只要将
if (_positionType == PositionType::FREE || _positionType == PositionType::RELATIVE)
{
Vec2 diff = currentPosition - p->startPos;
newPos = p->pos - diff;
}
else
{
newPos = p->pos;
}
改成
if (_positionType == PositionType::FREE)
{
Vec2 diff = convertToNodeSpace(currentPosition) - convertToNodeSpace(p->startPos);
newPos = p->pos - diff;
}
else if(_positionType == PositionType::RELATIVE)
{
Vec2 diff = currentPosition - p->startPos;
newPos = p->pos - diff;
}
else
{
newPos = p->pos;
}
即可解决这个问题
运行如下代码,效果如下图。
auto ptc = ParticleSun::create();
auto act = Sequence::create(DelayTime::create(2), MoveBy::create(0.1, Vec2(50, 50)), NULL);
ptc->runAction(Repeat::create(act,5));
scene->addChild(ptc);
这是正常情况下的表现,当我们将当前场景放大之后,效果如下
auto ptc = ParticleSun::create();
auto act = Sequence::create(DelayTime::create(2), MoveBy::create(0.1, Vec2(50, 50)), NULL);
ptc->runAction(Repeat::create(act,5));
scene->addChild(ptc);
scene->setScale(1.4f);
粒子的拖尾是喷射出来的,像发射火箭一样。
为什么放大后会出现这样的情况呢?
观察ParticleSystem的update
<pre name="code" class="cpp">// ParticleSystem - MainLoop void ParticleSystem::update(float dt) { CC_PROFILER_START_CATEGORY(kProfilerCategoryParticles , "CCParticleSystem - update"); if (_isActive && _emissionRate) { float rate = 1.0f / _emissionRate; //issue #1201, prevent bursts of particles, due to too high emitCounter if (_particleCount < _totalParticles) { _emitCounter += dt; } while (_particleCount < _totalParticles && _emitCounter > rate) { this->addParticle(); _emitCounter -= rate; } _elapsed += dt; if (_duration != -1 && _duration < _elapsed) { this->stopSystem(); } } _particleIdx = 0; Vec2 currentPosition = Vec2::ZERO; if (_positionType == PositionType::FREE) //默认情况下的PositionType是FREE模式 { currentPosition = this->convertToWorldSpace(Vec2::ZERO);//currentPosition保存的是屏幕坐标系的粒子坐标 } else if (_positionType == PositionType::RELATIVE) { currentPosition = _position; } { while (_particleIdx < _particleCount) { tParticle *p = &_particles[_particleIdx]; // life p->timeToLive -= dt; if (p->timeToLive > 0) { // Mode A: gravity, direction, tangential accel & radial accel if (_emitterMode == Mode::GRAVITY) { Vec2 tmp, radial, tangential; radial = Vec2::ZERO; // radial acceleration if (p->pos.x || p->pos.y) { radial = p->pos.getNormalized(); } tangential = radial; radial = radial * p->modeA.radialAccel; // tangential acceleration float newy = tangential.x; tangential.x = -tangential.y; tangential.y = newy; tangential = tangential * p->modeA.tangentialAccel; // (gravity + radial + tangential) * dt tmp = radial + tangential + modeA.gravity; tmp = tmp * dt; p->modeA.dir = p->modeA.dir + tmp; // this is cocos2d-x v3.0 // if (_configName.length()>0 && _yCoordFlipped != -1) // this is cocos2d-x v3.0 tmp = p->modeA.dir * dt * _yCoordFlipped; p->pos = p->pos + tmp; } // Mode B: radius movement else { // Update the angle and radius of the particle. p->modeB.angle += p->modeB.degreesPerSecond * dt; p->modeB.radius += p->modeB.deltaRadius * dt; p->pos.x = - cosf(p->modeB.angle) * p->modeB.radius; p->pos.y = - sinf(p->modeB.angle) * p->modeB.radius; p->pos.y *= _yCoordFlipped; } // color p->color.r += (p->deltaColor.r * dt); p->color.g += (p->deltaColor.g * dt); p->color.b += (p->deltaColor.b * dt); p->color.a += (p->deltaColor.a * dt); // size p->size += (p->deltaSize * dt); p->size = MAX( 0, p->size ); // angle p->rotation += (p->deltaRotation * dt); // // update values in quad // Vec2 newPos; if (_positionType == PositionType::FREE || _positionType == PositionType::RELATIVE) { Vec2 diff = currentPosition - p->startPos; //问题的关键在这里,场景放大后,以屏幕坐标系计算得出的diff实际上也被放大了,所以newPos是错误的 newPos = p->pos - diff; } else { newPos = p->pos; } // translate newPos to correct position, since matrix transform isn't performed in batchnode // don't update the particle with the new position information, it will interfere with the radius and tangential calculations if (_batchNode) { newPos.x+=_position.x; newPos.y+=_position.y; } updateQuadWithParticle(p, newPos); //updateParticleImp(self, updateParticleSel, p, newPos); // update particle counter ++_particleIdx; } else { // life < 0 int currentIndex = p->atlasIndex; if( _particleIdx != _particleCount-1 ) { _particles[_particleIdx] = _particles[_particleCount-1]; } if (_batchNode) { //disable the switched particle _batchNode->disableParticle(_atlasIndex+currentIndex); //switch indexes _particles[_particleCount-1].atlasIndex = currentIndex; } --_particleCount; if( _particleCount == 0 && _isAutoRemoveOnFinish ) { this->unscheduleUpdate(); _parent->removeChild(this, true); return; } } } //while _transformSystemDirty = false; } // only update gl buffer when visible if (_visible && ! _batchNode) { postStep(); } CC_PROFILER_STOP_CATEGORY(kProfilerCategoryParticles , "CCParticleSystem - update"); }
只要将
if (_positionType == PositionType::FREE || _positionType == PositionType::RELATIVE)
{
Vec2 diff = currentPosition - p->startPos;
newPos = p->pos - diff;
}
else
{
newPos = p->pos;
}
改成
if (_positionType == PositionType::FREE)
{
Vec2 diff = convertToNodeSpace(currentPosition) - convertToNodeSpace(p->startPos);
newPos = p->pos - diff;
}
else if(_positionType == PositionType::RELATIVE)
{
Vec2 diff = currentPosition - p->startPos;
newPos = p->pos - diff;
}
else
{
newPos = p->pos;
}
即可解决这个问题
相关文章推荐
- HttpCompressionModule 6的一个Bug及使用效果
- 播客:IE7的一个有趣的BUG
- 在Ext(Version2.2 和目前的Version3.1.1 Version3.2) 里面存在一个BUG,就是当设置了 stripeRows:true, 并没有出现斑马线的效果,解决的办法是在定义一个css类,放置在一个独立的css文件里面,页面加以引用。
- 面试碰到的一个粒子效果问题
- 一个有趣的现象(苹果的bug Or 坑?),关于区分真机和模拟器的预编译宏
- 关于DropDownList的一个有趣的Bug~
- cocos2dx C++ 粒子效果使用
- android上使用cocos2dx的一个bug
- 处理2D图像和纹理——创建一个3D爆炸效果,简单的粒子系统
- 一个有趣的Bug修正记
- Android 分享一个简单有趣的动画效果
- C++标准库的一个有趣的小bug
- C++标准库的一个有趣的小bug
- C++标准库的一个有趣的小bug
- 探讨C#.NET下DropDownList的一个有趣的bug及其解决办法
- DropDownList的一个有趣的Bug~
- C++标准库的一个有趣的小bug
- 一个有趣的和时钟相关的bug
- cocos2dx粒子效果出现黑块 解决办法
- cocos2dx 2.x版本在android下CCLabelTTF的一个bug