code:
#include "ParticleTest.h"
// #include "CCActionInterval.h"
// #include "CCMenu.h"
// #include "CCLabelTTF.h"
// #include "CCLabelAtlas.h"
// #include "touch_dispatcher/CCTouchDispatcher.h"
#include "../testResource.h"
/*#include "support/CCPointExtension.h"*/

enum
{
	kTagLabelAtlas = 1,
};

CCLayer* nextParticleAction();
CCLayer* backParticleAction();
CCLayer* restartParticleAction();

//------------------------------------------------------------------
//
// DemoFirework
//
//------------------------------------------------------------------
void DemoFirework::onEnter()
{
	ParticleDemo::onEnter();

	m_emitter = CCParticleFireworks::node();
    m_emitter->retain();
	m_background->addChild(m_emitter, 10);

    m_emitter->setTexture( CCTextureCache::sharedTextureCache()->addImage(s_stars1) );

	setEmitterPosition();
}

std::string DemoFirework::title()
{
	return "ParticleFireworks";
}

//------------------------------------------------------------------
//
// DemoFire
//
//------------------------------------------------------------------
void DemoFire::onEnter()
{
	ParticleDemo::onEnter();

	m_emitter = CCParticleFire::node();
    m_emitter->retain();
	m_background->addChild(m_emitter, 10);

	m_emitter->setTexture( CCTextureCache::sharedTextureCache()->addImage(s_fire) );//.pvr"];
	CCPoint p = m_emitter->getPosition();
	m_emitter->setPosition( CCPointMake(p.x, 100) );

	setEmitterPosition();
}

std::string DemoFire::title()
{
	return "ParticleFire";
}

//------------------------------------------------------------------
//
// DemoSun
//
//------------------------------------------------------------------
void DemoSun::onEnter()
{
	ParticleDemo::onEnter();

	m_emitter = CCParticleSun::node();
    m_emitter->retain();
	m_background->addChild(m_emitter, 10);

	m_emitter->setTexture( CCTextureCache::sharedTextureCache()->addImage(s_fire) );

	setEmitterPosition();
}

std::string DemoSun::title()
{
	return "ParticleSun";
}

//------------------------------------------------------------------
//
// DemoGalaxy
//
//------------------------------------------------------------------
void DemoGalaxy::onEnter()
{
	ParticleDemo::onEnter();

	m_emitter = CCParticleGalaxy::node();
    m_emitter->retain();
	m_background->addChild(m_emitter, 10);

    m_emitter->setTexture( CCTextureCache::sharedTextureCache()->addImage(s_fire) );

	setEmitterPosition();
}

std::string DemoGalaxy::title()
{
	return "ParticleGalaxy";
}

//------------------------------------------------------------------
//
// DemoFlower
//
//------------------------------------------------------------------
void DemoFlower::onEnter()
{
	ParticleDemo::onEnter();

	m_emitter = CCParticleFlower::node();
    m_emitter->retain();
	m_background->addChild(m_emitter, 10);
    m_emitter->setTexture( CCTextureCache::sharedTextureCache()->addImage(s_stars1) );

	setEmitterPosition();
}

std::string DemoFlower::title()
{
	return "ParticleFlower";
}

//------------------------------------------------------------------
//
// DemoBigFlower
//
//------------------------------------------------------------------
void DemoBigFlower::onEnter()
{
	ParticleDemo::onEnter();

	m_emitter = new CCParticleSystemQuad();
	m_emitter->initWithTotalParticles(50);
	//m_emitter->autorelease();

	m_background->addChild(m_emitter, 10);
	////m_emitter->release();	// win32 :  use this line or remove this line and use autorelease()
    m_emitter->setTexture( CCTextureCache::sharedTextureCache()->addImage(s_stars1) );

	m_emitter->setDuration(-1);

	// gravity
	m_emitter->setGravity(CCPointZero);

	// angle
	m_emitter->setAngle(90);
	m_emitter->setAngleVar(360);

	// speed of particles
	m_emitter->setSpeed(160);
	m_emitter->setSpeedVar(20);

	// radial
	m_emitter->setRadialAccel(-120);
	m_emitter->setRadialAccelVar(0);

	// tagential
	m_emitter->setTangentialAccel(30);
	m_emitter->setTangentialAccelVar(0);

	// emitter position
	m_emitter->setPosition( CCPointMake(160,240) );
	m_emitter->setPosVar(CCPointZero);

	// life of particles
	m_emitter->setLife(4);
	m_emitter->setLifeVar(1);

	// spin of particles
	m_emitter->setStartSpin(0);
	m_emitter->setStartSizeVar(0);
	m_emitter->setEndSpin(0);
	m_emitter->setEndSpinVar(0);

	// color of particles
	ccColor4F startColor = {0.5f, 0.5f, 0.5f, 1.0f};
	m_emitter->setStartColor(startColor);

	ccColor4F startColorVar = {0.5f, 0.5f, 0.5f, 1.0f};
	m_emitter->setStartColorVar(startColorVar);

	ccColor4F endColor = {0.1f, 0.1f, 0.1f, 0.2f};
	m_emitter->setEndColor(endColor);

	ccColor4F endColorVar = {0.1f, 0.1f, 0.1f, 0.2f};
	m_emitter->setEndColorVar(endColorVar);

	// size, in pixels
	m_emitter->setStartSize(80.0f);
	m_emitter->setStartSizeVar(40.0f);
	m_emitter->setEndSize(kParticleStartSizeEqualToEndSize);

	// emits per second
	m_emitter->setEmissionRate(m_emitter->getTotalParticles()/m_emitter->getLife());

	// additive
	m_emitter->setIsBlendAdditive(true);

	setEmitterPosition();
}

std::string DemoBigFlower::title()
{
	return "ParticleBigFlower";
}

//------------------------------------------------------------------
//
// DemoRotFlower
//
//------------------------------------------------------------------
void DemoRotFlower::onEnter()
{
	ParticleDemo::onEnter();

	m_emitter = new CCParticleSystemQuad();
	m_emitter->initWithTotalParticles(300);
	//m_emitter->autorelease();

	m_background->addChild(m_emitter, 10);
	////m_emitter->release();	// win32 : Remove this line
	m_emitter->setTexture( CCTextureCache::sharedTextureCache()->addImage(s_stars2) );

	// duration
	m_emitter->setDuration(-1);

	// gravity
	m_emitter->setGravity(CCPointZero);

	// angle
	m_emitter->setAngle(90);
	m_emitter->setAngleVar(360);

	// speed of particles
	m_emitter->setSpeed(160);
	m_emitter->setSpeedVar(20);

	// radial
	m_emitter->setRadialAccel(-120);
	m_emitter->setRadialAccelVar(0);

	// tagential
	m_emitter->setTangentialAccel(30);
	m_emitter->setTangentialAccelVar(0);

	// emitter position
	m_emitter->setPosition( CCPointMake(160,240) );
	m_emitter->setPosVar(CCPointZero);

	// life of particles
	m_emitter->setLife(3);
	m_emitter->setLifeVar(1);

	// spin of particles
	m_emitter->setStartSpin(0);
	m_emitter->setStartSpinVar(0);
	m_emitter->setEndSpin(0);
	m_emitter->setEndSpinVar(2000);

	// color of particles
	ccColor4F startColor = {0.5f, 0.5f, 0.5f, 1.0f};
	m_emitter->setStartColor(startColor);

	ccColor4F startColorVar = {0.5f, 0.5f, 0.5f, 1.0f};
	m_emitter->setStartColorVar(startColorVar);

	ccColor4F endColor = {0.1f, 0.1f, 0.1f, 0.2f};
	m_emitter->setEndColor(endColor);

	ccColor4F endColorVar = {0.1f, 0.1f, 0.1f, 0.2f};
	m_emitter->setEndColorVar(endColorVar);

	// size, in pixels
	m_emitter->setStartSize(30.0f);
	m_emitter->setStartSizeVar(00.0f);
	m_emitter->setEndSize(kParticleStartSizeEqualToEndSize);

	// emits per second
	m_emitter->setEmissionRate(m_emitter->getTotalParticles()/m_emitter->getLife());

	// additive
	m_emitter->setIsBlendAdditive(false);

	setEmitterPosition();
}

std::string DemoRotFlower::title()
{
	return "ParticleRotFlower";
}

//------------------------------------------------------------------
//
// DemoMeteor
//
//------------------------------------------------------------------
void DemoMeteor::onEnter()
{
	ParticleDemo::onEnter();

	m_emitter = CCParticleMeteor::node();
    m_emitter->retain();
	m_background->addChild(m_emitter, 10);

	m_emitter->setTexture( CCTextureCache::sharedTextureCache()->addImage(s_fire) );

	setEmitterPosition();
}

std::string DemoMeteor::title()
{
	return "ParticleMeteor";
}

//------------------------------------------------------------------
//
// DemoSpiral
//
//------------------------------------------------------------------
void DemoSpiral::onEnter()
{
	ParticleDemo::onEnter();

	m_emitter = CCParticleSpiral::node();
    m_emitter->retain();
	m_background->addChild(m_emitter, 10);

	m_emitter->setTexture( CCTextureCache::sharedTextureCache()->addImage(s_fire) );

	setEmitterPosition();
}

std::string DemoSpiral::title()
{
	return "ParticleSpiral";
}

//------------------------------------------------------------------
//
// DemoExplosion
//
//------------------------------------------------------------------
void DemoExplosion::onEnter()
{
	ParticleDemo::onEnter();

	m_emitter = CCParticleExplosion::node();
    m_emitter->retain();
	m_background->addChild(m_emitter, 10);

	m_emitter->setTexture( CCTextureCache::sharedTextureCache()->addImage(s_stars1) );

	m_emitter->setIsAutoRemoveOnFinish(true);

	setEmitterPosition();
}

std::string DemoExplosion::title()
{
	return "ParticleExplosion";
}

//------------------------------------------------------------------
//
// DemoSmoke
//
//------------------------------------------------------------------
void DemoSmoke::onEnter()
{
	ParticleDemo::onEnter();

	m_emitter = CCParticleSmoke::node();
    m_emitter->retain();
	m_background->addChild(m_emitter, 10);
    m_emitter->setTexture( CCTextureCache::sharedTextureCache()->addImage(s_fire) );

	CCPoint p = m_emitter->getPosition();
	m_emitter->setPosition( CCPointMake( p.x, 100) );

	setEmitterPosition();
}

std::string DemoSmoke::title()
{
	return "ParticleSmoke";
}

//------------------------------------------------------------------
//
// DemoSnow
//
//------------------------------------------------------------------
void DemoSnow::onEnter()
{
	ParticleDemo::onEnter();

	m_emitter = CCParticleSnow::node();
    m_emitter->retain();
	m_background->addChild(m_emitter, 10);

	CCPoint p = m_emitter->getPosition();
	m_emitter->setPosition( CCPointMake( p.x, p.y-110) );
	m_emitter->setLife(3);
	m_emitter->setLifeVar(1);

	// gravity
	m_emitter->setGravity(CCPointMake(0,-10));

	// speed of particles
	m_emitter->setSpeed(130);
	m_emitter->setSpeedVar(30);

	ccColor4F startColor = m_emitter->getStartColor();
	startColor.r = 0.9f;
	startColor.g = 0.9f;
	startColor.b = 0.9f;
	m_emitter->setStartColor(startColor);

	ccColor4F startColorVar = m_emitter->getStartColorVar();
	startColorVar.b = 0.1f;
	m_emitter->setStartColorVar(startColorVar);

	m_emitter->setEmissionRate(m_emitter->getTotalParticles()/m_emitter->getLife());

	m_emitter->setTexture( CCTextureCache::sharedTextureCache()->addImage(s_snow) );

	setEmitterPosition();
}

std::string DemoSnow::title()
{
	return "ParticleSnow";
}

//------------------------------------------------------------------
//
// DemoRain
//
//------------------------------------------------------------------
void DemoRain::onEnter()
{
	ParticleDemo::onEnter();

	m_emitter = CCParticleRain::node();
    m_emitter->retain();
	m_background->addChild(m_emitter, 10);

	CCPoint p = m_emitter->getPosition();
	m_emitter->setPosition( CCPointMake( p.x, p.y-100) );
	m_emitter->setLife(4);

	m_emitter->setTexture( CCTextureCache::sharedTextureCache()->addImage(s_fire) );

	setEmitterPosition();
}

std::string DemoRain::title()
{
	return "ParticleRain";
}

