[solved] Inconsistent behavior for CCParticleSystemQuad between using texture atlas or simple texture

Hi I’ve noticed some problems when using CCParticleSystemQuad. If I’m adding the texture like this _frenzyTrail->setTexture(CCTextureCache::sharedTextureCache()->addImage("stars.png")); the particles shown on screen look the way they’re supposed to (first attached image). I’m using a 32x32, 24bit png image.

Then I’ve added that image to a texture atlas using TexturePacker. The atlas uses the same bit depth and the sprite looks the same. Now, when I set the texture like this _frenzyTrail->setTexture(frameCache->spriteFrameByName("stars.png")->getTexture()); or _frenzyTrail->setDisplayFrame(frameCache->spriteFrameByName("stars.png")); I get some strange particles, see second attached image.

I figured that something is wrong when I’ve tried some other thing, I’ve replaced the trees with the particle sprite from the atlas and the stars are displayed ok but the particles are not, see third attached image. Anyone encountered this before?


20111223222403.jpg (248.8 KB)


20111223222016.jpg (269.0 KB)


20111223223701.jpg (236.0 KB)

I’ve found the problem and the solution. The problem lies in file CCParticleSystemQuad.cpp in method CCParticleSystemQuad::setDisplayFrame that looks like this:

void CCParticleSystemQuad::setDisplayFrame(CCSpriteFrame *spriteFrame)
{
@ CCAssert( CCPoint::CCPointEqualToPoint( spriteFrame->getOffsetInPixels() , CCPointZero ), “QuadParticle only supports SpriteFrames with no offsets”);@

@ // update texture before updating texture rect@
@ if ( !m_pTexture || spriteFrame->getTexture()>getName != m_pTexture>getName())@
@ {@
@ this->setTexture(spriteFrame->getTexture());@
@ }@
}

the problem is that the texture coordinates are not computed properly, the whole atlas is taken in consideration. the solution is simple, replace setTexture with setTextureWithRect like this:

void CCParticleSystemQuad::setDisplayFrame(CCSpriteFrame *spriteFrame)
{
@ CCAssert( CCPoint::CCPointEqualToPoint( spriteFrame->getOffsetInPixels() , CCPointZero ), “QuadParticle only supports SpriteFrames with no offsets”);@

@ // update texture before updating texture rect@
@ if ( !m_pTexture || spriteFrame->getTexture()>getName != m_pTexture>getName())@
@ {@
@ this~~>setTextureWithRect, spriteFrame~~>getRect());@
@ }@
}

See attached picture for results.

The code of setTexture() is

void CCParticleSystemQuad::setTexture(CCTexture2D* texture)
{
    const CCSize& s = texture->getContentSize();
    this->setTextureWithRect(texture, CCRectMake(0, 0, s.width, s.height));
}

As you see, it invoke setTextureWithRect, the rect is ((0,0), (s.width, s.height)).
It seems that ((0,0), (s.width, s.height)) is different from spriteFrame->getRect().

BTW, cocos2d-iphone also use setTexture().