//------------------------------------------------------------------
//
// DemoModernArt
//
//------------------------------------------------------------------
void DemoModernArt::onEnter()
{
	ParticleDemo::onEnter();

//FIXME: If use CCParticleSystemPoint, bada 1.0 device will crash.
//  Crash place: CCParticleSystemPoint.cpp Line 149, function: glDrawArrays(GL_POINTS, 0, m_uParticleIdx);
//  m_emitter = new CCParticleSystemPoint();
    m_emitter = new CCParticleSystemQuad();
	m_emitter->initWithTotalParticles(1000);
	//m_emitter->autorelease();

	m_background->addChild(m_emitter, 10);
	////m_emitter->release();

	CCSize s = CCDirector::sharedDirector()->getWinSize();

	// duration
	m_emitter->setDuration(-1);

	// gravity
	m_emitter->setGravity(CCPointMake(0,0));

	// angle
	m_emitter->setAngle(0);
	m_emitter->setAngleVar(360);

	// radial
	m_emitter->setRadialAccel(70);
	m_emitter->setRadialAccelVar(10);

	// tagential
	m_emitter->setTangentialAccel(80);
	m_emitter->setTangentialAccelVar(0);

	// speed of particles
	m_emitter->setSpeed(50);
	m_emitter->setSpeedVar(10);

	// emitter position
	m_emitter->setPosition( CCPointMake( s.width/2, s.height/2) );
	m_emitter->setPosVar(CCPointZero);

	// life of particles
	m_emitter->setLife(2.0f);
	m_emitter->setLifeVar(0.3f);

	// emits per frame
	m_emitter->setEmissionRate(m_emitter->getTotalParticles()/m_emitter->getLife());

	// color of particles
	ccColor4F startColor = {0.5f, 0.5f, 0.5f, 1.0f};
	m_emitter->setStartColor(startColor);

	ccColor4F startColorVar = {0.5f, 0.5f, 0.5f, 1.0f};
	m_emitter->setStartColorVar(startColorVar);

	ccColor4F endColor = {0.1f, 0.1f, 0.1f, 0.2f};
	m_emitter->setEndColor(endColor);

	ccColor4F endColorVar = {0.1f, 0.1f, 0.1f, 0.2f};
	m_emitter->setEndColorVar(endColorVar);

	// size, in pixels
	m_emitter->setStartSize(1.0f);
	m_emitter->setStartSizeVar(1.0f);
	m_emitter->setEndSize(32.0f);
	m_emitter->setEndSizeVar(8.0f);

	// texture
	m_emitter->setTexture( CCTextureCache::sharedTextureCache()->addImage(s_fire) );

	// additive
	m_emitter->setIsBlendAdditive(false);

	setEmitterPosition();
}

std::string DemoModernArt::title()
{
	return "Varying size";
}

//------------------------------------------------------------------
//
// DemoRing
//
//------------------------------------------------------------------
void DemoRing::onEnter()
{
	ParticleDemo::onEnter();

	m_emitter = CCParticleFlower::node();
    m_emitter->retain();

	m_background->addChild(m_emitter, 10);

	m_emitter->setTexture( CCTextureCache::sharedTextureCache()->addImage(s_stars1) );
	m_emitter->setLifeVar(0);
	m_emitter->setLife(10);
	m_emitter->setSpeed(100);
	m_emitter->setSpeedVar(0);
	m_emitter->setEmissionRate(10000);

	setEmitterPosition();
}

std::string DemoRing::title()
{
	return "Ring Demo";
}

//------------------------------------------------------------------
//
// ParallaxParticle
//
//------------------------------------------------------------------
void ParallaxParticle::onEnter()
{
	ParticleDemo::onEnter();

	m_background->getParent()->removeChild(m_background, true);
    m_background = NULL;

	CCParallaxNode* p = CCParallaxNode::node();
	addChild(p, 5);

	CCSprite *p1 = CCSprite::spriteWithFile(s_back3);
	CCSprite *p2 = CCSprite::spriteWithFile(s_back3);

	p->addChild( p1, 1, CCPointMake(0.5f,1), CCPointMake(0,250) );
	p->addChild(p2, 2, CCPointMake(1.5f,1), CCPointMake(0,50) );

	m_emitter = CCParticleFlower::node();
    m_emitter->retain();
    m_emitter->setTexture( CCTextureCache::sharedTextureCache()->addImage(s_fire) );

	p1->addChild(m_emitter, 10);
	m_emitter->setPosition( CCPointMake(250,200) );

	CCParticleSun* par = CCParticleSun::node();
	p2->addChild(par, 10);
    par->setTexture( CCTextureCache::sharedTextureCache()->addImage(s_fire) );

	CCActionInterval* move = CCMoveBy::actionWithDuration(4, CCPointMake(300,0));
	CCActionInterval* move_back = move->reverse();
	CCFiniteTimeAction* seq = CCSequence::actions( move, move_back, NULL);
	p->runAction(CCRepeatForever::actionWithAction((CCActionInterval*)seq));
}

std::string ParallaxParticle::title()
{
	return "Parallax + Particles";
}

//------------------------------------------------------------------
//
// RadiusMode1
//
//------------------------------------------------------------------
void RadiusMode1::onEnter()
{
    ParticleDemo::onEnter();

    setColor(ccBLACK);
    removeChild(m_background, true);
    m_background = NULL;

    m_emitter = new CCParticleSystemQuad();
    m_emitter->initWithTotalParticles(200);
    addChild(m_emitter, 10);
    m_emitter->setTexture(CCTextureCache::sharedTextureCache()->addImage("Images/stars-grayscale.png"));

    // duration
    m_emitter->setDuration(kCCParticleDurationInfinity);

    // radius mode
    m_emitter->setEmitterMode(kCCParticleModeRadius);

    // radius mode: start and end radius in pixels
    m_emitter->setStartRadius(0);
    m_emitter->setStartRadiusVar(0);
    m_emitter->setEndRadius(160);
    m_emitter->setEndRadiusVar(0);

    // radius mode: degrees per second
    m_emitter->setRotatePerSecond(180);
    m_emitter->setRotatePerSecondVar(0);

    // angle
    m_emitter->setAngle(90);
    m_emitter->setAngleVar(0);

    // emitter position
    CCSize size = CCDirector::sharedDirector()->getWinSize();
    m_emitter->setPosition(ccp(size.width/2, size.height/2));
    m_emitter->setPosVar(CCPointZero);

    // life of particles
    m_emitter->setLife(5);
    m_emitter->setLifeVar(0);

    // spin of particles
    m_emitter->setStartSpin(0);
    m_emitter->setStartSpinVar(0);
    m_emitter->setEndSpin(0);
    m_emitter->setEndSpinVar(0);

    // color of particles
    ccColor4F startColor = {0.5f, 0.5f, 0.5f, 1.0f};
    m_emitter->setStartColor(startColor);

    ccColor4F startColorVar = {0.5f, 0.5f, 0.5f, 1.0f};
    m_emitter->setStartColorVar(startColorVar);

    ccColor4F endColor = {0.1f, 0.1f, 0.1f, 0.2f};
    m_emitter->setEndColor(endColor);

    ccColor4F endColorVar = {0.1f, 0.1f, 0.1f, 0.2f};
    m_emitter->setEndColorVar(endColorVar);

    // size, in pixels
    m_emitter->setStartSize(32);
    m_emitter->setStartSizeVar(0);
    m_emitter->setEndSize(kCCParticleStartSizeEqualToEndSize);

    // emits per second
    m_emitter->setEmissionRate(m_emitter->getTotalParticles() / m_emitter->getLife());

    // additive
    m_emitter->setIsBlendAdditive(false);
}

std::string RadiusMode1::title()
{
    return "Radius Mode: Spiral";
}

//------------------------------------------------------------------
//
// RadiusMode2
//
//------------------------------------------------------------------
void RadiusMode2::onEnter()
{
    ParticleDemo::onEnter();

    setColor(ccBLACK);
    removeChild(m_background, true);
    m_background = NULL;

    m_emitter = new CCParticleSystemQuad();
    m_emitter->initWithTotalParticles(200);
    addChild(m_emitter, 10);
    m_emitter->setTexture(CCTextureCache::sharedTextureCache()->addImage("Images/stars-grayscale.png"));

    // duration
    m_emitter->setDuration(kCCParticleDurationInfinity);

    // radius mode
    m_emitter->setEmitterMode(kCCParticleModeRadius);

    // radius mode: start and end radius in pixels
    m_emitter->setStartRadius(100);
    m_emitter->setStartRadiusVar(0);
    m_emitter->setEndRadius(kCCParticleStartRadiusEqualToEndRadius);
    m_emitter->setEndRadiusVar(0);

    // radius mode: degrees per second
    m_emitter->setRotatePerSecond(45);
    m_emitter->setRotatePerSecondVar(0);

    // angle
    m_emitter->setAngle(90);
    m_emitter->setAngleVar(0);

    // emitter position
    CCSize size = CCDirector::sharedDirector()->getWinSize();
    m_emitter->setPosition(ccp(size.width/2, size.height/2));
    m_emitter->setPosVar(CCPointZero);

    // life of particles
    m_emitter->setLife(4);
    m_emitter->setLifeVar(0);

    // spin of particles
    m_emitter->setStartSpin(0);
    m_emitter->setStartSpinVar(0);
    m_emitter->setEndSpin(0);
    m_emitter->setEndSpinVar(0);

    // color of particles
    ccColor4F startColor = {0.5f, 0.5f, 0.5f, 1.0f};
    m_emitter->setStartColor(startColor);

    ccColor4F startColorVar = {0.5f, 0.5f, 0.5f, 1.0f};
    m_emitter->setStartColorVar(startColorVar);

        ccColor4F endColor = {0.1f, 0.1f, 0.1f, 0.2f};
    m_emitter->setEndColor(endColor);

    ccColor4F endColorVar = {0.1f, 0.1f, 0.1f, 0.2f};
    m_emitter->setEndColorVar(endColorVar);

    // size, in pixels
    m_emitter->setStartSize(32);
    m_emitter->setStartSizeVar(0);
    m_emitter->setEndSize(kCCParticleStartSizeEqualToEndSize);

    // emits per second
    m_emitter->setEmissionRate(m_emitter->getTotalParticles() / m_emitter->getLife());

    // additive
    m_emitter->setIsBlendAdditive(false);
}

std::string RadiusMode2::title()
{
    return "Radius Mode: Semi Circle";
}

//------------------------------------------------------------------
//
// Issue704
//
//------------------------------------------------------------------
void Issue704::onEnter()
{
    ParticleDemo::onEnter();

    setColor(ccBLACK);
    removeChild(m_background, true);
    m_background = NULL;

    m_emitter = new CCParticleSystemQuad();
    m_emitter->initWithTotalParticles(100);
    addChild(m_emitter, 10);
    m_emitter->setTexture(CCTextureCache::sharedTextureCache()->addImage("Images/fire.png"));

    // duration
    m_emitter->setDuration(kCCParticleDurationInfinity);

    // radius mode
    m_emitter->setEmitterMode(kCCParticleModeRadius);

    // radius mode: start and end radius in pixels
    m_emitter->setStartRadius(50);
    m_emitter->setStartRadiusVar(0);
    m_emitter->setEndRadius(kCCParticleStartRadiusEqualToEndRadius);
    m_emitter->setEndRadiusVar(0);

    // radius mode: degrees per second
    m_emitter->setRotatePerSecond(0);
    m_emitter->setRotatePerSecondVar(0);

    // angle
    m_emitter->setAngle(90);
    m_emitter->setAngleVar(0);

    // emitter position
    CCSize size = CCDirector::sharedDirector()->getWinSize();
    m_emitter->setPosition(ccp(size.width/2, size.height/2));
    m_emitter->setPosVar(CCPointZero);

    // life of particles
    m_emitter->setLife(5);
    m_emitter->setLifeVar(0);

    // spin of particles
    m_emitter->setStartSpin(0);
    m_emitter->setStartSpinVar(0);
    m_emitter->setEndSpin(0);
    m_emitter->setEndSpinVar(0);

    // color of particles
    ccColor4F startColor = {0.5f, 0.5f, 0.5f, 1.0f};
    m_emitter->setStartColor(startColor);

    ccColor4F startColorVar = {0.5f, 0.5f, 0.5f, 1.0f};
    m_emitter->setStartColorVar(startColorVar);

        ccColor4F endColor = {0.1f, 0.1f, 0.1f, 0.2f};
    m_emitter->setEndColor(endColor);

    ccColor4F endColorVar = {0.1f, 0.1f, 0.1f, 0.2f};
    m_emitter->setEndColorVar(endColorVar);

    // size, in pixels
    m_emitter->setStartSize(16);
    m_emitter->setStartSizeVar(0);
    m_emitter->setEndSize(kCCParticleStartSizeEqualToEndSize);

    // emits per second
    m_emitter->setEmissionRate(m_emitter->getTotalParticles() / m_emitter->getLife());

    // additive
    m_emitter->setIsBlendAdditive(false);

    CCRotateBy* rot = CCRotateBy::actionWithDuration(16, 360);
    m_emitter->runAction(CCRepeatForever::actionWithAction(rot));
}

std::string Issue704::title()
{
    return "Issue 704. Free + Rot";
}

std::string Issue704::subtitle()
{
    return "Emitted particles should not rotate";
}

//------------------------------------------------------------------
//
// Issue870
//
//------------------------------------------------------------------
void Issue870::onEnter()
{
    ParticleDemo::onEnter();

    setColor(ccBLACK);
    removeChild(m_background, true);
    m_background = NULL;

    CCParticleSystemQuad *system = new CCParticleSystemQuad();
    system->initWithFile("Images/SpinningPeas.plist");
    system->setTextureWithRect(CCTextureCache::sharedTextureCache()->addImage("Images/particles.png"), CCRectMake(0,0,32,32));
    addChild(system, 10);
    m_emitter = system;

    m_nIndex = 0;
    schedule(schedule_selector(Issue870::updateQuads), 2.0f);
}

void Issue870::updateQuads(ccTime dt)
{
    m_nIndex = (m_nIndex + 1) % 4;
    CCRect rect = CCRectMake(m_nIndex * 32, 0, 32, 32);
    CCParticleSystemQuad* system = (CCParticleSystemQuad*)m_emitter;
    system->setTextureWithRect(m_emitter->getTexture(), rect);
}

std::string Issue870::title()
{
    return "Issue 870. SubRect";
}

std::string Issue870::subtitle()
{
    return "Every 2 seconds the particle should change";
}

//------------------------------------------------------------------
//
// DemoParticleFromFile
//
//------------------------------------------------------------------
void DemoParticleFromFile::onEnter()
{
    ParticleDemo::onEnter();

	setColor(ccBLACK);
	removeChild(m_background, true);
	m_background = NULL;

    m_emitter = new CCParticleSystemQuad();
    std::string filename = "Images/" + m_title + ".plist";
    m_emitter->initWithFile(filename.c_str());
    addChild(m_emitter, 10);

    setEmitterPosition();
}

//------------------------------------------------------------------
//
// ParticleDemo
//
//------------------------------------------------------------------

enum
{
	IDC_NEXT = 100,
	IDC_BACK,
	IDC_RESTART,
	IDC_TOGGLE
};

static int sceneIdx = -1;

#define MAX_LAYER	33

CCLayer* createParticleLayer(int nIndex)
{
	switch(nIndex)
	{
		case 0: return new DemoFlower();
		case 1: return new DemoGalaxy();
		case 2: return new DemoFirework();
		case 3: return new DemoSpiral();
		case 4: return new DemoSun();
		case 5: return new DemoMeteor();
		case 6: return new DemoFire();
		case 7: return new DemoSmoke();
		case 8: return new DemoExplosion();
		case 9: return new DemoSnow();
		case 10: return new DemoRain();
		case 11: return new DemoBigFlower();
		case 12: return new DemoRotFlower();
		case 13: return new DemoModernArt();
		case 14: return new DemoRing();
		case 15: return new ParallaxParticle();
        case 16: return new DemoParticleFromFile("BoilingFoam");
        case 17: return new DemoParticleFromFile("BurstPipe");
        case 18: return new DemoParticleFromFile("Comet");
        case 19: return new DemoParticleFromFile("debian");
        case 20: return new DemoParticleFromFile("ExplodingRing");
        case 21: return new DemoParticleFromFile("LavaFlow");
        case 22: return new DemoParticleFromFile("SpinningPeas");
        case 23: return new DemoParticleFromFile("SpookyPeas");
        case 24: return new DemoParticleFromFile("Upsidedown");
        case 25: return new DemoParticleFromFile("Flower");
        case 26: return new DemoParticleFromFile("Spiral");
        case 27: return new DemoParticleFromFile("Galaxy");
        case 28: return new RadiusMode1();
        case 29: return new RadiusMode2();
        case 30: return new Issue704();
        case 31: return new Issue870();
		case 32: return new DemoParticleFromFile("Phoenix");
	}

	return NULL;
}

CCLayer* nextParticleAction()
{
	sceneIdx++;
	sceneIdx = sceneIdx % MAX_LAYER;

	CCLayer* pLayer = createParticleLayer(sceneIdx);
	pLayer->autorelease();

	return pLayer;
}

CCLayer* backParticleAction()
{
	sceneIdx--;
	int total = MAX_LAYER;
	if( sceneIdx < 0 )
		sceneIdx += total;

	CCLayer* pLayer = createParticleLayer(sceneIdx);
	pLayer->autorelease();

	return pLayer;
}

CCLayer* restartParticleAction()
{
	CCLayer* pLayer = createParticleLayer(sceneIdx);
	pLayer->autorelease();

	return pLayer;
}

ParticleDemo::ParticleDemo(void)
{
	initWithColor( ccc4f(127,127,127,255) );

	m_emitter = NULL;

	setIsTouchEnabled( true );

	CCSize s = CCDirector::sharedDirector()->getWinSize();
	CCLabelTTF* label = CCLabelTTF::labelWithString(title().c_str(), "Arial", 28);
	addChild(label, 100, 1000);
	label->setPosition( CCPointMake(s.width/2, s.height-50) );

	CCLabelTTF *tapScreen = CCLabelTTF::labelWithString("(Tap the Screen)", "Arial", 20);
	tapScreen->setPosition( CCPointMake(s.width/2, s.height-80) );
	addChild(tapScreen, 100);

	CCMenuItemImage* item1 = CCMenuItemImage::itemFromNormalImage(s_pPathB1, s_pPathB2, this, menu_selector(ParticleDemo::backCallback) );
	CCMenuItemImage* item2 = CCMenuItemImage::itemFromNormalImage(s_pPathR1, s_pPathR2, this, menu_selector(ParticleDemo::restartCallback) );
	CCMenuItemImage* item3 = CCMenuItemImage::itemFromNormalImage(s_pPathF1, s_pPathF2,  this, menu_selector(ParticleDemo::nextCallback) );

	CCMenuItemToggle* item4 = CCMenuItemToggle::itemWithTarget(	this,
																menu_selector(ParticleDemo::toggleCallback),
																CCMenuItemFont::itemFromString( "Free Movement" ),
                                                                CCMenuItemFont::itemFromString( "Relative Movement" ),
																CCMenuItemFont::itemFromString( "Grouped Movement" ),
																NULL );

	CCMenu *menu = CCMenu::menuWithItems(item1, item2, item3, item4, NULL);

	menu->setPosition( CCPointZero );
	item1->setPosition( CCPointMake( s.width/2 - 100,30) );
	item2->setPosition( CCPointMake( s.width/2, 30) );
	item3->setPosition( CCPointMake( s.width/2 + 100,30) );
	item4->setPosition( CCPointMake( 0, 100) );
	item4->setAnchorPoint( CCPointMake(0,0) );

	addChild( menu, 100 );

    CCLabelAtlas* labelAtlas = CCLabelAtlas::labelWithString("0000", "fonts/fps_images.png", 16, 24, '.');
    addChild(labelAtlas, 100, kTagLabelAtlas);
	labelAtlas->setPosition( CCPointMake(s.width-66,50) );

	// moving background
	m_background = CCSprite::spriteWithFile(s_back3);
	addChild(m_background, 5);
	m_background->setPosition( CCPointMake(s.width/2, s.height-180) );

	CCActionInterval* move = CCMoveBy::actionWithDuration(4, CCPointMake(300,0) );
	CCActionInterval* move_back = move->reverse();
	CCFiniteTimeAction* seq = CCSequence::actions( move, move_back, NULL);
	m_background->runAction( CCRepeatForever::actionWithAction((CCActionInterval*)seq) );

	schedule( schedule_selector(ParticleDemo::step) );
}

ParticleDemo::~ParticleDemo(void)
{
	m_emitter->release();
}

void ParticleDemo::onEnter(void)
{
	CCLayer::onEnter();

	CCLabelTTF* pLabel = (CCLabelTTF*)(this->getChildByTag(1000));
	pLabel->setString(title().c_str());
}

std::string ParticleDemo::title()
{
	return "No title";
}

void ParticleDemo::registerWithTouchDispatcher()
{
    CCTouchDispatcher::sharedDispatcher()->addTargetedDelegate(this, 0, false);
}

bool ParticleDemo::ccTouchBegan(CCTouch* touch, CCEvent* event)
{
	return true;
}

void ParticleDemo::ccTouchMoved(CCTouch* touch, CCEvent* event)
{
	return ccTouchEnded(touch, event);
}

void ParticleDemo::ccTouchEnded(CCTouch* touch, CCEvent* event)
{
	CCPoint location = touch->locationInView();
	CCPoint convertedLocation = CCDirector::sharedDirector()->convertToGL(location);

    CCPoint pos = CCPointZero;
    if (m_background)
    {
	    pos = m_background->convertToWorldSpace(CCPointZero);
    }
	m_emitter->setPosition( ccpSub(convertedLocation, pos) );
}

void ParticleDemo::step(ccTime dt)
{
    if (m_emitter)
    {
	    CCLabelAtlas* atlas = (CCLabelAtlas*)getChildByTag(kTagLabelAtlas);
        char str[5] = {0};
        sprintf(str, "%04d", m_emitter->getParticleCount());
	    atlas->setString(str);
    }
}

void ParticleDemo::toggleCallback(CCObject* pSender)
{
	if( m_emitter->getPositionType() == kCCPositionTypeGrouped )
		m_emitter->setPositionType( kCCPositionTypeFree );
    else if (m_emitter->getPositionType() == kCCPositionTypeFree)
        m_emitter->setPositionType(kCCPositionTypeRelative);
	else if (m_emitter->getPositionType() == kCCPositionTypeRelative)
		m_emitter->setPositionType( kCCPositionTypeGrouped );
}

void ParticleDemo::restartCallback(CCObject* pSender)
{
	m_emitter->resetSystem();
}

void ParticleDemo::nextCallback(CCObject* pSender)
{
	CCScene* s = new ParticleTestScene();
	s->addChild( nextParticleAction() );
	CCDirector::sharedDirector()->replaceScene(s);
    s->release();
}

void ParticleDemo::backCallback(CCObject* pSender)
{
	CCScene* s = new ParticleTestScene();
	s->addChild( backParticleAction() );
	CCDirector::sharedDirector()->replaceScene(s);
    s->release();
}

void ParticleDemo::setEmitterPosition()
{
    CCSize s = CCDirector::sharedDirector()->getWinSize();

	m_emitter->setPosition( CCPointMake(s.width / 2, s.height / 2) );
}

void ParticleTestScene::runThisTest()
{
    addChild(nextParticleAction());

    CCDirector::sharedDirector()->replaceScene(this);
}


code:
#ifndef _PARTICLE_TEST_H_
#define _PARTICLE_TEST_H_

#include "../testBasic.h"
////----#include "cocos2d.h"
// #include "touch_dispatcher/CCTouch.h"
// #include "CCParticleExample.h"

class ParticleTestScene : public TestScene
{
public:
    virtual void runThisTest();
};

class ParticleDemo : public CCLayerColor
{
protected:
	CCParticleSystem*	m_emitter;
	CCSprite*			m_background;

public:
	ParticleDemo(void);
	~ParticleDemo(void);

	virtual void onEnter(void);

	virtual std::string title();

	void restartCallback(CCObject* pSender);
	void nextCallback(CCObject* pSender);
	void backCallback(CCObject* pSender);
	void toggleCallback(CCObject* pSender);

	virtual void registerWithTouchDispatcher();
	virtual bool ccTouchBegan(CCTouch* touch, CCEvent* event);
	virtual void ccTouchMoved(CCTouch* touch, CCEvent* event);
	virtual void ccTouchEnded(CCTouch* touch, CCEvent* event);

	void step(ccTime dt);
	void setEmitterPosition();
};

class DemoFirework : public ParticleDemo
{
public:
	virtual void onEnter();
	virtual std::string title();
};

class DemoFire : public ParticleDemo
{
public:
	virtual void onEnter();
	virtual std::string title();
};

class DemoSun : public ParticleDemo
{
public:
	virtual void onEnter();
	virtual std::string title();
};

class DemoGalaxy : public ParticleDemo
{
public:
	virtual void onEnter();
	virtual std::string title();
};

class DemoFlower : public ParticleDemo
{
public:
	virtual void onEnter();
	virtual std::string title();
};

class DemoBigFlower : public ParticleDemo
{
public:
	virtual void onEnter();
	virtual std::string title();
};

class DemoRotFlower : public ParticleDemo
{
public:
	virtual void onEnter();
	virtual std::string title();
};

class DemoMeteor : public ParticleDemo
{
public:
	virtual void onEnter();
	virtual std::string title();
};

class DemoSpiral : public ParticleDemo
{
public:
	virtual void onEnter();
	virtual std::string title();
};

class DemoExplosion : public ParticleDemo
{
public:
	virtual void onEnter();
	virtual std::string title();
};

class DemoSmoke : public ParticleDemo
{
public:
	virtual void onEnter();
	virtual std::string title();
};

class DemoSnow : public ParticleDemo
{
public:
	virtual void onEnter();
	virtual std::string title();
};

class DemoRain : public ParticleDemo
{
public:
	virtual void onEnter();
	virtual std::string title();
};

class DemoModernArt : public ParticleDemo
{
public:
	virtual void onEnter();
	virtual std::string title();
};

class DemoRing : public ParticleDemo
{
public:
	virtual void onEnter();
	virtual std::string title();
};

class ParallaxParticle : public ParticleDemo
{
public:
	virtual void onEnter();
	virtual std::string title();
};

class DemoParticleFromFile : public ParticleDemo
{
public:
    std::string m_title;
    DemoParticleFromFile(const char *file)
    {
        m_title = file;
    }
    virtual void onEnter();
    virtual std::string title()
    {
        return m_title;
    }
};

class RadiusMode1 : public ParticleDemo
{
public:
    virtual void onEnter();
    virtual std::string title();
};

class RadiusMode2 : public ParticleDemo
{
public:
    virtual void onEnter();
    virtual std::string title();
};

class Issue704 : public ParticleDemo
{
public:
    virtual void onEnter();
    virtual std::string title();
    virtual std::string subtitle();
};

class Issue870 : public ParticleDemo
{
public:
    virtual void onEnter();
    virtual std::string title();
    virtual std::string subtitle();
    void updateQuads(ccTime dt);

private:
    int m_nIndex;
};

#endif

license: mit


code:
#include "PerformanceNodeChildrenTest.h"

enum {
    kTagInfoLayer = 1,
    kTagMainLayer = 2,
    kTagLabelAtlas = 3,

    kTagBase = 20000,

    TEST_COUNT = 4,
};

enum {
    kMaxNodes = 15000,
    kNodesIncrease = 500,
};

static int s_nCurCase = 0;

////////////////////////////////////////////////////////
//
// NodeChildrenMenuLayer
//
////////////////////////////////////////////////////////
NodeChildrenMenuLayer::NodeChildrenMenuLayer(bool bControlMenuVisible, int nMaxCases, int nCurCase)
: PerformBasicLayer(bControlMenuVisible, nMaxCases, nCurCase)
{

}

void NodeChildrenMenuLayer::showCurrentTest()
{
    int nNodes = ((NodeChildrenMainScene*)getParent())->getQuantityOfNodes();
    NodeChildrenMainScene* pScene = NULL;

    switch (m_nCurCase)
    {
//     case 0:
//         pScene = new IterateSpriteSheetFastEnum();
//         break;
    case 0:
        pScene = new IterateSpriteSheetCArray();
        break;
    case 1:
        pScene = new AddSpriteSheet();
        break;
    case 2:
        pScene = new RemoveSpriteSheet();
        break;
    case 3:
        pScene = new ReorderSpriteSheet();
        break;
    }
    s_nCurCase = m_nCurCase;

    if (pScene)
    {
        pScene->initWithQuantityOfNodes(nNodes);

        CCDirector::sharedDirector()->replaceScene(pScene);
        pScene->release();
    }
}

////////////////////////////////////////////////////////
//
// NodeChildrenMainScene
//
////////////////////////////////////////////////////////
void NodeChildrenMainScene::initWithQuantityOfNodes(unsigned int nNodes)
{
    //srand(time());
    CCSize s = CCDirector::sharedDirector()->getWinSize();

    // Title
    CCLabelTTF *label = CCLabelTTF::labelWithString(title().c_str(), "Arial", 40);
    addChild(label, 1);
    label->setPosition(ccp(s.width/2, s.height-32));
    label->setColor(ccc3(255,255,40));

    // Subtitle
    std::string strSubTitle = subtitle();
    if(strSubTitle.length())
    {
        CCLabelTTF *l = CCLabelTTF::labelWithString(strSubTitle.c_str(), "Thonburi", 16);
        addChild(l, 1);
        l->setPosition(ccp(s.width/2, s.height-80));
    }

    lastRenderedCount = 0;
    currentQuantityOfNodes = 0;
    quantityOfNodes = nNodes;

    CCMenuItemFont::setFontSize(65);
    CCMenuItemFont *decrease = CCMenuItemFont::itemFromString(" - ", this, menu_selector(NodeChildrenMainScene::onDecrease));
    decrease->setColor(ccc3(0,200,20));
    CCMenuItemFont *increase = CCMenuItemFont::itemFromString(" + ", this, menu_selector(NodeChildrenMainScene::onIncrease));
    increase->setColor(ccc3(0,200,20));

    CCMenu *menu = CCMenu::menuWithItems(decrease, increase, NULL);
    menu->alignItemsHorizontally();
    menu->setPosition(ccp(s.width/2, s.height/2+15));
    addChild(menu, 1);

    CCLabelTTF *infoLabel = CCLabelTTF::labelWithString("0 nodes", "Marker Felt", 30);
    infoLabel->setColor(ccc3(0,200,20));
    infoLabel->setPosition(ccp(s.width/2, s.height/2-15));
    addChild(infoLabel, 1, kTagInfoLayer);

    NodeChildrenMenuLayer* pMenu = new NodeChildrenMenuLayer(true, TEST_COUNT, s_nCurCase);
    addChild(pMenu);
    pMenu->release();

    updateQuantityLabel();
    updateQuantityOfNodes();
}

void NodeChildrenMainScene::onDecrease(CCObject* pSender)
{
    quantityOfNodes -= kNodesIncrease;
    if( quantityOfNodes < 0 )
        quantityOfNodes = 0;

    updateQuantityLabel();
    updateQuantityOfNodes();
}

void NodeChildrenMainScene::onIncrease(CCObject* pSender)
{
    quantityOfNodes += kNodesIncrease;
    if( quantityOfNodes > kMaxNodes )
        quantityOfNodes = kMaxNodes;

    updateQuantityLabel();
    updateQuantityOfNodes();
}

std::string NodeChildrenMainScene::title()
{
    return "No title";
}

std::string NodeChildrenMainScene::subtitle()
{
    return "";
}

void NodeChildrenMainScene::updateQuantityLabel()
{
    if( quantityOfNodes != lastRenderedCount )
    {
        CCLabelTTF *infoLabel = (CCLabelTTF *) getChildByTag(kTagInfoLayer);
        char str[20] = {0};
        sprintf(str, "%u nodes", quantityOfNodes);
        infoLabel->setString(str);

        lastRenderedCount = quantityOfNodes;
    }
}

////////////////////////////////////////////////////////
//
// IterateSpriteSheet
//
////////////////////////////////////////////////////////
IterateSpriteSheet::~IterateSpriteSheet()
{
#if CC_ENABLE_PROFILERS
    CCProfiler::releaseTimer(_profilingTimer);
    _profilingTimer = NULL;
#endif
}

void IterateSpriteSheet::updateQuantityOfNodes()
{
    CCSize s = CCDirector::sharedDirector()->getWinSize();

    // increase nodes
    if( currentQuantityOfNodes < quantityOfNodes )
    {
        for(int i = 0; i < (quantityOfNodes-currentQuantityOfNodes); i++)
        {
            CCSprite *sprite = CCSprite::spriteWithTexture(batchNode->getTexture(), CCRectMake(0, 0, 32, 32));
            batchNode->addChild(sprite);
            sprite->setPosition(ccp( CCRANDOM_0_1()*s.width, CCRANDOM_0_1()*s.height));
        }
    }

    // decrease nodes
    else if ( currentQuantityOfNodes > quantityOfNodes )
    {
        for(int i = 0; i < (currentQuantityOfNodes-quantityOfNodes); i++)
        {
            int index = currentQuantityOfNodes-i-1;
            batchNode->removeChildAtIndex(index, true);
        }
    }

    currentQuantityOfNodes = quantityOfNodes;
}

void IterateSpriteSheet::initWithQuantityOfNodes(unsigned int nNodes)
{
    batchNode = CCSpriteBatchNode::batchNodeWithFile("Images/spritesheet1.png");
    addChild(batchNode);

    NodeChildrenMainScene::initWithQuantityOfNodes(nNodes);

#if CC_ENABLE_PROFILERS
    _profilingTimer = CCProfiler::timerWithName(profilerName().c_str(), this);
#endif

    scheduleUpdate();
}

std::string IterateSpriteSheet::profilerName()
{
    return "none";
}

////////////////////////////////////////////////////////
//
// IterateSpriteSheetFastEnum
//
////////////////////////////////////////////////////////
void IterateSpriteSheetFastEnum::update(ccTime dt)
{
    // iterate using fast enumeration protocol
    CCArray* pChildren = batchNode->getChildren();
    CCObject* pObject = NULL;

#if CC_ENABLE_PROFILERS
    CCProfilingBeginTimingBlock(_profilingTimer);
#endif

    CCARRAY_FOREACH(pChildren, pObject)
    {
        CCSprite* pSprite = (CCSprite*) pObject;
        pSprite->setIsVisible(false);
    }

#if CC_ENABLE_PROFILERS
    CCProfilingEndTimingBlock(_profilingTimer);
#endif
}

std::string IterateSpriteSheetFastEnum::title()
{
    return "A - Iterate SpriteSheet";
}

std::string IterateSpriteSheetFastEnum::subtitle()
{
    return "Iterate children using Fast Enum API. See console";
}

std::string IterateSpriteSheetFastEnum::profilerName()
{
    return "iter fast enum";
}

////////////////////////////////////////////////////////
//
// IterateSpriteSheetCArray
//
////////////////////////////////////////////////////////
void IterateSpriteSheetCArray::update(ccTime dt)
{
    // iterate using fast enumeration protocol
    CCArray* pChildren = batchNode->getChildren();
    CCObject* pObject = NULL;

#if CC_ENABLE_PROFILERS
    CCProfilingBeginTimingBlock(_profilingTimer);
#endif

    CCARRAY_FOREACH(pChildren, pObject)
    {
        CCSprite* pSprite = (CCSprite*)pObject;
        pSprite->setIsVisible(false);
    }

#if CC_ENABLE_PROFILERS
    CCProfilingEndTimingBlock(_profilingTimer);
#endif
}

std::string IterateSpriteSheetCArray::title()
{
    return "B - Iterate SpriteSheet";
}

std::string IterateSpriteSheetCArray::subtitle()
{
    return "Iterate children using C Array API. See console";
}

std::string IterateSpriteSheetCArray::profilerName()
{
    return "iter c-array";
}

////////////////////////////////////////////////////////
//
// AddRemoveSpriteSheet
//
////////////////////////////////////////////////////////
AddRemoveSpriteSheet::~AddRemoveSpriteSheet()
{
#if CC_ENABLE_PROFILERS
    CCProfiler::releaseTimer(_profilingTimer);
    _profilingTimer = NULL;
#endif
}

void AddRemoveSpriteSheet::initWithQuantityOfNodes(unsigned int nNodes)
{
    batchNode = CCSpriteBatchNode::batchNodeWithFile("Images/spritesheet1.png");
    addChild(batchNode);

    NodeChildrenMainScene::initWithQuantityOfNodes(nNodes);

#if CC_ENABLE_PROFILERS
    _profilingTimer = CCProfiler::timerWithName(profilerName().c_str(), this);
#endif

    scheduleUpdate();
}

void AddRemoveSpriteSheet::updateQuantityOfNodes()
{
    CCSize s = CCDirector::sharedDirector()->getWinSize();

    // increase nodes
    if( currentQuantityOfNodes < quantityOfNodes )
    {
        for (int i=0; i < (quantityOfNodes-currentQuantityOfNodes); i++)
        {
            CCSprite *sprite = CCSprite::spriteWithTexture(batchNode->getTexture(), CCRectMake(0, 0, 32, 32));
            batchNode->addChild(sprite);
            sprite->setPosition(ccp( CCRANDOM_0_1()*s.width, CCRANDOM_0_1()*s.height));
            sprite->setIsVisible(false);
        }
    }
    // decrease nodes
    else if ( currentQuantityOfNodes > quantityOfNodes )
    {
        for(int i=0;i < (currentQuantityOfNodes-quantityOfNodes);i++)
        {
            int index = currentQuantityOfNodes-i-1;
            batchNode->removeChildAtIndex(index, true);
        }
    }

    currentQuantityOfNodes = quantityOfNodes;
}

std::string AddRemoveSpriteSheet::profilerName()
{
    return "none";
}

////////////////////////////////////////////////////////
//
// AddSpriteSheet
//
////////////////////////////////////////////////////////
void AddSpriteSheet::update(ccTime dt)
{
    // reset seed
    //srandom(0);

    // 15 percent
    int totalToAdd = currentQuantityOfNodes * 0.15f;

    if( totalToAdd > 0 )
    {
        CCArray* sprites = CCArray::arrayWithCapacity(totalToAdd);
        int		 *zs      = new int[totalToAdd];

        // Don't include the sprite creation time and random as part of the profiling
        for(int i=0; i<totalToAdd; i++)
        {
            CCSprite* pSprite = CCSprite::spriteWithTexture(batchNode->getTexture(), CCRectMake(0,0,32,32));
            sprites->addObject(pSprite);
            zs[i]      = CCRANDOM_MINUS1_1() * 50;
        }

        // add them with random Z (very important!)
#if CC_ENABLE_PROFILERS
        CCProfilingBeginTimingBlock(_profilingTimer);
#endif

        for( int i=0; i < totalToAdd;i++ )
        {
            batchNode->addChild((CCNode*) (sprites->objectAtIndex(i)), zs[i], kTagBase+i);
        }

#if CC_ENABLE_PROFILERS
        CCProfilingEndTimingBlock(_profilingTimer);
#endif

        // remove them
        for( int i=0;i <  totalToAdd;i++)
        {
            batchNode->removeChildByTag(kTagBase+i, true);
        }

        delete [] zs;
    }
}

std::string AddSpriteSheet::title()
{
    return "C - Add to spritesheet";
}

std::string AddSpriteSheet::subtitle()
{
    return "Adds %10 of total sprites with random z. See console";
}

std::string AddSpriteSheet::profilerName()
{
    return "add sprites";
}

////////////////////////////////////////////////////////
//
// RemoveSpriteSheet
//
////////////////////////////////////////////////////////
void RemoveSpriteSheet::update(ccTime dt)
{
    //srandom(0);

    // 15 percent
    int totalToAdd = currentQuantityOfNodes * 0.15f;

    if( totalToAdd > 0 )
    {
        CCArray* sprites = CCArray::arrayWithCapacity(totalToAdd);

        // Don't include the sprite creation time as part of the profiling
        for(int i=0;i<totalToAdd;i++)
        {
            CCSprite* pSprite = CCSprite::spriteWithTexture(batchNode->getTexture(), CCRectMake(0,0,32,32));
            sprites->addObject(pSprite);
        }

        // add them with random Z (very important!)
        for( int i=0; i < totalToAdd;i++ )
        {
            batchNode->addChild((CCNode*) (sprites->objectAtIndex(i)), CCRANDOM_MINUS1_1() * 50, kTagBase+i);
        }

        // remove them
#if CC_ENABLE_PROFILERS
        CCProfilingBeginTimingBlock(_profilingTimer);
#endif

        for( int i=0;i <  totalToAdd;i++)
        {
            batchNode->removeChildByTag(kTagBase+i, true);
        }

#if CC_ENABLE_PROFILERS
        CCProfilingEndTimingBlock(_profilingTimer);
#endif
    }
}

std::string RemoveSpriteSheet::title()
{
    return "D - Del from spritesheet";
}

std::string RemoveSpriteSheet::subtitle()
{
    return "Remove %10 of total sprites placed randomly. See console";
}

std::string RemoveSpriteSheet::profilerName()
{
    return "remove sprites";
}

////////////////////////////////////////////////////////
//
// ReorderSpriteSheet
//
////////////////////////////////////////////////////////
void ReorderSpriteSheet::update(ccTime dt)
{
    //srandom(0);

    // 15 percent
    int totalToAdd = currentQuantityOfNodes * 0.15f;

    if( totalToAdd > 0 )
    {
        CCArray* sprites = CCArray::arrayWithCapacity(totalToAdd);

        // Don't include the sprite creation time as part of the profiling
        for(int i=0;i<totalToAdd;i++)
        {
            CCSprite* pSprite = CCSprite::spriteWithTexture(batchNode->getTexture(), CCRectMake(0,0,32,32));
            sprites->addObject(pSprite);
        }

        // add them with random Z (very important!)
        for( int i=0; i < totalToAdd;i++ )
        {
            batchNode->addChild((CCNode*) (sprites->objectAtIndex(i)), CCRANDOM_MINUS1_1() * 50, kTagBase+i);
        }

        //		[batchNode sortAllChildren];

        // reorder them
#if CC_ENABLE_PROFILERS
        CCProfilingBeginTimingBlock(_profilingTimer);
#endif

        for( int i=0;i <  totalToAdd;i++)
        {
            CCNode* pNode = (CCNode*) (batchNode->getChildren()->objectAtIndex(i));
            batchNode->reorderChild(pNode, CCRANDOM_MINUS1_1() * 50);
        }

#if CC_ENABLE_PROFILERS
        CCProfilingEndTimingBlock(_profilingTimer);
#endif

        // remove them
        for( int i=0;i <  totalToAdd;i++)
        {
            batchNode->removeChildByTag(kTagBase+i, true);
        }
    }
}

std::string ReorderSpriteSheet::title()
{
    return "E - Reorder from spritesheet";
}

std::string ReorderSpriteSheet::subtitle()
{
    return "Reorder %10 of total sprites placed randomly. See console";
}

std::string ReorderSpriteSheet::profilerName()
{
    return "reorder sprites";
}

void runNodeChildrenTest()
{
    IterateSpriteSheet* pScene = new IterateSpriteSheetCArray();
    pScene->initWithQuantityOfNodes(kNodesIncrease);

    CCDirector::sharedDirector()->replaceScene(pScene);
    pScene->release();
}


code:
#ifndef __PERFORMANCE_NODE_CHILDREN_TEST_H__
#define __PERFORMANCE_NODE_CHILDREN_TEST_H__

#include "PerformanceTest.h"
#include "CCProfiling.h"

class NodeChildrenMenuLayer : public PerformBasicLayer
{
public:
    NodeChildrenMenuLayer(bool bControlMenuVisible, int nMaxCases = 0, int nCurCase = 0);
    virtual void showCurrentTest();
};

class NodeChildrenMainScene : public CCScene
{
public:
    virtual void initWithQuantityOfNodes(unsigned int nNodes);
    virtual std::string title();
    virtual std::string subtitle();
    virtual void updateQuantityOfNodes() = 0;

    void onDecrease(CCObject* pSender);
    void onIncrease(CCObject* pSender);
    void updateQuantityLabel();

    int getQuantityOfNodes() { return quantityOfNodes; }

protected:
    int	lastRenderedCount;
    int	quantityOfNodes;
    int	currentQuantityOfNodes;
};

class IterateSpriteSheet : public NodeChildrenMainScene
{
public:
    ~IterateSpriteSheet();
    virtual void updateQuantityOfNodes();
    virtual void initWithQuantityOfNodes(unsigned int nNodes);
    virtual void update(ccTime dt) = 0;
    virtual std::string profilerName();

protected:
    CCSpriteBatchNode	*batchNode;

#if CC_ENABLE_PROFILERS
    CCProfilingTimer    *_profilingTimer;
#endif
};

class IterateSpriteSheetFastEnum : public IterateSpriteSheet
{
public:
    virtual void update(ccTime dt);

    virtual std::string title();
    virtual std::string subtitle();
    virtual std::string profilerName();
};

class IterateSpriteSheetCArray : public IterateSpriteSheet
{
public:
    virtual void update(ccTime dt);

    virtual std::string title();
    virtual std::string subtitle();
    virtual std::string profilerName();
};

class AddRemoveSpriteSheet : public NodeChildrenMainScene
{
public:
    ~AddRemoveSpriteSheet();
    virtual void updateQuantityOfNodes();
    virtual void initWithQuantityOfNodes(unsigned int nNodes);
    virtual void update(ccTime dt) = 0;
    virtual std::string profilerName();

protected:
    CCSpriteBatchNode	*batchNode;

#if CC_ENABLE_PROFILERS
    CCProfilingTimer* _profilingTimer;
#endif
};

class AddSpriteSheet : public AddRemoveSpriteSheet
{
public:
    virtual void update(ccTime dt);

    virtual std::string title();
    virtual std::string subtitle();
    virtual std::string profilerName();
};

class RemoveSpriteSheet : public AddRemoveSpriteSheet
{
public:
    virtual void update(ccTime dt);

    virtual std::string title();
    virtual std::string subtitle();
    virtual std::string profilerName();
};

class ReorderSpriteSheet : public AddRemoveSpriteSheet
{
public:
    virtual void update(ccTime dt);

    virtual std::string title();
    virtual std::string subtitle();
    virtual std::string profilerName();
};

void runNodeChildrenTest();

#endif // __PERFORMANCE_NODE_CHILDREN_TEST_H__


code:
#include "PerformanceParticleTest.h"

enum {
    kTagInfoLayer = 1,
    kTagMainLayer = 2,
    kTagParticleSystem = 3,
    kTagLabelAtlas = 4,
    kTagMenuLayer = 1000,

    TEST_COUNT = 4,
};

enum {
    kMaxParticles = 14000,
    kNodesIncrease = 100,
};

static int s_nParCurIdx = 0;

////////////////////////////////////////////////////////
//
// ParticleMenuLayer
//
////////////////////////////////////////////////////////
ParticleMenuLayer::ParticleMenuLayer(bool bControlMenuVisible, int nMaxCases, int nCurCase)
: PerformBasicLayer(bControlMenuVisible, nMaxCases, nCurCase)
{

}

void ParticleMenuLayer::showCurrentTest()
{
    ParticleMainScene* pScene = (ParticleMainScene*)getParent();
    int subTest = pScene->getSubTestNum();
    int parNum  = pScene->getParticlesNum();

    ParticleMainScene* pNewScene = NULL;

    switch (m_nCurCase)
    {
    case 0:
        pNewScene = new ParticlePerformTest1;
        break;
    case 1:
        pNewScene = new ParticlePerformTest2;
        break;
    case 2:
        pNewScene = new ParticlePerformTest3;
        break;
    case 3:
        pNewScene = new ParticlePerformTest4;
        break;
    }

    s_nParCurIdx = m_nCurCase;
    if (pNewScene)
    {
        pNewScene->initWithSubTest(subTest, parNum);

        CCDirector::sharedDirector()->replaceScene(pNewScene);
        pNewScene->release();
    }
}

////////////////////////////////////////////////////////
//
// ParticleMainScene
//
////////////////////////////////////////////////////////
void ParticleMainScene::initWithSubTest(int asubtest, int particles)
{
    //srandom(0);

    subtestNumber = asubtest;
    CCSize s = CCDirector::sharedDirector()->getWinSize();

    lastRenderedCount = 0;
    quantityParticles = particles;

    CCMenuItemFont::setFontSize(65);
    CCMenuItemFont *decrease = CCMenuItemFont::itemFromString(" - ", this, menu_selector(ParticleMainScene::onDecrease));
    decrease->setColor(ccc3(0,200,20));
    CCMenuItemFont *increase = CCMenuItemFont::itemFromString(" + ", this, menu_selector(ParticleMainScene::onIncrease));
    increase->setColor(ccc3(0,200,20));

    CCMenu *menu = CCMenu::menuWithItems(decrease, increase, NULL);
    menu->alignItemsHorizontally();
    menu->setPosition(ccp(s.width/2, s.height/2+15));
    addChild(menu, 1);

    CCLabelTTF *infoLabel = CCLabelTTF::labelWithString("0 nodes", "Marker Felt", 30);
    infoLabel->setColor(ccc3(0,200,20));
    infoLabel->setPosition(ccp(s.width/2, s.height - 90));
    addChild(infoLabel, 1, kTagInfoLayer);

    // particles on stage
    CCLabelAtlas *labelAtlas = CCLabelAtlas::labelWithString("0000", "Images/fps_images.png", 16, 24, '.');
    addChild(labelAtlas, 0, kTagLabelAtlas);
    labelAtlas->setPosition(ccp(s.width-66,50));

    // Next Prev Test
    ParticleMenuLayer* pMenu = new ParticleMenuLayer(true, TEST_COUNT, s_nParCurIdx);
    addChild(pMenu, 1, kTagMenuLayer);
    pMenu->release();

    // Sub Tests
    CCMenuItemFont::setFontSize(40);
    CCMenu* pSubMenu = CCMenu::menuWithItems(NULL);
    for (int i = 1; i <= 6; ++i)
    {
        char str[10] = {0};
        sprintf(str, "%d ", i);
        CCMenuItemFont* itemFont = CCMenuItemFont::itemFromString(str, this, menu_selector(ParticleMainScene::testNCallback));
        itemFont->setTag(i);
        pSubMenu->addChild(itemFont, 10);

        if (i <= 3)
        {
            itemFont->setColor(ccc3(200,20,20));
        }
        else
        {
            itemFont->setColor(ccc3(0,200,20));
        }
    }
    pSubMenu->alignItemsHorizontally();
    pSubMenu->setPosition(ccp(s.width/2, 80));
    addChild(pSubMenu, 2);

    CCLabelTTF *label = CCLabelTTF::labelWithString(title().c_str(), "Arial", 40);
    addChild(label, 1);
    label->setPosition(ccp(s.width/2, s.height-32));
    label->setColor(ccc3(255,255,40));

    updateQuantityLabel();
    createParticleSystem();

    schedule(schedule_selector(ParticleMainScene::step));
}

std::string ParticleMainScene::title()
{
    return "No title";
}

void ParticleMainScene::step(ccTime dt)
{
    CCLabelAtlas *atlas = (CCLabelAtlas*) getChildByTag(kTagLabelAtlas);
    CCParticleSystem *emitter = (CCParticleSystem*) getChildByTag(kTagParticleSystem);

    char str[10] = {0};
    sprintf(str, "%4d", emitter->getParticleCount());
    atlas->setString(str);
}

void ParticleMainScene::createParticleSystem()
{
    CCParticleSystem *particleSystem = NULL;

    /*
    * Tests:
    * 1: Point Particle System using 32-bit textures (PNG)
    * 2: Point Particle System using 16-bit textures (PNG)
    * 3: Point Particle System using 8-bit textures (PNG)
    * 4: Point Particle System using 4-bit textures (PVRTC)

    * 5: Quad Particle System using 32-bit textures (PNG)
    * 6: Quad Particle System using 16-bit textures (PNG)
    * 7: Quad Particle System using 8-bit textures (PNG)
    * 8: Quad Particle System using 4-bit textures (PVRTC)
    */
    removeChildByTag(kTagParticleSystem, true);

    // remove the "fire.png" from the TextureCache cache.
    CCTexture2D *texture = CCTextureCache::sharedTextureCache()->addImage("Images/fire.png");
    CCTextureCache::sharedTextureCache()->removeTexture(texture);

    if (subtestNumber <= 3)
    {
        particleSystem = new CCParticleSystemPoint();
    }
    else
    {
        particleSystem = new CCParticleSystemQuad();
    }

    switch( subtestNumber)
    {
    case 1:
        CCTexture2D::setDefaultAlphaPixelFormat(kCCTexture2DPixelFormat_RGBA8888);
        particleSystem->initWithTotalParticles(quantityParticles);
        particleSystem->setTexture(CCTextureCache::sharedTextureCache()->addImage("Images/fire.png"));
        break;
    case 2:
        CCTexture2D::setDefaultAlphaPixelFormat(kCCTexture2DPixelFormat_RGBA4444);
        particleSystem->initWithTotalParticles(quantityParticles);
        particleSystem->setTexture(CCTextureCache::sharedTextureCache()->addImage("Images/fire.png"));
        break;
    case 3:
        CCTexture2D::setDefaultAlphaPixelFormat(kCCTexture2DPixelFormat_A8);
        particleSystem->initWithTotalParticles(quantityParticles);
        particleSystem->setTexture(CCTextureCache::sharedTextureCache()->addImage("Images/fire.png"));
        break;
//     case 4:
//         particleSystem->initWithTotalParticles(quantityParticles);
//         ////---- particleSystem.texture = [[CCTextureCache sharedTextureCache] addImage:@"fire.pvr"];
//         particleSystem->setTexture(CCTextureCache::sharedTextureCache()->addImage("Images/fire.png"));
//         break;
    case 4:
        CCTexture2D::setDefaultAlphaPixelFormat(kCCTexture2DPixelFormat_RGBA8888);
        particleSystem->initWithTotalParticles(quantityParticles);
        particleSystem->setTexture(CCTextureCache::sharedTextureCache()->addImage("Images/fire.png"));
        break;
    case 5:
        CCTexture2D::setDefaultAlphaPixelFormat(kCCTexture2DPixelFormat_RGBA4444);
        particleSystem->initWithTotalParticles(quantityParticles);
        particleSystem->setTexture(CCTextureCache::sharedTextureCache()->addImage("Images/fire.png"));
        break;
    case 6:
        CCTexture2D::setDefaultAlphaPixelFormat(kCCTexture2DPixelFormat_A8);
        particleSystem->initWithTotalParticles(quantityParticles);
        particleSystem->setTexture(CCTextureCache::sharedTextureCache()->addImage("Images/fire.png"));
        break;
//     case 8:
//         particleSystem->initWithTotalParticles(quantityParticles);
//         ////---- particleSystem.texture = [[CCTextureCache sharedTextureCache] addImage:@"fire.pvr"];
//         particleSystem->setTexture(CCTextureCache::sharedTextureCache()->addImage("Images/fire.png"));
//         break;
    default:
        particleSystem = NULL;
        CCLOG("Shall not happen!");
        break;
    }
    addChild(particleSystem, 0, kTagParticleSystem);
    particleSystem->release();

    doTest();

	// restore the default pixel format
	CCTexture2D::setDefaultAlphaPixelFormat(kCCTexture2DPixelFormat_RGBA8888);
}

void ParticleMainScene::testNCallback(CCObject* pSender)
{
    subtestNumber = ((CCNode*)pSender)->getTag();

    ParticleMenuLayer* pMenu = (ParticleMenuLayer*)getChildByTag(kTagMenuLayer);
    pMenu->restartCallback(pSender);
}

void ParticleMainScene::onIncrease(CCObject* pSender)
{
    quantityParticles += kNodesIncrease;
    if( quantityParticles > kMaxParticles )
        quantityParticles = kMaxParticles;

    updateQuantityLabel();
    createParticleSystem();
}

void ParticleMainScene::onDecrease(CCObject* pSender)
{
    quantityParticles -= kNodesIncrease;
    if( quantityParticles < 0 )
        quantityParticles = 0;

    updateQuantityLabel();
    createParticleSystem();
}

void ParticleMainScene::updateQuantityLabel()
{
    if( quantityParticles != lastRenderedCount )
    {
        CCLabelTTF *infoLabel = (CCLabelTTF *) getChildByTag(kTagInfoLayer);
        char str[20] = {0};
        sprintf(str, "%u particles", quantityParticles);
        infoLabel->setString(str);

        lastRenderedCount = quantityParticles;
    }
}

////////////////////////////////////////////////////////
//
// ParticlePerformTest1
//
////////////////////////////////////////////////////////
std::string ParticlePerformTest1::title()
{
    char str[20] = {0};
    sprintf(str, "A (%d) size=4", subtestNumber);
    std::string strRet = str;
    return strRet;
}

void ParticlePerformTest1::doTest()
{
    CCSize s = CCDirector::sharedDirector()->getWinSize();
    CCParticleSystem *particleSystem = (CCParticleSystem*)getChildByTag(kTagParticleSystem);

    // duration
    particleSystem->setDuration(-1);

    // gravity
    particleSystem->setGravity(ccp(0,-90));

    // angle
    particleSystem->setAngle(90);
    particleSystem->setAngleVar(0);

    // radial
    particleSystem->setRadialAccel(0);
    particleSystem->setRadialAccelVar(0);

    // speed of particles
    particleSystem->setSpeed(180);
    particleSystem->setSpeedVar(50);

    // emitter position
    particleSystem->setPosition(ccp(s.width/2, 100));
    particleSystem->setPosVar(ccp(s.width/2,0));

    // life of particles
    particleSystem->setLife(2.0f);
    particleSystem->setLifeVar(1);

    // emits per frame
    particleSystem->setEmissionRate(particleSystem->getTotalParticles() /particleSystem->getLife());

    // color of particles
    ccColor4F startColor = {0.5f, 0.5f, 0.5f, 1.0f};
    particleSystem->setStartColor(startColor);

    ccColor4F startColorVar = {0.5f, 0.5f, 0.5f, 1.0f};
    particleSystem->setStartColorVar( startColorVar);

    ccColor4F endColor = {0.1f, 0.1f, 0.1f, 0.2f};
    particleSystem->setEndColor(endColor);

    ccColor4F endColorVar = {0.1f, 0.1f, 0.1f, 0.2f};
    particleSystem->setEndColorVar(endColorVar);

    // size, in pixels
    particleSystem->setEndSize(4.0f);
    particleSystem->setStartSize(4.0f);
    particleSystem->setEndSizeVar(0);
    particleSystem->setStartSizeVar(0);

    // additive
    particleSystem->setIsBlendAdditive(false);
}

////////////////////////////////////////////////////////
//
// ParticlePerformTest2
//
////////////////////////////////////////////////////////
std::string ParticlePerformTest2::title()
{
    char str[20] = {0};
    sprintf(str, "B (%d) size=8", subtestNumber);
    std::string strRet = str;
    return strRet;
}

void ParticlePerformTest2::doTest()
{
    CCSize s = CCDirector::sharedDirector()->getWinSize();
    CCParticleSystem *particleSystem = (CCParticleSystem*) getChildByTag(kTagParticleSystem);

    // duration
    particleSystem->setDuration(-1);

    // gravity
    particleSystem->setGravity(ccp(0,-90));

    // angle
    particleSystem->setAngle(90);
    particleSystem->setAngleVar(0);

    // radial
    particleSystem->setRadialAccel(0);
    particleSystem->setRadialAccelVar(0);

    // speed of particles
    particleSystem->setSpeed(180);
    particleSystem->setSpeedVar(50);

    // emitter position
    particleSystem->setPosition(ccp(s.width/2, 100));
    particleSystem->setPosVar(ccp(s.width/2,0));

    // life of particles
    particleSystem->setLife(2.0f);
    particleSystem->setLifeVar(1);

    // emits per frame
    particleSystem->setEmissionRate(particleSystem->getTotalParticles() / particleSystem->getLife());

    // color of particles
    ccColor4F startColor = {0.5f, 0.5f, 0.5f, 1.0f};
    particleSystem->setStartColor(startColor);

    ccColor4F startColorVar = {0.5f, 0.5f, 0.5f, 1.0f};
    particleSystem->setStartColorVar(startColorVar);

    ccColor4F endColor = {0.1f, 0.1f, 0.1f, 0.2f};
    particleSystem->setEndColor(endColor);

    ccColor4F endColorVar = {0.1f, 0.1f, 0.1f, 0.2f};
    particleSystem->setEndColorVar(endColorVar);

    // size, in pixels
    particleSystem->setEndSize(8.0f);
    particleSystem->setStartSize(8.0f);
    particleSystem->setEndSizeVar(0);
    particleSystem->setStartSizeVar(0);

    // additive
    particleSystem->setIsBlendAdditive(false);
}

////////////////////////////////////////////////////////
//
// ParticlePerformTest3
//
////////////////////////////////////////////////////////
std::string ParticlePerformTest3::title()
{
    char str[20] = {0};
    sprintf(str, "C (%d) size=32", subtestNumber);
    std::string strRet = str;
    return strRet;
}

void ParticlePerformTest3::doTest()
{
    CCSize s = CCDirector::sharedDirector()->getWinSize();
    CCParticleSystem *particleSystem = (CCParticleSystem*)getChildByTag(kTagParticleSystem);

    // duration
    particleSystem->setDuration(-1);

    // gravity
    particleSystem->setGravity(ccp(0,-90));

    // angle
    particleSystem->setAngle(90);
    particleSystem->setAngleVar(0);

    // radial
    particleSystem->setRadialAccel(0);
    particleSystem->setRadialAccelVar(0);

    // speed of particles
    particleSystem->setSpeed(180);
    particleSystem->setSpeedVar(50);

    // emitter position
    particleSystem->setPosition(ccp(s.width/2, 100));
    particleSystem->setPosVar(ccp(s.width/2,0));

    // life of particles
    particleSystem->setLife(2.0f);
    particleSystem->setLifeVar(1);

    // emits per frame
    particleSystem->setEmissionRate(particleSystem->getTotalParticles() / particleSystem->getLife());

    // color of particles
    ccColor4F startColor = {0.5f, 0.5f, 0.5f, 1.0f};
    particleSystem->setStartColor(startColor);

    ccColor4F startColorVar = {0.5f, 0.5f, 0.5f, 1.0f};
    particleSystem->setStartColorVar(startColorVar);

    ccColor4F endColor = {0.1f, 0.1f, 0.1f, 0.2f};
    particleSystem->setEndColor(endColor);

    ccColor4F endColorVar = {0.1f, 0.1f, 0.1f, 0.2f};
    particleSystem->setEndColorVar(endColorVar);

    // size, in pixels
    particleSystem->setEndSize(32.0f);
    particleSystem->setStartSize(32.0f);
    particleSystem->setEndSizeVar(0);
    particleSystem->setStartSizeVar(0);

    // additive
    particleSystem->setIsBlendAdditive(false);
}

////////////////////////////////////////////////////////
//
// ParticlePerformTest4
//
////////////////////////////////////////////////////////
std::string ParticlePerformTest4::title()
{
    char str[20] = {0};
    sprintf(str, "D (%d) size=64", subtestNumber);
    std::string strRet = str;
    return strRet;
}

void ParticlePerformTest4::doTest()
{
    CCSize s = CCDirector::sharedDirector()->getWinSize();
    CCParticleSystem *particleSystem = (CCParticleSystem*) getChildByTag(kTagParticleSystem);

    // duration
    particleSystem->setDuration(-1);

    // gravity
    particleSystem->setGravity(ccp(0,-90));

    // angle
    particleSystem->setAngle(90);
    particleSystem->setAngleVar(0);

    // radial
    particleSystem->setRadialAccel(0);
    particleSystem->setRadialAccelVar(0);

    // speed of particles
    particleSystem->setSpeed(180);
    particleSystem->setSpeedVar(50);

    // emitter position
    particleSystem->setPosition(ccp(s.width/2, 100));
    particleSystem->setPosVar(ccp(s.width/2,0));

    // life of particles
    particleSystem->setLife(2.0f);
    particleSystem->setLifeVar(1);

    // emits per frame
    particleSystem->setEmissionRate(particleSystem->getTotalParticles() / particleSystem->getLife());

    // color of particles
    ccColor4F startColor = {0.5f, 0.5f, 0.5f, 1.0f};
    particleSystem->setStartColor(startColor);

    ccColor4F startColorVar = {0.5f, 0.5f, 0.5f, 1.0f};
    particleSystem->setStartColorVar(startColorVar);

    ccColor4F endColor = {0.1f, 0.1f, 0.1f, 0.2f};
    particleSystem->setEndColor(endColor);

    ccColor4F endColorVar = {0.1f, 0.1f, 0.1f, 0.2f};
    particleSystem->setEndColorVar(endColorVar);

    // size, in pixels
    particleSystem->setEndSize(64.0f);
    particleSystem->setStartSize(64.0f);
    particleSystem->setEndSizeVar(0);
    particleSystem->setStartSizeVar(0);

    // additive
    particleSystem->setIsBlendAdditive(false);

}

void runParticleTest()
{
    ParticleMainScene* pScene = new ParticlePerformTest1;
    pScene->initWithSubTest(1, kNodesIncrease);

    CCDirector::sharedDirector()->replaceScene(pScene);
    pScene->release();
}


code:
#ifndef __PERFORMANCE_PARTICLE_TEST_H__
#define __PERFORMANCE_PARTICLE_TEST_H__

#include "PerformanceTest.h"

class ParticleMenuLayer : public PerformBasicLayer
{
public:
    ParticleMenuLayer(bool bControlMenuVisible, int nMaxCases = 0, int nCurCase = 0);
    virtual void showCurrentTest();
};

class ParticleMainScene : public CCScene
{
public:
    virtual void initWithSubTest(int subtest, int particles);
    virtual std::string title();

    void step(ccTime dt);
    void createParticleSystem();
    void onDecrease(CCObject* pSender);
    void onIncrease(CCObject* pSender);
    void testNCallback(CCObject* pSender);
    void updateQuantityLabel();
    int getSubTestNum() { return subtestNumber; }
    int getParticlesNum() { return quantityParticles; }
    virtual void doTest() = 0;

protected:
    int			lastRenderedCount;
    int			quantityParticles;
    int			subtestNumber;
};

class ParticlePerformTest1 : public ParticleMainScene
{
public:
    virtual std::string title();
    virtual void doTest();
};

class ParticlePerformTest2 : public ParticleMainScene
{
public:
    virtual std::string title();
    virtual void doTest();
};

class ParticlePerformTest3 : public ParticleMainScene
{
public:
    virtual std::string title();
    virtual void doTest();
};

class ParticlePerformTest4 : public ParticleMainScene
{
public:
    virtual std::string title();
    virtual void doTest();
};

void runParticleTest();

#endif


code:
#include "PerformanceSpriteTest.h"

enum {
    kMaxNodes = 5000,
    kNodesIncrease = 50,

    TEST_COUNT = 7,
};

enum {
    kTagInfoLayer = 1,
    kTagMainLayer = 2,
    kTagMenuLayer = (kMaxNodes + 1000),
};

static int s_nSpriteCurCase = 0;

////////////////////////////////////////////////////////
//
// SubTest
//
////////////////////////////////////////////////////////
SubTest::~SubTest()
{
    if (batchNode)
    {
        batchNode->release();
        batchNode = NULL;
    }
}

void SubTest::initWithSubTest(int nSubTest, CCNode* p)
{
    subtestNumber = nSubTest;
    parent = p;
    batchNode = NULL;
    /*
    * Tests:
    * 1: 1 (32-bit) PNG sprite of 52 x 139
    * 2: 1 (32-bit) PNG Batch Node using 1 sprite of 52 x 139
    * 3: 1 (16-bit) PNG Batch Node using 1 sprite of 52 x 139
    * 4: 1 (4-bit) PVRTC Batch Node using 1 sprite of 52 x 139

    * 5: 14 (32-bit) PNG sprites of 85 x 121 each
    * 6: 14 (32-bit) PNG Batch Node of 85 x 121 each
    * 7: 14 (16-bit) PNG Batch Node of 85 x 121 each
    * 8: 14 (4-bit) PVRTC Batch Node of 85 x 121 each

    * 9: 64 (32-bit) sprites of 32 x 32 each
    *10: 64 (32-bit) PNG Batch Node of 32 x 32 each
    *11: 64 (16-bit) PNG Batch Node of 32 x 32 each
    *12: 64 (4-bit) PVRTC Batch Node of 32 x 32 each
    */

    // purge textures
    CCTextureCache *mgr = CCTextureCache::sharedTextureCache();
    //		[mgr removeAllTextures];
    mgr->removeTexture(mgr->addImage("Images/grossinis_sister1.png"));
    mgr->removeTexture(mgr->addImage("Images/grossini_dance_atlas.png"));
    mgr->removeTexture(mgr->addImage("Images/spritesheet1.png"));

    switch ( subtestNumber)
    {
        case 1:
        case 4:
        case 7:
            break;
            ///
        case 2:
            CCTexture2D::setDefaultAlphaPixelFormat(kCCTexture2DPixelFormat_RGBA8888);
            batchNode = CCSpriteBatchNode::batchNodeWithFile("Images/grossinis_sister1.png", 100);
            p->addChild(batchNode, 0);
            break;
        case 3:
            CCTexture2D::setDefaultAlphaPixelFormat(kCCTexture2DPixelFormat_RGBA4444);
            batchNode = CCSpriteBatchNode::batchNodeWithFile("Images/grossinis_sister1.png", 100);
            p->addChild(batchNode, 0);
            break;

            ///
        case 5:
            CCTexture2D::setDefaultAlphaPixelFormat(kCCTexture2DPixelFormat_RGBA8888);
            batchNode = CCSpriteBatchNode::batchNodeWithFile("Images/grossini_dance_atlas.png", 100);
            p->addChild(batchNode, 0);
            break;
        case 6:
            CCTexture2D::setDefaultAlphaPixelFormat(kCCTexture2DPixelFormat_RGBA4444);
            batchNode = CCSpriteBatchNode::batchNodeWithFile("Images/grossini_dance_atlas.png", 100);
            p->addChild(batchNode, 0);
            break;

            ///
        case 8:
            CCTexture2D::setDefaultAlphaPixelFormat(kCCTexture2DPixelFormat_RGBA8888);
            batchNode = CCSpriteBatchNode::batchNodeWithFile("Images/spritesheet1.png", 100);
            p->addChild(batchNode, 0);
            break;
        case 9:
            CCTexture2D::setDefaultAlphaPixelFormat(kCCTexture2DPixelFormat_RGBA4444);
            batchNode = CCSpriteBatchNode::batchNodeWithFile("Images/spritesheet1.png", 100);
            p->addChild(batchNode, 0);
            break;

        default:
            break;
    }

    if (batchNode)
    {
        batchNode->retain();
    }

    CCTexture2D::setDefaultAlphaPixelFormat(kCCTexture2DPixelFormat_Default);
}

CCSprite* SubTest::createSpriteWithTag(int tag)
{
    // create
    CCTexture2D::setDefaultAlphaPixelFormat(kCCTexture2DPixelFormat_RGBA8888);

    CCSprite* sprite = NULL;
    switch (subtestNumber)
    {
        case 1:
            {
                sprite = CCSprite::spriteWithFile("Images/grossinis_sister1.png");
                parent->addChild(sprite, 0, tag+100);
                break;
            }
        case 2:
        case 3:
            {
                sprite = CCSprite::spriteWithBatchNode(batchNode, CCRectMake(0, 0, 52, 139));
                batchNode->addChild(sprite, 0, tag+100);
                break;
            }
        case 4:
            {
                int idx = (CCRANDOM_0_1() * 1400 / 100) + 1;
                char str[32] = {0};
                sprintf(str, "Images/grossini_dance_%02d.png", idx);
                sprite = CCSprite::spriteWithFile(str);
                parent->addChild(sprite, 0, tag+100);
                break;
            }
        case 5:
        case 6:
            {
                int y,x;
                int r = (CCRANDOM_0_1() * 1400 / 100);

                y = r / 5;
                x = r % 5;

                x *= 85;
                y *= 121;
                sprite = CCSprite::spriteWithBatchNode(batchNode, CCRectMake(x,y,85,121));
                batchNode->addChild(sprite, 0, tag+100);
                break;
            }

        case 7:
            {
                int y,x;
                int r = (CCRANDOM_0_1() * 6400 / 100);

                y = r / 8;
                x = r % 8;

                char str[40] = {0};
                sprintf(str, "Images/sprites_test/sprite-%d-%d.png", x, y);
                sprite = CCSprite::spriteWithFile(str);
                parent->addChild(sprite, 0, tag+100);
                break;
            }

        case 8:
        case 9:
            {
                int y,x;
                int r = (CCRANDOM_0_1() * 6400 / 100);

                y = r / 8;
                x = r % 8;

                x *= 32;
                y *= 32;
                sprite = CCSprite::spriteWithBatchNode(batchNode, CCRectMake(x,y,32,32));
                batchNode->addChild(sprite, 0, tag+100);
                break;
            }

        default:
            break;
    }

    CCTexture2D::setDefaultAlphaPixelFormat(kCCTexture2DPixelFormat_Default);

    return sprite;
}

void SubTest::removeByTag(int tag)
{
    switch (subtestNumber)
    {
        case 1:
        case 4:
        case 7:
            parent->removeChildByTag(tag+100, true);
            break;
        case 2:
        case 3:
        case 5:
        case 6:
        case 8:
        case 9:
            batchNode->removeChildAtIndex(tag, true);
            //			[batchNode removeChildByTag:tag+100 cleanup:YES];
            break;
        default:
            break;
    }
}

////////////////////////////////////////////////////////
//
// SpriteMenuLayer
//
////////////////////////////////////////////////////////
void SpriteMenuLayer::showCurrentTest()
{
    SpriteMainScene* pScene = NULL;
    SpriteMainScene* pPreScene = (SpriteMainScene*) getParent();
    int nSubTest = pPreScene->getSubTestNum();
    int nNodes   = pPreScene->getNodesNum();

    switch (m_nCurCase)
    {
    case 0:
        pScene = new SpritePerformTest1;
        break;
    case 1:
        pScene = new SpritePerformTest2;
        break;
    case 2:
        pScene = new SpritePerformTest3;
        break;
    case 3:
        pScene = new SpritePerformTest4;
        break;
    case 4:
        pScene = new SpritePerformTest5;
        break;
    case 5:
        pScene = new SpritePerformTest6;
        break;
    case 6:
        pScene = new SpritePerformTest7;
        break;
    }
    s_nSpriteCurCase = m_nCurCase;

    if (pScene)
    {
        pScene->initWithSubTest(nSubTest, nNodes);
        CCDirector::sharedDirector()->replaceScene(pScene);
        pScene->release();
    }
}

////////////////////////////////////////////////////////
//
// SpriteMainScene
//
////////////////////////////////////////////////////////
void SpriteMainScene::initWithSubTest(int asubtest, int nNodes)
{
    //srandom(0);

    subtestNumber = asubtest;
    m_pSubTest = new SubTest;
    m_pSubTest->initWithSubTest(asubtest, this);

    CCSize s = CCDirector::sharedDirector()->getWinSize();

    lastRenderedCount = 0;
    quantityNodes = 0;

    CCMenuItemFont::setFontSize(65);
    CCMenuItemFont *decrease = CCMenuItemFont::itemFromString(" - ", this, menu_selector(SpriteMainScene::onDecrease));
    decrease->setColor(ccc3(0,200,20));
    CCMenuItemFont *increase = CCMenuItemFont::itemFromString(" + ", this, menu_selector(SpriteMainScene::onIncrease));
    increase->setColor(ccc3(0,200,20));

    CCMenu *menu = CCMenu::menuWithItems(decrease, increase, NULL);
    menu->alignItemsHorizontally();
    menu->setPosition(ccp(s.width/2, s.height-65));
    addChild(menu, 1);

    CCLabelTTF *infoLabel = CCLabelTTF::labelWithString("0 nodes", "Marker Felt", 30);
    infoLabel->setColor(ccc3(0,200,20));
    infoLabel->setPosition(ccp(s.width/2, s.height-90));
    addChild(infoLabel, 1, kTagInfoLayer);

    // add menu
    SpriteMenuLayer* pMenu = new SpriteMenuLayer(true, TEST_COUNT, s_nSpriteCurCase);
    addChild(pMenu, 1, kTagMenuLayer);
    pMenu->release();

    // Sub Tests
    CCMenuItemFont::setFontSize(32);
    CCMenu* pSubMenu = CCMenu::menuWithItems(NULL);
    for (int i = 1; i <= 9; ++i)
    {
        char str[10] = {0};
        sprintf(str, "%d ", i);
        CCMenuItemFont* itemFont = CCMenuItemFont::itemFromString(str, this, menu_selector(SpriteMainScene::testNCallback));
        itemFont->setTag(i);
        pSubMenu->addChild(itemFont, 10);

        if( i<= 3)
            itemFont->setColor(ccc3(200,20,20));
        else if(i <= 6)
            itemFont->setColor(ccc3(0,200,20));
        else
            itemFont->setColor(ccc3(0,20,200));
    }

    pSubMenu->alignItemsHorizontally();
    pSubMenu->setPosition(ccp(s.width/2, 80));
    addChild(pSubMenu, 2);

    // add title label
    CCLabelTTF *label = CCLabelTTF::labelWithString(title().c_str(), "Arial", 40);
    addChild(label, 1);
    label->setPosition(ccp(s.width/2, s.height-32));
    label->setColor(ccc3(255,255,40));

    while(quantityNodes < nNodes)
        onIncrease(this);
}

std::string SpriteMainScene::title()
{
    return "No title";
}

SpriteMainScene::~SpriteMainScene()
{
    if (m_pSubTest)
    {
        delete m_pSubTest;
        m_pSubTest = NULL;
    }
}

void SpriteMainScene::testNCallback(CCObject* pSender)
{
    subtestNumber = ((CCMenuItemFont*) pSender)->getTag();
    SpriteMenuLayer* pMenu = (SpriteMenuLayer*)getChildByTag(kTagMenuLayer);
    pMenu->restartCallback(pSender);
}

void SpriteMainScene::updateNodes()
{
    if( quantityNodes != lastRenderedCount )
    {
        CCLabelTTF *infoLabel = (CCLabelTTF *) getChildByTag(kTagInfoLayer);
        char str[16] = {0};
        sprintf(str, "%u nodes", quantityNodes);
        infoLabel->setString(str);

        lastRenderedCount = quantityNodes;
    }
}

void SpriteMainScene::onIncrease(CCObject* pSender)
{
    if( quantityNodes >= kMaxNodes)
        return;

    for( int i=0;i< kNodesIncrease;i++)
    {
        CCSprite *sprite = m_pSubTest->createSpriteWithTag(quantityNodes);
        doTest(sprite);
        quantityNodes++;
    }

    updateNodes();
}

void SpriteMainScene::onDecrease(CCObject* pSender)
{
    if( quantityNodes <= 0 )
        return;

    for( int i=0;i < kNodesIncrease;i++)
    {
        quantityNodes--;
        m_pSubTest->removeByTag(quantityNodes);
    }

    updateNodes();
}

////////////////////////////////////////////////////////
//
// For test functions
//
////////////////////////////////////////////////////////
void performanceActions(CCSprite* pSprite)
{
    CCSize size = CCDirector::sharedDirector()->getWinSize();
    pSprite->setPosition(ccp((rand() % (int)size.width), (rand() % (int)size.height)));

    float period = 0.5f + (rand() % 1000) / 500.0f;
    CCRotateBy* rot = CCRotateBy::actionWithDuration(period, 360.0f * CCRANDOM_0_1());
    CCActionInterval* rot_back = rot->reverse();
    CCAction *permanentRotation = CCRepeatForever::actionWithAction((CCActionInterval *)CCSequence::actions(rot, rot_back, NULL));
    pSprite->runAction(permanentRotation);

    float growDuration = 0.5f + (rand() % 1000) / 500.0f;
    CCActionInterval *grow = CCScaleBy::actionWithDuration(growDuration, 0.5f, 0.5f);
    CCAction *permanentScaleLoop = CCRepeatForever::actionWithAction((CCActionInterval *)CCSequence::actionOneTwo(grow, grow->reverse()));
    pSprite->runAction(permanentScaleLoop);
}

void performanceActions20(CCSprite* pSprite)
{
    CCSize size = CCDirector::sharedDirector()->getWinSize();
    if( CCRANDOM_0_1() < 0.2f )
        pSprite->setPosition(ccp((rand() % (int)size.width), (rand() % (int)size.height)));
    else
        pSprite->setPosition(ccp( -1000, -1000));

    float period = 0.5f + (rand() % 1000) / 500.0f;
    CCRotateBy* rot = CCRotateBy::actionWithDuration(period, 360.0f * CCRANDOM_0_1());
    CCActionInterval* rot_back = rot->reverse();
    CCAction *permanentRotation = CCRepeatForever::actionWithAction((CCActionInterval *)CCSequence::actions(rot, rot_back, NULL));
    pSprite->runAction(permanentRotation);

    float growDuration = 0.5f + (rand() % 1000) / 500.0f;
    CCActionInterval *grow = CCScaleBy::actionWithDuration(growDuration, 0.5f, 0.5f);
    CCAction *permanentScaleLoop = CCRepeatForever::actionWithAction(CCSequence::actionOneTwo(grow, grow->reverse()));
    pSprite->runAction(permanentScaleLoop);
}

void performanceRotationScale(CCSprite* pSprite)
{
    CCSize size = CCDirector::sharedDirector()->getWinSize();
    pSprite->setPosition(ccp((rand() % (int)size.width), (rand() % (int)size.height)));
    pSprite->setRotation(CCRANDOM_0_1() * 360);
    pSprite->setScale(CCRANDOM_0_1() * 2);
}

void performancePosition(CCSprite* pSprite)
{
    CCSize size = CCDirector::sharedDirector()->getWinSize();
    pSprite->setPosition(ccp((rand() % (int)size.width), (rand() % (int)size.height)));
}

void performanceout20(CCSprite* pSprite)
{
    CCSize size = CCDirector::sharedDirector()->getWinSize();

    if( CCRANDOM_0_1() < 0.2f )
        pSprite->setPosition(ccp((rand() % (int)size.width), (rand() % (int)size.height)));
    else
        pSprite->setPosition(ccp( -1000, -1000));
}

void performanceOut100(CCSprite* pSprite)
{
    pSprite->setPosition(ccp( -1000, -1000));
}

void performanceScale(CCSprite* pSprite)
{
    CCSize size = CCDirector::sharedDirector()->getWinSize();
    pSprite->setPosition(ccp((rand() % (int)size.width), (rand() % (int)size.height)));
    pSprite->setScale(CCRANDOM_0_1() * 100 / 50);
}

////////////////////////////////////////////////////////
//
// SpritePerformTest1
//
////////////////////////////////////////////////////////
std::string SpritePerformTest1::title()
{
    char str[32] = {0};
    sprintf(str, "A (%d) position", subtestNumber);
    std::string strRet = str;
    return strRet;
}

void SpritePerformTest1::doTest(CCSprite* sprite)
{
    performancePosition(sprite);
}

////////////////////////////////////////////////////////
//
// SpritePerformTest2
//
////////////////////////////////////////////////////////
std::string SpritePerformTest2::title()
{
    char str[32] = {0};
    sprintf(str, "B (%d) scale", subtestNumber);
    std::string strRet = str;
    return strRet;
}

void SpritePerformTest2::doTest(CCSprite* sprite)
{
    performanceScale(sprite);
}

////////////////////////////////////////////////////////
//
// SpritePerformTest3
//
////////////////////////////////////////////////////////
std::string SpritePerformTest3::title()
{
    char str[32] = {0};
    sprintf(str, "C (%d) scale + rot", subtestNumber);
    std::string strRet = str;
    return strRet;
}

void SpritePerformTest3::doTest(CCSprite* sprite)
{
    performanceRotationScale(sprite);
}

////////////////////////////////////////////////////////
//
// SpritePerformTest4
//
////////////////////////////////////////////////////////
std::string SpritePerformTest4::title()
{
    char str[32] = {0};
    sprintf(str, "D (%d) 100%% out", subtestNumber);
    std::string strRet = str;
    return strRet;
}

void SpritePerformTest4::doTest(CCSprite* sprite)
{
    performanceOut100(sprite);
}

////////////////////////////////////////////////////////
//
// SpritePerformTest5
//
////////////////////////////////////////////////////////
std::string SpritePerformTest5::title()
{
    char str[32] = {0};
    sprintf(str, "E (%d) 80%% out", subtestNumber);
    std::string strRet = str;
    return strRet;
}

void SpritePerformTest5::doTest(CCSprite* sprite)
{
    performanceout20(sprite);
}

////////////////////////////////////////////////////////
//
// SpritePerformTest6
//
////////////////////////////////////////////////////////
std::string SpritePerformTest6::title()
{
    char str[32] = {0};
    sprintf(str, "F (%d) actions", subtestNumber);
    std::string strRet = str;
    return strRet;
}

void SpritePerformTest6::doTest(CCSprite* sprite)
{
    performanceActions(sprite);
}

////////////////////////////////////////////////////////
//
// SpritePerformTest7
//
////////////////////////////////////////////////////////
std::string SpritePerformTest7::title()
{
    char str[32] = {0};
    sprintf(str, "G (%d) actions 80%% out", subtestNumber);
    std::string strRet = str;
    return strRet;
}

void SpritePerformTest7::doTest(CCSprite* sprite)
{
    performanceActions20(sprite);
}

void runSpriteTest()
{
    SpriteMainScene* pScene = new SpritePerformTest1;
    pScene->initWithSubTest(1, 50);
    CCDirector::sharedDirector()->replaceScene(pScene);
    pScene->release();
}


code:
#ifndef __PERFORMANCE_SPRITE_TEST_H__
#define __PERFORMANCE_SPRITE_TEST_H__

#include "PerformanceTest.h"

class SubTest
{
public:
    ~SubTest();
    void removeByTag(int tag);
    CCSprite* createSpriteWithTag(int tag);
    void initWithSubTest(int nSubTest, CCNode* parent);

protected:
    int					subtestNumber;
    CCSpriteBatchNode	*batchNode;
    CCNode* 			parent;
};

class SpriteMenuLayer : public PerformBasicLayer
{
public:
    SpriteMenuLayer(bool bControlMenuVisible, int nMaxCases = 0, int nCurCase = 0)
        : PerformBasicLayer(bControlMenuVisible, nMaxCases, nCurCase)
    {
    }

    virtual void showCurrentTest();
};

class SpriteMainScene : public CCScene
{
public:
    virtual ~SpriteMainScene();
    virtual std::string title();

    void initWithSubTest(int nSubTest, int nNodes);
    void updateNodes();

    void testNCallback(CCObject* pSender);
    void onIncrease(CCObject* pSender);
    void onDecrease(CCObject* pSender);

    virtual void doTest(CCSprite* sprite) = 0;

    int getSubTestNum() { return subtestNumber; }
    int getNodesNum() { return quantityNodes; }

protected:
    int			lastRenderedCount;
    int			quantityNodes;
    SubTest		*m_pSubTest;
    int			subtestNumber;
};

class SpritePerformTest1 : public SpriteMainScene
{
public:
    virtual void doTest(CCSprite* sprite);
    virtual std::string title();
};

class SpritePerformTest2 : public SpriteMainScene
{
public:
    virtual void doTest(CCSprite* sprite);
    virtual std::string title();
};

class SpritePerformTest3 : public SpriteMainScene
{
public:
    virtual void doTest(CCSprite* sprite);
    virtual std::string title();
};

class SpritePerformTest4 : public SpriteMainScene
{
public:
    virtual void doTest(CCSprite* sprite);
    virtual std::string title();
};

class SpritePerformTest5 : public SpriteMainScene
{
public:
    virtual void doTest(CCSprite* sprite);
    virtual std::string title();
};

class SpritePerformTest6 : public SpriteMainScene
{
public:
    virtual void doTest(CCSprite* sprite);
    virtual std::string title();
};

class SpritePerformTest7 : public SpriteMainScene
{
public:
    virtual void doTest(CCSprite* sprite);
    virtual std::string title();
};

void runSpriteTest();

#endif


code:
#include "PerformanceTest.h"
#include "../testResource.h"
#include "PerformanceNodeChildrenTest.h"
#include "PerformanceParticleTest.h"
#include "PerformanceSpriteTest.h"
#include "PerformanceTextureTest.h"
#include "PerformanceTouchesTest.h"

enum
{
    MAX_COUNT = 5,
    LINE_SPACE = 40,
    kItemTagBasic = 1000,
};

const std::string testsName[MAX_COUNT] =
{
    "PerformanceNodeChildrenTest",
    "PerformanceParticleTest",
    "PerformanceSpriteTest",
    "PerformanceTextureTest",
    "PerformanceTouchesTest"
};

////////////////////////////////////////////////////////
//
// PerformanceMainLayer
//
////////////////////////////////////////////////////////
void PerformanceMainLayer::onEnter()
{
    CCLayer::onEnter();

    CCSize s = CCDirector::sharedDirector()->getWinSize();

    CCMenu* pMenu = CCMenu::menuWithItems(NULL);
    pMenu->setPosition( CCPointZero );
    CCMenuItemFont::setFontName("Arial");
    CCMenuItemFont::setFontSize(24);
    for (int i = 0; i < MAX_COUNT; ++i)
    {
        CCMenuItemFont* pItem = CCMenuItemFont::itemFromString(testsName[i].c_str(), this,
                                                    menu_selector(PerformanceMainLayer::menuCallback));
        pItem->setPosition(ccp(s.width / 2, s.height - (i + 1) * LINE_SPACE));
        pMenu->addChild(pItem, kItemTagBasic + i);
    }

    addChild(pMenu);
}

void PerformanceMainLayer::menuCallback(CCObject* pSender)
{
    CCMenuItemFont* pItem = (CCMenuItemFont*)pSender;
    int nIndex = pItem->getZOrder() - kItemTagBasic;

    switch (nIndex)
    {
    case 0:
        runNodeChildrenTest();
        break;
    case 1:
        runParticleTest();
        break;
    case 2:
        runSpriteTest();
        break;
    case 3:
        runTextureTest();
        break;
    case 4:
        runTouchesTest();
        break;
    default:
        break;
    }
}

////////////////////////////////////////////////////////
//
// PerformBasicLayer
//
////////////////////////////////////////////////////////
PerformBasicLayer::PerformBasicLayer(bool bControlMenuVisible, int nMaxCases, int nCurCase)
: m_bControlMenuVisible(bControlMenuVisible)
, m_nMaxCases(nMaxCases)
, m_nCurCase(nCurCase)
{

}

void PerformBasicLayer::onEnter()
{
    CCLayer::onEnter();

    CCSize s = CCDirector::sharedDirector()->getWinSize();

    CCMenuItemFont::setFontName("Arial");
    CCMenuItemFont::setFontSize(24);
    CCMenuItemFont* pMainItem = CCMenuItemFont::itemFromString("Back", this,
                                                    menu_selector(PerformBasicLayer::toMainLayer));
    pMainItem->setPosition(ccp(s.width - 50, 25));
    CCMenu* pMenu = CCMenu::menuWithItems(pMainItem, NULL);
    pMenu->setPosition( CCPointZero );

    if (m_bControlMenuVisible)
    {
        CCMenuItemImage *item1 = CCMenuItemImage::itemFromNormalImage(s_pPathB1, s_pPathB2, this, menu_selector(PerformBasicLayer::backCallback) );
        CCMenuItemImage *item2 = CCMenuItemImage::itemFromNormalImage(s_pPathR1, s_pPathR2, this, menu_selector(PerformBasicLayer::restartCallback) );
        CCMenuItemImage *item3 = CCMenuItemImage::itemFromNormalImage(s_pPathF1, s_pPathF2, this, menu_selector(PerformBasicLayer::nextCallback) );
        item1->setPosition( ccp( s.width/2 - 100,30) );
        item2->setPosition( ccp( s.width/2, 30) );
        item3->setPosition( ccp( s.width/2 + 100,30) );

        pMenu->addChild(item1, kItemTagBasic);
        pMenu->addChild(item2, kItemTagBasic);
        pMenu->addChild(item3, kItemTagBasic);
    }
    addChild(pMenu);
}

void PerformBasicLayer::toMainLayer(CCObject* pSender)
{
    PerformanceTestScene* pScene = new PerformanceTestScene();
    pScene->runThisTest();

    pScene->release();
}

void PerformBasicLayer::restartCallback(CCObject* pSender)
{
    showCurrentTest();
}

void PerformBasicLayer::nextCallback(CCObject* pSender)
{
    m_nCurCase++;
    m_nCurCase = m_nCurCase % m_nMaxCases;

    showCurrentTest();
}

void PerformBasicLayer::backCallback(CCObject* pSender)
{
    m_nCurCase--;
    if( m_nCurCase < 0 )
        m_nCurCase += m_nMaxCases;

    showCurrentTest();
}

////////////////////////////////////////////////////////
//
// PerformanceTestScene
//
////////////////////////////////////////////////////////

void PerformanceTestScene::runThisTest()
{
    CCLayer* pLayer = new PerformanceMainLayer();
    addChild(pLayer);
    pLayer->release();

    CCDirector::sharedDirector()->replaceScene(this);
}


code:
#ifndef __PERFORMANCE_TEST_H__
#define __PERFORMANCE_TEST_H__

#include "../testBasic.h"

class PerformanceMainLayer : public CCLayer
{
public:
    virtual void onEnter();
    void menuCallback(CCObject* pSender);
};

class PerformBasicLayer : public CCLayer
{
public:
    PerformBasicLayer(bool bControlMenuVisible, int nMaxCases = 0, int nCurCase = 0);

    virtual void onEnter();

    virtual void restartCallback(CCObject* pSender);
    virtual void nextCallback(CCObject* pSender);
    virtual void backCallback(CCObject* pSender);
    virtual void showCurrentTest() = 0;

    virtual void toMainLayer(CCObject* pSender);

protected:
    bool m_bControlMenuVisible;
    int  m_nMaxCases;
    int  m_nCurCase;
};

class PerformanceTestScene : public TestScene
{
public:
    virtual void runThisTest();
};

#endif