[Cocos2d-x相关教程来源于红孩儿的游戏编程之路CSDN博客地址:http://blog.csdn.net/honghaier]
红孩儿Cocos2d-X学习园地QQ2群:44208467加群写:Cocos2d-x
红孩儿Cocos2d-X学习园地QQ群:249941957加群写:Cocos2d-x
Cocos2d-x2.0 粒子系统深入分析三部曲(三)
另:本章所用Cocos2d-x版本为:
cocos2d-2.0-x-2.0.2@ Aug 30 2012
http://cn.cocos2d-x.org/download
前面两节我们分析了Cocos2d-x中粒子系统的的基类,了解了粒子系统的构成与原理,本节我们来看一下在Cocos2d-x中如何具体展示粒子系统。
我们打开libcocos2d工程下的particle_nodes目录,可以看到:

这个目录是粒子系统相关的一些源码的列表,很明显,我们还有一个CCParticleExample.h/cpp没有学习。那么,这一节,我们将会从这两个文件开始。
CCParticleSystem.h:
#ifndef __CCPARTICLE_EXAMPLE_H__
#define __CCPARTICLE_EXAMPLE_H__
//包含粒子系统基类头文件
#include "CCParticleSystemQuad.h"
//使用Cocos2d命名空间
NS_CC_BEGIN
//由粒子系统基类派生出CCParticleFire,表现的是火焰
class CC_DLL CCParticleFire : public CCParticleSystemQuad
{
public:
//构造
CCParticleFire(){}
//析构
virtual ~CCParticleFire(){}
//初始化,创建250个粒子。
bool init(){ return initWithTotalParticles(250); }
//创建相应数量的粒子。
virtual bool initWithTotalParticles(unsigned int numberOfParticles);
//创建一个当前实例对象,内部调用create实现。
static CCParticleFire * node()
{
return create();
}
//上面的create实现。
static CCParticleFire * create()
{
//创建一个新的实例,初始化后交由内存管理器进行管理,返回实例指针。
CCParticleFire *pRet = new CCParticleFire();
if (pRet->init())
{
pRet->autorelease();
return pRet;
}
//如果失败释放置空并返回NULL。
CC_SAFE_DELETE(pRet);
return NULL;
}
};
对应的CPP实现:
//创建相应数量的粒子。
bool CCParticleFire::initWithTotalParticles(unsigned int numberOfParticles)
{
//调用基类的初始化函数。
if( CCParticleSystemQuad::initWithTotalParticles(numberOfParticles) )
{
// 设置为一直不断的发射。
m_fDuration = kCCParticleDurationInfinity;
// 设置为重力加速模式。
this->m_nEmitterMode = kCCParticleModeGravity;
// 设置重力加速度的值。
this->modeA.gravity = ccp(0,0);
// 设置半径变化值及其用于随机初始化的范围值。
this->modeA.radialAccel = 0;
this->modeA.radialAccelVar = 0;
// 设置速度及其用于随机初始化的范围值。
this->modeA.speed = 60;
this->modeA.speedVar = 20;
// 设置起始角度及其用于随机初始化的范围值。
m_fAngle = 90;
m_fAngleVar = 10;
// 设置发射器的位置及其用于随机初始化的范围值。
CCSize winSize = CCDirector::sharedDirector()->getWinSize();
this->setPosition(ccp(winSize.width/2, 60));
this->m_tPosVar = ccp(40, 20);
// 粒子的生命值及其用于随机初始化的范围值。
m_fLife = 3;
m_fLifeVar = 0.25f;
//起始大小及其用于随机初始化的范围值。终止大小为枚举值,在粒子系统基类的update里有处理,即大小在更新时不变化。
m_fStartSize = 54.0f;
m_fStartSizeVar = 10.0f;
m_fEndSize = kCCParticleStartSizeEqualToEndSize;
// 发射器的发射速率。
m_fEmissionRate = m_uTotalParticles/m_fLife;
// 起始和结束的粒子颜色。
m_tStartColor.r = 0.76f;
m_tStartColor.g = 0.25f;
m_tStartColor.b = 0.12f;
m_tStartColor.a = 1.0f;
m_tStartColorVar.r = 0.0f;
m_tStartColorVar.g = 0.0f;
m_tStartColorVar.b = 0.0f;
m_tStartColorVar.a = 0.0f;
m_tEndColor.r = 0.0f;
m_tEndColor.g = 0.0f;
m_tEndColor.b = 0.0f;
m_tEndColor.a = 1.0f;
m_tEndColorVar.r = 0.0f;
m_tEndColorVar.g = 0.0f;
m_tEndColorVar.b = 0.0f;
m_tEndColorVar.a = 0.0f;
// 设置为加亮模式。
this->setBlendAdditive(true);
return true;
}
return false;
}
//由粒子系统基类派生出CCParticleFire,表现的是焰火
class CC_DLL CCParticleFireworks : public CCParticleSystemQuad
{
public:
//构造
CCParticleFireworks(){}
//析构
virtual ~CCParticleFireworks(){}
//初始化,创建1500个粒子。
bool init(){ return initWithTotalParticles(1500); }
//创建相应数量的粒子。
virtual bool initWithTotalParticles(unsigned int numberOfParticles);
//创建一个当前实例对象,内部调用create实现。
static CCParticleFireworks * node()
{
return create();
}
//上面的create实现。
static CCParticleFireworks * create()
{
//创建一个新的实例,初始化后交由内存管理器进行管理,返回实例指针。
CCParticleFireworks *pRet = new CCParticleFireworks();
if (pRet->init())
{
pRet->autorelease();
return pRet;
}
//如果失败释放置空并返回NULL。
CC_SAFE_DELETE(pRet);
return NULL;
}
};
对应CPP实现:
//创建相应数量的粒子。
bool CCParticleFireworks::initWithTotalParticles(unsigned int numberOfParticles)
{
//先调用基类的相应函数。
if( CCParticleSystemQuad::initWithTotalParticles(numberOfParticles) )
{
// 设置为一直不断的发射。
m_fDuration = kCCParticleDurationInfinity;
// 设置为重力加速模式。
this->m_nEmitterMode = kCCParticleModeGravity;
// 设置重力加速度值。
this->modeA.gravity = ccp(0,-90);
// 设置半径变化值及其用于随机初始化的范围值。
this->modeA.radialAccel = 0;
this->modeA.radialAccelVar = 0;
// 设置速度及其用于随机初始化的范围值。
this->modeA.speed = 180;
this->modeA.speedVar = 50;
//设置发射器的位置。
CCSize winSize = CCDirector::sharedDirector()->getWinSize();
this->setPosition(ccp(winSize.width/2, winSize.height/2));
//设置起始角度及其用于随机初始化的范围值。
this->m_fAngle= 90;
this->m_fAngleVar = 20;
// 粒子的生命值及其用于随机初始化的范围值。
this->m_fLife = 3.5f;
this->m_fLifeVar = 1;
// 发射器的发射速率。
this->m_fEmissionRate = m_uTotalParticles/m_fLife;
// 起始和结束的粒子颜色。
m_tStartColor.r = 0.5f;
m_tStartColor.g = 0.5f;
m_tStartColor.b = 0.5f;
m_tStartColor.a = 1.0f;
m_tStartColorVar.r = 0.5f;
m_tStartColorVar.g = 0.5f;
m_tStartColorVar.b = 0.5f;
m_tStartColorVar.a = 0.1f;
m_tEndColor.r = 0.1f;
m_tEndColor.g = 0.1f;
m_tEndColor.b = 0.1f;
m_tEndColor.a = 0.2f;
m_tEndColorVar.r = 0.1f;
m_tEndColorVar.g = 0.1f;
m_tEndColorVar.b = 0.1f;
m_tEndColorVar.a = 0.2f;
//起始大小及其用于随机初始化的范围值,终止大小指定与起始大小相同,即在更新时不变化。
m_fStartSize = 8.0f;
m_fStartSizeVar = 2.0f;
m_fEndSize = kCCParticleStartSizeEqualToEndSize;
//不使用加亮模式。
this->setBlendAdditive(false);
return true;
}
return false;
}
//由粒子系统基类派生出CCParticleSun,表现的是太阳
class CC_DLL CCParticleSun : public CCParticleSystemQuad
{
public:
//构造
CCParticleSun(){}
//析构
virtual ~CCParticleSun(){}
//初始化,创建350个粒子。
bool init(){ return initWithTotalParticles(350); }
//创建相应数量的粒子。
virtual bool initWithTotalParticles(unsigned int numberOfParticles);
//创建一个当前实例,内部调用create实现。
static CCParticleSun * node()
{
return create();
}
//上面的create实现。
static CCParticleSun * create()
{
CCParticleSun *pRet = new CCParticleSun();
if (pRet->init())
{
pRet->autorelease();
return pRet;
}
CC_SAFE_DELETE(pRet);
return NULL;
}
};
对应的CPP实现:
//创建相应数量的粒子。
bool CCParticleSun::initWithTotalParticles(unsigned int numberOfParticles)
{
//先调用基类的相应函数。if( CCParticleSystemQuad::initWithTotalParticles(numberOfParticles) )
{
// 设置使用加亮模式。
this->setBlendAdditive(true);
// 设置为一直不断的发射。
m_fDuration = kCCParticleDurationInfinity;
// 设置为重力加速模式。
m_nEmitterMode = kCCParticleModeGravity;
// 设置重力加速度值。
modeA.gravity = ccp(0,0);
// 设置半径变化值及其用于随机初始化的范围值。
modeA.radialAccel = 0;
modeA.radialAccelVar = 0;
// 设置速度及其用于随机初始化的范围值。
modeA.speed = 20;
modeA.speedVar = 5;
//设置起始角度及其用于随机初始化的范围值。
m_fAngle = 90;
m_fAngleVar = 360;
//设置发射器的位置及其用于随机初始化的范围值。
CCSize winSize = CCDirector::sharedDirector()->getWinSize();
this->setPosition(ccp(winSize.width/2, winSize.height/2));
m_tPosVar = CCPointZero;
// 粒子的生命值及其用于随机初始化的范围值。
m_fLife = 1;
m_fLifeVar = 0.5f;
//起始大小及其用于随机初始化的范围值,终止大小指定与起始大小相同,即在更新时不变化。
m_fStartSize = 30.0f;
m_fStartSizeVar = 10.0f;
m_fEndSize = kCCParticleStartSizeEqualToEndSize;
// 发射器的发射速率。
m_fEmissionRate = m_uTotalParticles/m_fLife;
// 起始和结束的粒子颜色。
m_tStartColor.r = 0.76f;
m_tStartColor.g = 0.25f;
m_tStartColor.b = 0.12f;
m_tStartColor.a = 1.0f;
m_tStartColorVar.r = 0.0f;
m_tStartColorVar.g = 0.0f;
m_tStartColorVar.b = 0.0f;
m_tStartColorVar.a = 0.0f;
m_tEndColor.r = 0.0f;
m_tEndColor.g = 0.0f;
m_tEndColor.b = 0.0f;
m_tEndColor.a = 1.0f;
m_tEndColorVar.r = 0.0f;
m_tEndColorVar.g = 0.0f;
m_tEndColorVar.b = 0.0f;
m_tEndColorVar.a = 0.0f;
return true;
}
return false;
}
//由粒子系统基类派生出CCParticleGalaxy,表现的是银河或一大堆星星。
class CC_DLL CCParticleGalaxy : public CCParticleSystemQuad
{
public:
//构造与析构
CCParticleGalaxy(){}
virtual ~CCParticleGalaxy(){}
//初始化,创建200个粒子。
bool init(){ return initWithTotalParticles(200); }
//创建相应数量的例子。
virtual bool initWithTotalParticles(unsigned int numberOfParticles);
//创建当前类的实例,内部调用create实现。
static CCParticleGalaxy * node()
{
return create();
}
//上面的create实现。
static CCParticleGalaxy * create()
{
CCParticleGalaxy *pRet = new CCParticleGalaxy();
if (pRet->init())
{
pRet->autorelease();
return pRet;
}
CC_SAFE_DELETE(pRet);
return NULL;
}
};
其对应的CPP:
bool CCParticleGalaxy::initWithTotalParticles(unsigned int numberOfParticles)
{
//调用基类的相应函数。
if( CCParticleSystemQuad::initWithTotalParticles(numberOfParticles) )
{
// 设置为一直不断的发射。
m_fDuration = kCCParticleDurationInfinity;
// 设置为重力加速模式。
m_nEmitterMode = kCCParticleModeGravity;
// 设置重力加速度值。
modeA.gravity = ccp(0,0);
// 设置速度及其用于随机初始化的范围值。
modeA.speed = 60;
modeA.speedVar = 10;
// 设置半径变化值及其用于随机初始化的范围值。
modeA.radialAccel = -80;
modeA.radialAccelVar = 0;
// 设置切角变化值及其用于随机初始化的范围值。
modeA.tangentialAccel = 80;
modeA.tangentialAccelVar = 0;
//设置起始角度及其用于随机初始化的范围值。
m_fAngle = 90;
m_fAngleVar = 360;
//设置发射器的位置及其用于随机初始化的范围值。
CCSize winSize = CCDirector::sharedDirector()->getWinSize();
this->setPosition(ccp(winSize.width/2, winSize.height/2));
m_tPosVar = CCPointZero;
// 粒子的生命值及其用于随机初始化的范围值。
m_fLife = 4;
m_fLifeVar = 1;
//起始大小及其用于随机初始化的范围值,终止大小指定与起始大小相同,即在更新时不变化。
m_fStartSize = 37.0f;
m_fStartSizeVar = 10.0f;
m_fEndSize = kCCParticleStartSizeEqualToEndSize;
//发射器的发射速率
m_fEmissionRate = m_uTotalParticles/m_fLife;
// 起始和结束的粒子颜色。
m_tStartColor.r = 0.12f;
m_tStartColor.g = 0.25f;
m_tStartColor.b = 0.76f;
m_tStartColor.a = 1.0f;
m_tStartColorVar.r = 0.0f;
m_tStartColorVar.g = 0.0f;
m_tStartColorVar.b = 0.0f;
m_tStartColorVar.a = 0.0f;
m_tEndColor.r = 0.0f;
m_tEndColor.g = 0.0f;
m_tEndColor.b = 0.0f;
m_tEndColor.a = 1.0f;
m_tEndColorVar.r = 0.0f;
m_tEndColorVar.g = 0.0f;
m_tEndColorVar.b = 0.0f;
m_tEndColorVar.a = 0.0f;
// 设置为加亮模式。
this->setBlendAdditive(true);
return true;
}
return false;
}
//由粒子系统基类派生出CCParticleFlower,表现的是花瓣洒落。
class CC_DLL CCParticleFlower : public CCParticleSystemQuad
{
public:
//函数注释同上面的类,不再赘述。
CCParticleFlower(){}
virtual ~CCParticleFlower(){}
bool init(){ return initWithTotalParticles(250); }
virtual bool initWithTotalParticles(unsigned int numberOfParticles);
static CCParticleFlower * node()
{
return create();
}
static CCParticleFlower * create()
{
CCParticleFlower *pRet = new CCParticleFlower();
if (pRet->init())
{
pRet->autorelease();
return pRet;
}
CC_SAFE_DELETE(pRet);
return NULL;
}
};
对应的CPP:
bool CCParticleFlower::initWithTotalParticles(unsigned int numberOfParticles)
{
//先调用基类的相应函数。
if( CCParticleSystemQuad::initWithTotalParticles(numberOfParticles) )
{
// 设置为一直不断的发射。
m_fDuration = kCCParticleDurationInfinity;
// 设置为重力加速模式。
m_nEmitterMode = kCCParticleModeGravity;
// 设置重力加速度的值。
modeA.gravity = ccp(0,0);
// 设置速度及其用于随机初始化的范围值。
modeA.speed = 80;
modeA.speedVar = 10;
// 设置半径变化值及其用于随机初始化的范围值。
modeA.radialAccel = -60;
modeA.radialAccelVar = 0;
// 设置切角变化值及其用于随机初始化的范围值。
modeA.tangentialAccel = 15;
modeA.tangentialAccelVar = 0;
// 设置起始角度及其用于随机初始化的范围值。
m_fAngle = 90;
m_fAngleVar = 360;
//设置发射器的位置及其用于随机初始化的范围值。
CCSize winSize = CCDirector::sharedDirector()->getWinSize();
this->setPosition(ccp(winSize.width/2, winSize.height/2));
m_tPosVar = CCPointZero;
// 粒子的生命值及其用于随机初始化的范围值。
m_fLife = 4;
m_fLifeVar = 1;
//起始大小及其用于随机初始化的范围值,终止大小指定与起始大小相同,即在更新时不变化。
m_fStartSize = 30.0f;
m_fStartSizeVar = 10.0f;
m_fEndSize = kCCParticleStartSizeEqualToEndSize;
// 发射器的发射速率。
m_fEmissionRate = m_uTotalParticles/m_fLife;
// 起始和结束的粒子颜色。
m_tStartColor.r = 0.50f;
m_tStartColor.g = 0.50f;
m_tStartColor.b = 0.50f;
m_tStartColor.a = 1.0f;
m_tStartColorVar.r = 0.5f;
m_tStartColorVar.g = 0.5f;
m_tStartColorVar.b = 0.5f;
m_tStartColorVar.a = 0.5f;
m_tEndColor.r = 0.0f;
m_tEndColor.g = 0.0f;
m_tEndColor.b = 0.0f;
m_tEndColor.a = 1.0f;
m_tEndColorVar.r = 0.0f;
m_tEndColorVar.g = 0.0f;
m_tEndColorVar.b = 0.0f;
m_tEndColorVar.a = 0.0f;
// 设置为加亮模式。
this->setBlendAdditive(true);
return true;
}
return false;
}
//由粒子系统基类派生出CCParticleMeteor,表现的是流星
class CC_DLL CCParticleMeteor : public CCParticleSystemQuad
{
public:
//函数注释同上面的类,不再赘述。
CCParticleMeteor(){}
virtual ~CCParticleMeteor(){}
bool init(){ return initWithTotalParticles(150); }
virtual bool initWithTotalParticles(unsigned int numberOfParticles);
static CCParticleMeteor * node()
{
return create();
}
static CCParticleMeteor * create()
{
CCParticleMeteor *pRet = new CCParticleMeteor();
if (pRet->init())
{
pRet->autorelease();
return pRet;
}
CC_SAFE_DELETE(pRet);
return NULL;
}
};
对应CPP:
bool CCParticleMeteor::initWithTotalParticles(unsigned int numberOfParticles)
{
if( CCParticleSystemQuad::initWithTotalParticles(numberOfParticles) )
{
// 设置为一直不断的发射。
m_fDuration = kCCParticleDurationInfinity;
// 设置为重力加速模式。
m_nEmitterMode = kCCParticleModeGravity;
// 设置重力加速度的值。
modeA.gravity = ccp(-200,200);
// 设置速度及其用于随机初始化的范围值。
modeA.speed = 15;
modeA.speedVar = 5;
// 设置半径变化值及其用于随机初始化的范围值。
modeA.radialAccel = 0;
modeA.radialAccelVar = 0;
// 设置切角变化值及其用于随机初始化的范围值。
modeA.tangentialAccel = 0;
modeA.tangentialAccelVar = 0;
// 设置起始角度及其用于随机初始化的范围值。
m_fAngle = 90;
m_fAngleVar = 360;
//设置发射器的位置及其用于随机初始化的范围值。
CCSize winSize = CCDirector::sharedDirector()->getWinSize();
this->setPosition(ccp(winSize.width/2, winSize.height/2));
m_tPosVar = CCPointZero;
// 粒子的生命值及其用于随机初始化的范围值。
m_fLife = 2;
m_fLifeVar = 1;
//起始大小及其用于随机初始化的范围值,终止大小指定与起始大小相同,即在更新时不变化。
m_fStartSize = 60.0f;
m_fStartSizeVar = 10.0f;
m_fEndSize = kCCParticleStartSizeEqualToEndSize;
// 发射器的发射速率。
m_fEmissionRate = m_uTotalParticles/m_fLife;
// 起始和结束的粒子颜色。
m_tStartColor.r = 0.2f;
m_tStartColor.g = 0.4f;
m_tStartColor.b = 0.7f;
m_tStartColor.a = 1.0f;
m_tStartColorVar.r = 0.0f;
m_tStartColorVar.g = 0.0f;
m_tStartColorVar.b = 0.2f;
m_tStartColorVar.a = 0.1f;
m_tEndColor.r = 0.0f;
m_tEndColor.g = 0.0f;
m_tEndColor.b = 0.0f;
m_tEndColor.a = 1.0f;
m_tEndColorVar.r = 0.0f;
m_tEndColorVar.g = 0.0f;
m_tEndColorVar.b = 0.0f;
m_tEndColorVar.a = 0.0f;
// 设置为加亮模式。
this->setBlendAdditive(true);
return true;
}
return false;
}
//由粒子系统基类派生出CCParticleSpiral,表现的是螺旋线
class CC_DLL CCParticleSpiral : public CCParticleSystemQuad
{
public:
//函数注释同上面的类,不再赘述。
CCParticleSpiral(){}
virtual ~CCParticleSpiral(){}
bool init(){ return initWithTotalParticles(500); }
virtual bool initWithTotalParticles(unsigned int numberOfParticles);
static CCParticleSpiral * node()
{
return create();
}
static CCParticleSpiral * create()
{
CCParticleSpiral *pRet = new CCParticleSpiral();
if (pRet->init())
{
pRet->autorelease();
return pRet;
}
CC_SAFE_DELETE(pRet);
return NULL;
}
};
对应CPP:
//创建相应数量的粒子。
bool CCParticleSpiral::initWithTotalParticles(unsigned int numberOfParticles)
{
//调用基类的相应函数。
if( CCParticleSystemQuad::initWithTotalParticles(numberOfParticles) )
{
// 设置为一直不断的发射。
m_fDuration = kCCParticleDurationInfinity;
// 设置为重力加速模式。
m_nEmitterMode = kCCParticleModeGravity;
// 设置重力加速度的值。
modeA.gravity = ccp(0,0);
// 设置速度及其用于随机初始化的范围值。
modeA.speed = 150;
modeA.speedVar = 0;
// 设置半径变化值及其用于随机初始化的范围值。
modeA.radialAccel = -380;
modeA.radialAccelVar = 0;
// 设置切角变化值及其用于随机初始化的范围值。
modeA.tangentialAccel = 45;
modeA.tangentialAccelVar = 0;
// 设置起始角度及其用于随机初始化的范围值。
m_fAngle = 90;
m_fAngleVar = 0;
//设置发射器的位置及其用于随机初始化的范围值。
CCSize winSize = CCDirector::sharedDirector()->getWinSize();
this->setPosition(ccp(winSize.width/2, winSize.height/2));
m_tPosVar = CCPointZero;
// 粒子的生命值及其用于随机初始化的范围值。
m_fLife = 12;
m_fLifeVar = 0;
//起始大小及其用于随机初始化的范围值,终止大小指定与起始大小相同,即在更新时不变化。
m_fStartSize = 20.0f;
m_fStartSizeVar = 0.0f;
m_fEndSize = kCCParticleStartSizeEqualToEndSize;
// 发射器的发射速率。
m_fEmissionRate = m_uTotalParticles/m_fLife;
// 起始和结束的粒子颜色。
m_tStartColor.r = 0.5f;
m_tStartColor.g = 0.5f;
m_tStartColor.b = 0.5f;
m_tStartColor.a = 1.0f;
m_tStartColorVar.r = 0.5f;
m_tStartColorVar.g = 0.5f;
m_tStartColorVar.b = 0.5f;
m_tStartColorVar.a = 0.0f;
m_tEndColor.r = 0.5f;
m_tEndColor.g = 0.5f;
m_tEndColor.b = 0.5f;
m_tEndColor.a = 1.0f;
m_tEndColorVar.r = 0.5f;
m_tEndColorVar.g = 0.5f;
m_tEndColorVar.b = 0.5f;
m_tEndColorVar.a = 0.0f;
// 设置不使用加亮模式。
this->setBlendAdditive(false);
return true;
}
return false;
}
//由粒子系统基类派生出CCParticleExplosion,表现的是爆炸
class CC_DLL CCParticleExplosion : public CCParticleSystemQuad
{
public:
//函数注释同上面的类,不再赘述。
CCParticleExplosion(){}
virtual ~CCParticleExplosion(){}
bool init(){ return initWithTotalParticles(700); }
virtual bool initWithTotalParticles(unsigned int numberOfParticles);
static CCParticleExplosion * node()
{
return create();
}
static CCParticleExplosion * create()
{
CCParticleExplosion *pRet = new CCParticleExplosion();
if (pRet->init())
{
pRet->autorelease();
return pRet;
}
CC_SAFE_DELETE(pRet);
return NULL;
}
};
对应CPP:
//创建相应数量的粒子。
bool CCParticleExplosion::initWithTotalParticles(unsigned int numberOfParticles)
{
//调用基类的相应函数。
if( CCParticleSystemQuad::initWithTotalParticles(numberOfParticles) )
{
// 设置为一直不断的发射。
m_fDuration = 0.1f;
// 设置为重力加速模式。
m_nEmitterMode = kCCParticleModeGravity;
// 设置重力加速度的值。
modeA.gravity = ccp(0,0);
// 设置速度及其用于随机初始化的范围值。
modeA.speed = 70;
modeA.speedVar = 40;
// 设置半径变化值及其用于随机初始化的范围值。
modeA.radialAccel = 0;
modeA.radialAccelVar = 0;
// 设置切角变化值及其用于随机初始化的范围值。
modeA.tangentialAccel = 0;
modeA.tangentialAccelVar = 0;
// 设置起始角度及其用于随机初始化的范围值。
m_fAngle = 90;
m_fAngleVar = 360;
//设置发射器的位置及其用于随机初始化的范围值。
CCSize winSize = CCDirector::sharedDirector()->getWinSize();
this->setPosition(ccp(winSize.width/2, winSize.height/2));
m_tPosVar = CCPointZero;
// 粒子的生命值及其用于随机初始化的范围值。
m_fLife = 5.0f;
m_fLifeVar = 2;
//起始大小及其用于随机初始化的范围值,终止大小指定与起始大小相同,即在更新时不变化。
m_fStartSize = 15.0f;
m_fStartSizeVar = 10.0f;
m_fEndSize = kCCParticleStartSizeEqualToEndSize;
// 发射器的发射速率。
m_fEmissionRate = m_uTotalParticles/m_fDuration;
// 起始和结束的粒子颜色。
m_tStartColor.r = 0.7f;
m_tStartColor.g = 0.1f;
m_tStartColor.b = 0.2f;
m_tStartColor.a = 1.0f;
m_tStartColorVar.r = 0.5f;
m_tStartColorVar.g = 0.5f;
m_tStartColorVar.b = 0.5f;
m_tStartColorVar.a = 0.0f;
m_tEndColor.r = 0.5f;
m_tEndColor.g = 0.5f;
m_tEndColor.b = 0.5f;
m_tEndColor.a = 0.0f;
m_tEndColorVar.r = 0.5f;
m_tEndColorVar.g = 0.5f;
m_tEndColorVar.b = 0.5f;
m_tEndColorVar.a = 0.0f;
// 设置不使用加亮模式。
this->setBlendAdditive(false);
return true;
}
return false;
}
//由粒子系统基类派生出CCParticleSmoke,表现的是烟雾
class CC_DLL CCParticleSmoke : public CCParticleSystemQuad
{
public:
//函数注释同上面的类,不再赘述。
CCParticleSmoke(){}
virtual ~CCParticleSmoke(){}
bool init(){ return initWithTotalParticles(200); }
virtual bool initWithTotalParticles(unsigned int numberOfParticles);
static CCParticleSmoke * node()
{
return create();
}
static CCParticleSmoke * create()
{
CCParticleSmoke *pRet = new CCParticleSmoke();
if (pRet->init())
{
pRet->autorelease();
return pRet;
}
CC_SAFE_DELETE(pRet);
return NULL;
}
};
对应CPP:
//创建相应数量的粒子。
bool CCParticleSmoke::initWithTotalParticles(unsigned int numberOfParticles)
{
//调用基类的相应函数。
if( CCParticleSystemQuad::initWithTotalParticles(numberOfParticles) )
{
// 设置为一直不断的发射。
m_fDuration = kCCParticleDurationInfinity;
// 设置为重力加速模式。
m_nEmitterMode = kCCParticleModeGravity;
// 设置重力加速度的值。
modeA.gravity = ccp(0,0);
// 设置半径变化值及其用于随机初始化的范围值。
modeA.radialAccel = 0;
modeA.radialAccelVar = 0;
// 设置速度及其用于随机初始化的范围值。
modeA.speed = 25;
modeA.speedVar = 10;
// 设置起始角度及其用于随机初始化的范围值。
m_fAngle = 90;
m_fAngleVar = 5;
//设置发射器的位置及其用于随机初始化的范围值。
CCSize winSize = CCDirector::sharedDirector()->getWinSize();
this->setPosition(ccp(winSize.width/2, 0));
m_tPosVar = ccp(20, 0);
// 粒子的生命值及其用于随机初始化的范围值。
m_fLife = 4;
m_fLifeVar = 1;
//起始大小及其用于随机初始化的范围值,终止大小指定与起始大小相同,即在更新时不变化。
m_fStartSize = 60.0f;
m_fStartSizeVar = 10.0f;
m_fEndSize = kCCParticleStartSizeEqualToEndSize;
// 发射器的发射速率。
m_fEmissionRate = m_uTotalParticles/m_fLife;
// 起始和结束的粒子颜色。
m_tStartColor.r = 0.8f;
m_tStartColor.g = 0.8f;
m_tStartColor.b = 0.8f;
m_tStartColor.a = 1.0f;
m_tStartColorVar.r = 0.02f;
m_tStartColorVar.g = 0.02f;
m_tStartColorVar.b = 0.02f;
m_tStartColorVar.a = 0.0f;
m_tEndColor.r = 0.0f;
m_tEndColor.g = 0.0f;
m_tEndColor.b = 0.0f;
m_tEndColor.a = 1.0f;
m_tEndColorVar.r = 0.0f;
m_tEndColorVar.g = 0.0f;
m_tEndColorVar.b = 0.0f;
m_tEndColorVar.a = 0.0f;
// 设置不使用加亮模式。
this->setBlendAdditive(false);
return true;
}
return false;
}
//由粒子系统基类派生出CCParticleSnow,表现的是雪
class CC_DLL CCParticleSnow : public CCParticleSystemQuad
{
public:
//函数注释同上面的类,不再赘述。
CCParticleSnow(){}
virtual ~CCParticleSnow(){}
bool init(){ return initWithTotalParticles(700); }
virtual bool initWithTotalParticles(unsigned int numberOfParticles);
static CCParticleSnow * node()
{
return create();
}
static CCParticleSnow * create()
{
CCParticleSnow *pRet = new CCParticleSnow();
if (pRet->init())
{
pRet->autorelease();
return pRet;
}
CC_SAFE_DELETE(pRet);
return NULL;
}
};
对应CPP:
//创建相应数量的粒子。
bool CCParticleSnow::initWithTotalParticles(unsigned int numberOfParticles)
{
//调用基类的相应函数。
if( CCParticleSystemQuad::initWithTotalParticles(numberOfParticles) )
{
// 设置为一直不断的发射。
m_fDuration = kCCParticleDurationInfinity;
// 设置为重力加速模式。
m_nEmitterMode = kCCParticleModeGravity;
// 设置重力加速度的值。
modeA.gravity = ccp(0,-1);
// 设置速度及其用于随机初始化的范围值。
modeA.speed = 5;
modeA.speedVar = 1;
// 设置半径变化值及其用于随机初始化的范围值。
modeA.radialAccel = 0;
modeA.radialAccelVar = 1;
// 设置切角变化值及其用于随机初始化的范围值。
modeA.tangentialAccel = 0;
modeA.tangentialAccelVar = 1;
//设置发射器的位置及其用于随机初始化的范围值。
CCSize winSize = CCDirector::sharedDirector()->getWinSize();
this->setPosition(ccp(winSize.width/2, winSize.height + 10));
m_tPosVar = ccp( winSize.width/2, 0 );
// 设置起始角度及其用于随机初始化的范围值。
m_fAngle = -90;
m_fAngleVar = 5;
// 粒子的生命值及其用于随机初始化的范围值。
m_fLife = 45;
m_fLifeVar = 15;
//起始大小及其用于随机初始化的范围值,终止大小指定与起始大小相同,即在更新时不变化。
m_fStartSize = 10.0f;
m_fStartSizeVar = 5.0f;
m_fEndSize = kCCParticleStartSizeEqualToEndSize;
// 发射器的发射速率。
m_fEmissionRate = 10;
// 起始和结束的粒子颜色。
m_tStartColor.r = 1.0f;
m_tStartColor.g = 1.0f;
m_tStartColor.b = 1.0f;
m_tStartColor.a = 1.0f;
m_tStartColorVar.r = 0.0f;
m_tStartColorVar.g = 0.0f;
m_tStartColorVar.b = 0.0f;
m_tStartColorVar.a = 0.0f;
m_tEndColor.r = 1.0f;
m_tEndColor.g = 1.0f;
m_tEndColor.b = 1.0f;
m_tEndColor.a = 0.0f;
m_tEndColorVar.r = 0.0f;
m_tEndColorVar.g = 0.0f;
m_tEndColorVar.b = 0.0f;
m_tEndColorVar.a = 0.0f;
// 设置不使用加亮模式。
this->setBlendAdditive(false);
return true;
}
return false;
}
//由粒子系统基类派生出CCParticleRain,表现的是雨
class CC_DLL CCParticleRain : public CCParticleSystemQuad
{
public:
//函数注释同上面的类,不再赘述。
CCParticleRain(){}
virtual ~CCParticleRain(){}
bool init(){ return initWithTotalParticles(1000); }
virtual bool initWithTotalParticles(unsigned int numberOfParticles);
static CCParticleRain * node()
{
return create();
}
static CCParticleRain * create()
{
CCParticleRain *pRet = new CCParticleRain();
if (pRet->init())
{
pRet->autorelease();
return pRet;
}
CC_SAFE_DELETE(pRet);
return NULL;
}
};
对应CPP:
//创建相应数量的粒子。
bool CCParticleRain::initWithTotalParticles(unsigned int numberOfParticles)
{
//调用基类的相应函数。
if( CCParticleSystemQuad::initWithTotalParticles(numberOfParticles) )
{
// 设置为一直不断的发射。
m_fDuration = kCCParticleDurationInfinity;
// 设置为重力加速模式。
m_nEmitterMode = kCCParticleModeGravity;
// 设置重力加速度的值。
modeA.gravity = ccp(10,-10);
// 设置半径变化值及其用于随机初始化的范围值。
modeA.radialAccel = 0;
modeA.radialAccelVar = 1;
// 设置切角变化值及其用于随机初始化的范围值。
modeA.tangentialAccel = 0;
modeA.tangentialAccelVar = 1;
// 设置速度及其用于随机初始化的范围值。
modeA.speed = 130;
modeA.speedVar = 30;
// 设置起始角度及其用于随机初始化的范围值。
m_fAngle = -90;
m_fAngleVar = 5;
//设置发射器的位置及其用于随机初始化的范围值。
CCSize winSize = CCDirector::sharedDirector()->getWinSize();
this->setPosition(ccp(winSize.width/2, winSize.height));
m_tPosVar = ccp( winSize.width/2, 0 );
// 粒子的生命值及其用于随机初始化的范围值。
m_fLife = 4.5f;
m_fLifeVar = 0;
//起始大小及其用于随机初始化的范围值,终止大小指定与起始大小相同,即在更新时不变化。
m_fStartSize = 4.0f;
m_fStartSizeVar = 2.0f;
m_fEndSize = kCCParticleStartSizeEqualToEndSize;
// 发射器的发射速率。
m_fEmissionRate = 20;
// 起始和结束的粒子颜色。
m_tStartColor.r = 0.7f;
m_tStartColor.g = 0.8f;
m_tStartColor.b = 1.0f;
m_tStartColor.a = 1.0f;
m_tStartColorVar.r = 0.0f;
m_tStartColorVar.g = 0.0f;
m_tStartColorVar.b = 0.0f;
m_tStartColorVar.a = 0.0f;
m_tEndColor.r = 0.7f;
m_tEndColor.g = 0.8f;
m_tEndColor.b = 1.0f;
m_tEndColor.a = 0.5f;
m_tEndColorVar.r = 0.0f;
m_tEndColorVar.g = 0.0f;
m_tEndColorVar.b = 0.0f;
m_tEndColorVar.a = 0.0f;
// 设置不使用加亮模式。
this->setBlendAdditive(false);
return true;
}
return false;
}
CCParticleExample.h中都是典型的粒子系统的表现类。我们可以清楚的看到,粒子系统的基类已经将这些典型的粒子系统所需要的属性一一包含,想要使用粒子系统摸拟自然现象,所需要做的就是通过对其具有的粒子属性进行相应的设置,仅此而已。
在ParticleTest中,共有42个粒子系统的展示,它们均是基于ParticleDemo这个类进行派生实现的, ParticleDemo是基于CCLayerColor所派生的一个类,实现了对于粒子系统演示的管理控制,下面我们来看一下头文件:
//粒子系统演示所用的场景
class ParticleTestScene : public TestScene
{
public:
//运行当前场景
virtual void runThisTest();
};
//可见本实例中的粒子系统演示,是以层的形式来表现的。
class ParticleDemo : public CCLayerColor
{
protected:
//每一个粒子系统演示中,都有一个粒子系统的指针。
CCParticleSystem* m_emitter;
//背景图精灵
CCSprite* m_background;
public:
//析构
~ParticleDemo(void);
//加载当前粒子系统演示层时调用的函数。
virtual void onEnter(void);
//取得标题和幅标题。
virtual std::string title();
virtual std::string subtitle();
//响应当前演示层的一些菜单触发事件,以便演示的控制。
//重新演示当前的粒子系统。
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);
//更新时的处理
virtual void update(float dt);
//初始化粒子发射器的位置。
void setEmitterPosition();
};
//演示表现烟火的粒子系统,由基类ParticleDemo派生。
class DemoFirework : public ParticleDemo
{
public:
virtual void onEnter();
virtual std::string title();
};
//演示表现火焰的粒子系统,由基类ParticleDemo派生。
class DemoFire : public ParticleDemo
{
public:
virtual void onEnter();
virtual std::string title();
};
后面雷同不再赘述…
看上面的代码,很容易理解,每个粒子系统的演示都是一个层,创建一个场景用来管理这些演示层。在CPP中,我们可以找到以下函数的实现。
//场景运行时调用的函数处理。
void ParticleTestScene::runThisTest()
{
//创建下一个粒子系统的演示层,放入当前场景。
addChild(nextParticleAction());
//调用设备的更新场景函数,运行当前场景。
CCDirector::sharedDirector()->replaceScene(this);
}
CPP中有三个函数,分别是运行下一个粒子系统的演示,运行上一个粒子系统的演示,重新进行当前粒子系统的演示。
//下一个粒子系统的演示
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;
}
可以看到,就如TestCpp类似的管理方案,所有的演示都会放在createParticleLayer中,通过索引来进行相应的控制管理。
//没错,就是这样。
CCLayer* createParticleLayer(int nIndex)
{
switch(nIndex)
{
case 0: return new ParticleReorder();
case 1: return new ParticleBatchHybrid();
case 2: return new ParticleBatchMultipleEmitters();
case 3: return new DemoFlower();
case 4: return new DemoGalaxy();
case 5: return new DemoFirework();
case 6: return new DemoSpiral();
case 7: return new DemoSun();
case 8: return new DemoMeteor();
case 9: return new DemoFire();
case 10: return new DemoSmoke();
case 11: return new DemoExplosion();
case 12: return new DemoSnow();
case 13: return new DemoRain();
case 14: return new DemoBigFlower();
case 15: return new DemoRotFlower();
case 16: return new DemoModernArt();
case 17: return new DemoRing();
case 18: return new ParallaxParticle();
case 19: return new DemoParticleFromFile("BoilingFoam");
case 20: return new DemoParticleFromFile("BurstPipe");
case 21: return new DemoParticleFromFile("Comet");
case 22: return new DemoParticleFromFile("debian");
case 23: return new DemoParticleFromFile("ExplodingRing");
case 24: return new DemoParticleFromFile("LavaFlow");
case 25: return new DemoParticleFromFile("SpinningPeas");
case 26: return new DemoParticleFromFile("SpookyPeas");
case 27: return new DemoParticleFromFile("Upsidedown");
case 28: return new DemoParticleFromFile("Flower");
case 29: return new DemoParticleFromFile("Spiral");
case 30: return new DemoParticleFromFile("Galaxy");
case 31: return new DemoParticleFromFile("Phoenix");
case 32: return new RadiusMode1();
case 33: return new RadiusMode2();
case 34: return new Issue704();
case 35: return new Issue870();
case 36: return new Issue1201();
// v1.1 tests
case 37: return new MultipleParticleSystems();
case 38: return new MultipleParticleSystemsBatched();
case 39: return new AddAndDeleteParticleSystems();
case 40: return new ReorderParticleSystems();
case 41: return new PremultipliedAlphaTest();
case 42: return new PremultipliedAlphaTest2();
default:
break;
}
return NULL;
}
然后是演示粒子效果所用的层的基类ParticleDemo:
//析构函数。
ParticleDemo::~ParticleDemo(void)
{
//释放粒子系统。
CC_SAFE_RELEASE(m_emitter);
}
//加载当前层时调用的函数。
void ParticleDemo::onEnter(void)
{
//调用基类的相应函数。
CCLayer::onEnter();
//初始化背景色。
initWithColor( ccc4(127,127,127,255) );
//粒子系统置空。
m_emitter = NULL;
//设置接受触屏消息。
setTouchEnabled( true );
//取得屏幕大小。
CCSize s = CCDirector::sharedDirector()->getWinSize();
//创建主标题文字标签并放到当前层中的相应位置。
CCLabelTTF* label = CCLabelTTF::create(title().c_str(), "Arial", 28);
addChild(label, 100, 1000);
label->setPosition( CCPointMake(s.width/2, s.height-50) );
//创建幅标题文字标签并放到当前层中的相应位置。
CCLabelTTF *sub = CCLabelTTF::create(subtitle().c_str(), "Arial", 16);
addChild(sub, 100);
sub->setPosition(CCPointMake(s.width/2, s.height-80));
//创建菜单按钮用于控制演示。
CCMenuItemImage* item1 = CCMenuItemImage::create(s_pPathB1, s_pPathB2, this, menu_selector(ParticleDemo::backCallback) );
CCMenuItemImage* item2 = CCMenuItemImage::create(s_pPathR1, s_pPathR2, this, menu_selector(ParticleDemo::restartCallback) );
CCMenuItemImage* item3 = CCMenuItemImage::create(s_pPathF1, s_pPathF2, this, menu_selector(ParticleDemo::nextCallback) );
//创建一个菜单按钮用于切换运动时的受影响类型,响应函数为ParticleDemo::toggleCallback。
CCMenuItemToggle* item4 = CCMenuItemToggle::createWithTarget(this,
menu_selector(ParticleDemo::toggleCallback),
CCMenuItemFont::create( "Free Movement" ),
CCMenuItemFont::create( "Relative Movement" ),
CCMenuItemFont::create( "Grouped Movement" ),
NULL );
//创建菜单。
CCMenu *menu = CCMenu::create(item1, item2, item3, item4, NULL);
//设置各菜单按钮的位置。
menu->setPosition( CCPointZero );
item1->setPosition( ccp( s.width/2 - item2->getContentSize().width*2, item2->getContentSize().height/2) );
item2->setPosition( ccp( s.width/2, item2->getContentSize().height/2) );
item3->setPosition( ccp( s.width/2 + item2->getContentSize().width*2, item2->getContentSize().height/2) );
item4->setPosition( ccp( 0, 100) );
item4->setAnchorPoint( ccp(0,0) );
//将菜单放入当前层中。
addChild( menu, 100 );
//创建一个文字标签显示FPS
CCLabelAtlas* labelAtlas = CCLabelAtlas::create("0000", "fps_images.png", 12, 32, '.');
addChild(labelAtlas, 100, kTagParticleCount);
labelAtlas->setPosition(ccp(s.width-66,50));
//创建背景图精灵并放在当前层的相应位置。
m_background = CCSprite::create(s_back3);
addChild(m_background, 5);
m_background->setPosition( ccp(s.width/2, s.height-180) );
//创建移动动画以及反向动画。
CCActionInterval* move = CCMoveBy::create(4, ccp(300,0) );
CCActionInterval* move_back = move->reverse();
//将两个动画放到一个动画序列中。
CCFiniteTimeAction* seq = CCSequence::create( move, move_back, NULL);
//让背景图精录无限循环执行这个动画序列。
m_background->runAction( CCRepeatForever::create((CCActionInterval*)seq) );
//让当前层响应Update函数。
scheduleUpdate();
//取得主标题并设置显示文字串。
CCLabelTTF* pLabel = (CCLabelTTF*)(this->getChildByTag(1000));
pLabel->setString(title().c_str());
}
//取得主标题。
std::string ParticleDemo::title()
{
return "No title";
}
//取得幅标题。
std::string ParticleDemo::subtitle()
{
return "No titile";
}
//开启触屏消息响应。
void ParticleDemo::registerWithTouchDispatcher()
{
CCDirector* pDirector = CCDirector::sharedDirector();
pDirector->getTouchDispatcher()->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->getLocation();
//创建临时变量取得背景精灵的位置。
CCPoint pos = CCPointZero;
if (m_background)
{
pos = m_background->convertToWorldSpace(CCPointZero);
}
//如果粒子系统发射器有效,设置其位置为触点位置减去背景精零的零点世界位置(即当前层的左下角世界位置),因为粒子系统是当前层的子结点,所以ccpSub(location, pos)结果即为触点与当前层的相对位置。。
if (m_emitter != NULL)
{
m_emitter->setPosition( ccpSub(location, pos) );
}
}
//更新函数。
void ParticleDemo::update(float dt)
{
//显示粒子的数量。
if (m_emitter)
{
CCLabelAtlas* atlas = (CCLabelAtlas*)getChildByTag(kTagParticleCount);
char str[5] = {0};
sprintf(str, "%04d", m_emitter->getParticleCount());
atlas->setString(str);
}
}
//点击切换粒子系统的运动影响方式时的响应函数。
void ParticleDemo::toggleCallback(CCObject* pSender)
{
//根据当前粒子系统运动影响方式类型,切换到下一种枚举的运动影响方式类型。
if (m_emitter != NULL)
{
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)
{
if (m_emitter != NULL)
{
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();
if (m_emitter != NULL)
{
m_emitter->setPosition( CCPointMake(s.width / 2, s.height / 2) );
}
}
OK,这个基类搞定后,下面我们来一一把本演示DEMO中的演示实例进行解释:
(1) ParticleReorder
描述:
粒子系统的排序。每秒对粒子系统进行一个不同的显示顺序的设定。
截图:

源码解析:
//当前层加载时的处理。
void ParticleReorder::onEnter()
{
//调用基类的相应初始化函数。
ParticleDemo::onEnter();
//
m_nOrder = 0;
//设置层背景色为黑色。
setColor(ccBLACK);
//将背景精灵移除并置空
removeChild(m_background, true);
m_background = NULL;
//从SmallSun.plist中加载创建一个粒子系统。
CCParticleSystem* ignore = CCParticleSystemQuad::create("Particles/SmallSun.plist");
//创建第一个父结点。
CCNode *parent1 = CCNode::create();
//由粒子系统取出的纹理对象创建一个粒子批次结点做为第二个父结点。
CCNode *parent2 = CCParticleBatchNode::createWithTexture(ignore->getTexture());
//粒子系统不调用Update函数。
ignore->unscheduleUpdate();
//
for( unsigned int i=0; i<2;i++)
{
//循环两次,第一次parent取parent1,第二次取parent2。
CCNode *parent = ( i==0 ? parent1 : parent2 );
//由SmallSun.plist文件创建第一个粒子系统。
CCParticleSystemQuad *emitter1 = CCParticleSystemQuad::create("Particles/SmallSun.plist");
//设置粒子系统的粒子的起始颜色。
emitter1->setStartColor(ccc4f(1,0,0,1));
//设置粒子系统不使用加亮模式。
emitter1->setBlendAdditive(false);
//由SmallSun.plist文件创建第二个粒子系统。
CCParticleSystemQuad *emitter2 = CCParticleSystemQuad::create("Particles/SmallSun.plist");
//设置粒子系统的粒子的起始颜色。
emitter2->setStartColor(ccc4f(0,1,0,1));
//设置粒子系统不使用加亮模式。
emitter2->setBlendAdditive(false);
//由SmallSun.plist文件创建第三个粒子系统。
CCParticleSystemQuad *emitter3 = CCParticleSystemQuad::create("Particles/SmallSun.plist");
//设置粒子系统的粒子的起始颜色。
emitter3->setStartColor(ccc4f(0,0,1,1));
//设置粒子系统不使用加亮模式。
emitter3->setBlendAdditive(false);
//取得屏幕大小。
CCSize s = CCDirector::sharedDirector()->getWinSize();
//根据遍历计数器值设定一个位置影响参数。
int neg = (i==0 ? 1 : -1 );
//设置三个粒子系统的位置。
emitter1->setPosition(ccp( s.width/2-30, s.height/2+60*neg));
emitter2->setPosition(ccp( s.width/2, s.height/2+60*neg));
emitter3->setPosition(ccp( s.width/2+30, s.height/2+60*neg));
//将三个粒子系统放入相应的父结点。
parent->addChild(emitter1, 0, 1);
parent->addChild(emitter2, 0, 2);
parent->addChild(emitter3, 0, 3);
//将父结点做为子结点放入当前层。
addChild(parent, 10, 1000+i);
}
//定时器每秒响应一次ParticleReorder::reorderParticles函数。
schedule(schedule_selector(ParticleReorder::reorderParticles), 1.0f);
}
//取得标题。
std::string ParticleReorder::title()
{
return "Reordering particles";
}
//取得幅标题。
std::string ParticleReorder::subtitle()
{
return "Reordering particles with and without batches batches";
}
//每秒响应的回调函数。
void ParticleReorder::reorderParticles(float dt)
{
for( int i=0; i<2;i++) {
//取得不同的粒子系统父结点。
CCNode *parent = getChildByTag(1000+i);
//取得相应的粒子系统。
CCNode *child1 = parent->getChildByTag(1);
CCNode *child2 = parent->getChildByTag(2);
CCNode *child3 = parent->getChildByTag(3);
//对3取模后设置不同的排序。
if( m_nOrder % 3 == 0 ) {
parent->reorderChild(child1, 1);
parent->reorderChild(child2, 2);
parent->reorderChild(child3, 3);
} else if (m_nOrder % 3 == 1 ) {
parent->reorderChild(child1, 3);
parent->reorderChild(child2, 1);
parent->reorderChild(child3, 2);
} else if (m_nOrder % 3 == 2 ) {
parent->reorderChild(child1, 2);
parent->reorderChild(child2, 3);
parent->reorderChild(child3, 1);
}
}
m_nOrder++;
}
(2) ParticleBatchHybrid
描述:
表现使用批次结点
截图:

源码分析:
//加载当前层时的处理。
void ParticleBatchHybrid::onEnter()
{
//调用基类的相应函数。
ParticleDemo::onEnter();
//设置背景色为黑色。
setColor(ccBLACK);
//删除背景精灵并置空。
removeChild(m_background, true);
m_background = NULL;
//由LavaFlow.plist文件创建粒子系统。
m_emitter = CCParticleSystemQuad::create("Particles/LavaFlow.plist");
//占用此粒子系统,对其引用计数器加一操作。
m_emitter->retain();
//由粒子系统的纹理对象创建一个粒子批次结点。
CCParticleBatchNode *batch = CCParticleBatchNode::createWithTexture(m_emitter->getTexture());
//将粒子系统加入到粒子批次结点中。
batch->addChild(m_emitter);
//将粒子批次结点加入到当前层中。
addChild(batch, 10);
//每2秒调用一次ParticleBatchHybrid::switchRender函数切换使用批次结点。
schedule(schedule_selector(ParticleBatchHybrid::switchRender), 2.0f);
//创建一个结点做为子结点。
CCNode *node = CCNode::create();
addChild(node);
//第一父结点设为批次结点。
m_pParent1 = batch;
//第二父结点设为上面的子结点。
m_pParent2 = node;
}
//切换使用或不使用批次结点的函数。
void ParticleBatchHybrid::switchRender(float dt)
{
//取得是否使用了批次结点。
bool usingBatch = ( m_emitter->getBatchNode() != NULL );
//从父结点中移除。
m_emitter->removeFromParentAndCleanup(false);
//根据上面的usingBatch来设置不同的父结点,这样就可以让粒子系统进行来回切换了。
CCNode *newParent = (usingBatch ? m_pParent2 : m_pParent1 );
//将粒子系统放入父结点中。
newParent->addChild(m_emitter);
//打印信息
CCLog("Particle: Using new parent: %s", usingBatch ? "CCNode" : "CCParticleBatchNode");
}
//取得标题。
std::string ParticleBatchHybrid::title()
{
return "Paticle Batch";
}
//取得幅标题。
std::string ParticleBatchHybrid::subtitle()
{
return "Hybrid: batched and non batched every 2 seconds";
}
(3) ParticleBatchMultipleEmitters
描述:
多个粒子系统应用一个批次结点。
截图:

源码分析:
//加载当前层的处理。
void ParticleBatchMultipleEmitters::onEnter()
{
//调用基类的相应函数。
ParticleDemo::onEnter();
//设置背景色为黑色。
setColor(ccBLACK);
//移除背景精灵并将指针置空。
removeChild(m_background, true);
m_background = NULL;
//创建三个粒子系统,分别设置不同的初始颜色。
CCParticleSystemQuad *emitter1 = CCParticleSystemQuad::create("Particles/LavaFlow.plist");
emitter1->setStartColor(ccc4f(1,0,0,1));
CCParticleSystemQuad *emitter2 = CCParticleSystemQuad::create("Particles/LavaFlow.plist");
emitter2->setStartColor(ccc4f(0,1,0,1));
CCParticleSystemQuad *emitter3 = CCParticleSystemQuad::create("Particles/LavaFlow.plist");
emitter3->setStartColor(ccc4f(0,0,1,1));
//取得屏幕大小
CCSize s = CCDirector::sharedDirector()->getWinSize();
//设置粒子系统的位置。
emitter1->setPosition(ccp( s.width/1.25f, s.height/1.25f));
emitter2->setPosition(ccp( s.width/2, s.height/2));
emitter3->setPosition(ccp( s.width/4, s.height/4));
//由粒子系统的纹理创建相应的批次结点。
CCParticleBatchNode *batch = CCParticleBatchNode::createWithTexture(emitter1->getTexture());
//将粒子系统都放入批次结点中。
batch->addChild(emitter1, 0);
batch->addChild(emitter2, 0);
batch->addChild(emitter3, 0);
//将批次结点放入当前层。
addChild(batch, 10);
}
//标题。
std::string ParticleBatchMultipleEmitters::title()
{
return "Paticle Batch";
}
//幅标题。
std::string ParticleBatchMultipleEmitters::subtitle()
{
return "Multiple emitters. One Batch";
}
(4) DemoFlower:
描述:
花?不像,倒不如说是星光闪烁。
截图:

源码分析:
//加载当前层时的处理
void DemoFlower::onEnter()
{
//调用基类的相应函数。
ParticleDemo::onEnter();
//创建粒子系统。
m_emitter = CCParticleFlower::create();
m_emitter->retain();
//将粒子系统放入背景精灵结点下。
m_background->addChild(m_emitter, 10);
//设置粒子系统使用星星的纹理。
m_emitter->setTexture( CCTextureCache::sharedTextureCache()->addImage(s_stars1) );
//调用基类的相应函数将粒子发射器置于屏幕中央。
setEmitterPosition();
}
//取得标题。
std::string DemoFlower::title()
{
return "ParticleFlower";
}
注:这里星星的纹理为:

这是一个PNG格式的ALPHA渐变图,本身色彩就是由白到黑的一个亮度变化。通过粒子的顶点着色就能出现五彩缤纷的星光了。
(5) DemoGalaxy
描述:
星系。
截图:
源码分析:
//加载当前层时的处理。
void DemoGalaxy::onEnter()
{
//调用基类的相应函数。
ParticleDemo::onEnter();
//创建一个CCParticleGalaxy类的实例。
m_emitter = CCParticleGalaxy::create();
//占用,则对其使用计数器加一。
m_emitter->retain();
//将粒子系统放入背景结点下。
m_background->addChild(m_emitter, 10);
//加载一个火焰的图片,设置为粒子系统的纹理。
m_emitter->setTexture( CCTextureCache::sharedTextureCache()->addImage(s_fire) );
//调用基类的相应函数,设置粒子系统的位置居于屏幕中央。
setEmitterPosition();
}
//取得标题
std::string DemoGalaxy::title()
{
return "ParticleGalaxy";
}
注:这里火焰的纹理为:

这是一个PNG格式的ALPHA渐变图,本身色彩就是由白到黑的一个亮度变化。通过粒子的顶点着色就能出现五彩的火火焰了。
(6) DemoFirework
描述:
烟火的摸拟
截图:

源码解析:
//加载当前层时的处理。
void DemoFirework::onEnter()
{
//调用基类的相应函数。
ParticleDemo::onEnter();
//创建一个CCParticleFireworks类的实例。
m_emitter = CCParticleFireworks::create();
//对其占用,故引用计数器加一操作。
m_emitter->retain();
//将粒子系统加入到背景精灵结点之下
m_background->addChild(m_emitter, 10);
//加载星星的图片做为粒子的纹理。
m_emitter->setTexture( CCTextureCache::sharedTextureCache()->addImage(s_stars1) );
//设置粒子系统居中。
setEmitterPosition();
}
//取得标题。
std::string DemoFirework::title()
{
return "ParticleFireworks";
}
(7) DemoSpiral
描述:
螺旋线的摸拟
截图:

源码解析:
//加载当前层的处理。
void DemoSpiral::onEnter()
{
//调用基类的相应函数。
ParticleDemo::onEnter();
//创建一个CCParticleSpiral类的实例。
m_emitter = CCParticleSpiral::create();
//占用,对其引用计数器加一。
m_emitter->retain();
//将粒子系统放在精灵背景结点之下。
m_background->addChild(m_emitter, 10);
//加载火焰图片设置为粒子系统所用的纹理。
m_emitter->setTexture( CCTextureCache::sharedTextureCache()->addImage(s_fire) );
//设置粒子系统发射器的位置居于屏幕中央。
setEmitterPosition();
}
//取得标题。
std::string DemoSpiral::title()
{
return "ParticleSpiral";
}
(8) DemoSun
描述:
太阳的摸拟
截图:

源码解析:
//加载当前层时的处理。
void DemoSun::onEnter()
{
//调用基类的相应函数。
ParticleDemo::onEnter();
//创建一个CCParticleSun类的实例
m_emitter = CCParticleSun::create();
//占用粒子系统,对其引用计数器加一。
m_emitter->retain();
//将粒子系统放在背景精灵结点之下。
m_background->addChild(m_emitter, 10);
//加载火焰图片做为粒子系统的纹理。
m_emitter->setTexture( CCTextureCache::sharedTextureCache()->addImage(s_fire) );
//设置粒子系统发射器的位置居于屏幕中央。
setEmitterPosition();
}
//取得标题文字。
std::string DemoSun::title()
{
return "ParticleSun";
}
(9) DemoMeteor:
描述:
流星的摸拟
截图:
源码解析:
//加载当前层的处理。
void DemoMeteor::onEnter()
{
//调用基类的相应函数。
ParticleDemo::onEnter();
//创建一个CCParticleMeteor类的实例。
m_emitter = CCParticleMeteor::create();
//占用它,对它的引用计数器加一。
m_emitter->retain();
//将粒子系统加入到当前背景精灵节点之下。
m_background->addChild(m_emitter, 10);
//加载火焰的图片做为粒子系统的纹理。
m_emitter->setTexture( CCTextureCache::sharedTextureCache()->addImage(s_fire) );
//设置粒子系统居于屏幕中央。
setEmitterPosition();
}
//取得标题。
std::string DemoMeteor::title()
{
return "ParticleMeteor";
}
(10) DemoFire
描述:
火焰的摸拟
截图:

源码解析:
void DemoFire::onEnter()
{
//调用基类的相应函数。
ParticleDemo::onEnter();
//创建一个CCParticleFire类的实例。
m_emitter = CCParticleFire::create();
//占用它,对其引用计数器加一。
m_emitter->retain();
//将粒子系统放在背景精灵结点之下。
m_background->addChild(m_emitter, 10);
//加载一个火焰图片做为粒子系统的纹理。
m_emitter->setTexture( CCTextureCache::sharedTextureCache()->addImage(s_fire) );//.pvr");
//取得粒子系统的位置。设置高度在100。
CCPoint p = m_emitter->getPosition();
m_emitter->setPosition( CCPointMake(p.x, 100) );
//将粒子系统居中。
setEmitterPosition();
}
//取得标题。
std::string DemoFire::title()
{
return "ParticleFire";
}
(11) DemoSmoke
描述:
烟雾的摸拟
截图:

源码解析:
//加载当前层时的处理。
void DemoSmoke::onEnter()
{
//调用基类的相应函数。
ParticleDemo::onEnter();
//创建一个CCParticleSmoke的实例。
m_emitter = CCParticleSmoke::create();
//占用它,对它的引用计数器加一。
m_emitter->retain();
//将粒子系统放入到背景精灵结点之下。
m_background->addChild(m_emitter, 10);
//加载一个火焰的图片设置为粒子系统的纹理。
m_emitter->setTexture( CCTextureCache::sharedTextureCache()->addImage(s_fire) );
//取得粒子系统的位置并限制其高度在100。
CCPoint p = m_emitter->getPosition();
m_emitter->setPosition( CCPointMake( p.x, 100) );
//将粒子系统居于屏幕中央。
setEmitterPosition();
}
//取得粒子系统的标题。
std::string DemoSmoke::title()
{
return "ParticleSmoke";
}
(12) DemoExplosion
描述:
爆炸的摸拟
截图:

源码解析:
//加载当前层时的处理。
void DemoExplosion::onEnter()
{
//调用基类的相应函数。
ParticleDemo::onEnter();
//创建一个CCParticleExplosion类的实例。
m_emitter = CCParticleExplosion::create();
//占用实例,对其引用计数器加一。
m_emitter->retain();
//将粒子发射器放到背景精灵结点之下。
m_background->addChild(m_emitter, 10);
//加载星星图片做为粒子系统的纹理。
m_emitter->setTexture( CCTextureCache::sharedTextureCache()->addImage(s_stars1) );
//设置粒子释放完成后自动移除并释放,这样的话,不会连续不断的发射粒子。
m_emitter->setAutoRemoveOnFinish(true);
//设置粒子发射器的位置居于屏幕中央。
setEmitterPosition();
}
//取得标题。
std::string DemoExplosion::title()
{
return "ParticleExplosion";
}
(13) DemoSnow
描述:
雪的摸拟
截图:

源码解析:
//加载当前层时的处理。
void DemoSnow::onEnter()
{
//先调用基类的相应函数。
ParticleDemo::onEnter();
//创建一个CCParticleSnow的实例。
m_emitter = CCParticleSnow::create();
//占用它,对它的引用计数器加一。
m_emitter->retain();
//将其放在背景精灵结点之下。
m_background->addChild(m_emitter, 10);
//取得粒子系统的位置,设置为当前位置往下移110像素。具体位置请参看前面CCParticleExample中CCParticleSnow的initWithTotalParticles函数。
CCPoint p = m_emitter->getPosition();
m_emitter->setPosition( CCPointMake( p.x, p.y-110) );
//设置生命值为3
m_emitter->setLife(3);
//设置生命随机加值范围为1,也就是生命值在2~4间初始化。
m_emitter->setLifeVar(1);
// 设置重力加速度值。
m_emitter->setGravity(CCPointMake(0,-10));
// 设置初始速度值及随机加值范围,生命值在100~160间初始化。
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";
}
(14) DemoRain:
描述:
雨的摸拟
截图:

源码解析:
//当前层加载时的处理
void DemoRain::onEnter()
{
//调用基类的相应函数。
ParticleDemo::onEnter();
//创建一个CCParticleRain的实例,
m_emitter = CCParticleRain::create();
//占用,对其引用计数器加一。
m_emitter->retain();
//将粒子系统加入到背景精灵结点下。
m_background->addChild(m_emitter, 10);
//取得粒子系统的位置,设置为当前位置往下移110像素。具体位置请参看前面CCParticleExample中CCParticleRain的initWithTotalParticles函数。
CCPoint p = m_emitter->getPosition();
m_emitter->setPosition( CCPointMake( p.x, p.y-100) );
//设置粒子的生命值为4
m_emitter->setLife(4);
//加载火焰图片做为当前粒子系统的纹理
m_emitter->setTexture( CCTextureCache::sharedTextureCache()->addImage(s_fire) );
//设置粒子系统发射器的位置居于屏幕中央。
setEmitterPosition();
}
//取得标题。
std::string DemoRain::title()
{
return "ParticleRain";
}
(15) DemoBigFlower
描述:
大颗星光闪烁的摸拟
截图:

源码解析:
//加载当前层时的处理。
void DemoBigFlower::onEnter()
{
//调用基类的相应函数。
ParticleDemo::onEnter();
//创建一个CCParticleSystemQuad的实例。
m_emitter = new CCParticleSystemQuad();
//创建50个粒子。
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);
//设置重力加速度。
m_emitter->setGravity(CCPointZero);
// 设置初始角度及角度初始随机变化范围
m_emitter->setAngle(90);
m_emitter->setAngleVar(360);
// 设置初始速度及速度初始随机变化范围
m_emitter->setSpeed(160);
m_emitter->setSpeedVar(20);
//设置初始半径长度及半径长度初始随机变化范围
m_emitter->setRadialAccel(-120);
m_emitter->setRadialAccelVar(0);
//设置初始切角度及切角度初始随机变化范围
m_emitter->setTangentialAccel(30);
m_emitter->setTangentialAccelVar(0);
//设置初始位置及切位置初始随机变化范围
m_emitter->setPosition( CCPointMake(160,240) );
m_emitter->setPosVar(CCPointZero);
//设置初始生命值及生命值随机变化范围
m_emitter->setLife(4);
m_emitter->setLifeVar(1);
// 设置粒子起始的旋转角度和随机的旋转角度加值范围,这里设置为不旋转。
m_emitter->setStartSpin(0);
m_emitter->setStartSizeVar(0);
m_emitter->setEndSpin(0);
m_emitter->setEndSpinVar(0);
// 设置粒子的起始,结束色彩值和其相应的随机变化范围。
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);
// 设置粒子的大小值及其随机变化范围。
m_emitter->setStartSize(80.0f);
m_emitter->setStartSizeVar(40.0f);
//结束大小设为宏kParticleStartSizeEqualToEndSize,代表大小不变化。
m_emitter->setEndSize(kParticleStartSizeEqualToEndSize);
// 设置粒子系统的发射速率。
m_emitter->setEmissionRate(m_emitter->getTotalParticles()/m_emitter->getLife());
// 设置为加亮模式。
m_emitter->setBlendAdditive(true);
//设置粒子系统发射器的位置居于屏幕中央。
setEmitterPosition();
}
//取得标题。
std::string DemoBigFlower::title()
{
return "ParticleBigFlower";
}
(16) DemoRotFlower
描述:
旋转的星光的摸拟
截图:

源码解析:
void DemoRotFlower::onEnter()
{
//调用基类的相应函数。
ParticleDemo::onEnter();
//创建一个粒子系统的实例。
m_emitter = new CCParticleSystemQuad();
//创建300个粒子。
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) );
// 设置粒子系统一直进行update
m_emitter->setDuration(-1);
// 设置无重力加速度。
m_emitter->setGravity(CCPointZero);
// 设置起始的角度以及初始化时的随机角度加值范围。
m_emitter->setAngle(90);
m_emitter->setAngleVar(360);
//设置起始的速度以及初始化时的随机速度加值范围。
m_emitter->setSpeed(160);
m_emitter->setSpeedVar(20);
//设置起始的半径以及初始化时的随机半径加值范围。
m_emitter->setRadialAccel(-120);
m_emitter->setRadialAccelVar(0);
//设置起始的切角以及初始化时的随机切角加值范围。
m_emitter->setTangentialAccel(30);
m_emitter->setTangentialAccelVar(0);
//设置起始的位置以及初始化时的随机位置加值范围。
m_emitter->setPosition( CCPointMake(160,240) );
m_emitter->setPosVar(CCPointZero);
//设置起始的生命值以及初始化时的随机生命值加值范围。
m_emitter->setLife(3);
m_emitter->setLifeVar(1);
//设置起始的旋转角度以及初始化时的随机旋转角度加值范围。
m_emitter->setStartSpin(0);
m_emitter->setStartSpinVar(0);
m_emitter->setEndSpin(0);
m_emitter->setEndSpinVar(2000);
//设置起始的颜色以及初始化时起始颜色的随机颜色加值范围。
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);
//设置起始的粒子大小以及初始化时起始粒子大小的随机颜色加值范围。
m_emitter->setStartSize(30.0f);
m_emitter->setStartSizeVar(00.0f);
//设置在Update过程中大小不变。
m_emitter->setEndSize(kParticleStartSizeEqualToEndSize);
// 设置粒子系统发射速率
m_emitter->setEmissionRate(m_emitter->getTotalParticles()/m_emitter->getLife());
// 设置不使用加亮模式。
m_emitter->setBlendAdditive(false);
//设置粒子系统发射器的位置居于屏幕中央。
setEmitterPosition();
}
//取得标题。
std::string DemoRotFlower::title()
{
return "ParticleRotFlower";
}
(17) DemoModernArt
描述:
大小的变化
截图:

源码解析:
//加载本层的源码
void DemoModernArt::onEnter()
{
//调用基类的相应函数。
ParticleDemo::onEnter();
//创建一个粒子系统。
glDrawArrays(GL_POINTS, 0, m_uParticleIdx);
// m_emitter = new CCParticleSystemPoint();
m_emitter = new CCParticleSystemQuad();
//创建1000个粒子
m_emitter->initWithTotalParticles(1000);
//m_emitter->autorelease();
//将粒子系统放入到背景精灵的结点下。
m_background->addChild(m_emitter, 10);
m_emitter->release();
//取得屏幕大小。
CCSize s = CCDirector::sharedDirector()->getWinSize();
//设置一直更新粒子系统。
m_emitter->setDuration(-1);
//设置重力加速度。
m_emitter->setGravity(CCPointMake(0,0));
//设置角度初始值及角度初始值的随机加值范围 。
m_emitter->setAngle(0);
m_emitter->setAngleVar(360);
//设置半径初始值及半径初始值的随机加值范围。
m_emitter->setRadialAccel(70);
m_emitter->setRadialAccelVar(10);
//设置切角初始值及切角初始值的随机加值范围。
m_emitter->setTangentialAccel(80);
m_emitter->setTangentialAccelVar(0);
//设置速度初始值及速度初始值的随机加值范围。
m_emitter->setSpeed(50);
m_emitter->setSpeedVar(10);
//设置位置初始值在屏幕中央。
m_emitter->setPosition( CCPointMake( s.width/2, s.height/2) );
m_emitter->setPosVar(CCPointZero);
//设置粒子的生命初始值及初始时生命值的随机加值范围。
m_emitter->setLife(2.0f);
m_emitter->setLifeVar(0.3f);
//设置粒子系统的发射速率。
m_emitter->setEmissionRate(m_emitter->getTotalParticles()/m_emitter->getLife());
//设置粒子系统的起始颜色和起始颜色的随机加值范围。
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);
//设置粒子系统的起始大小和起始大小的随机加值范围。
m_emitter->setStartSize(1.0f);
m_emitter->setStartSizeVar(1.0f);
//设置粒子系统的结束大小和结束大小的随机加值范围。
m_emitter->setEndSize(32.0f);
m_emitter->setEndSizeVar(8.0f);
//加载火焰的图片做为粒子系统的纹理。
m_emitter->setTexture( CCTextureCache::sharedTextureCache()->addImage(s_fire) );
//设置不使用加亮模式。
m_emitter->setBlendAdditive(false);
//设置粒子系统居中。
setEmitterPosition();
}
//取得标题。
std::string DemoModernArt::title()
{
return "Varying size";
}
(18) DemoRing
描述:
光环的摸拟
截图:

源码解析:
//加载当前层时的处理。
void DemoRing::onEnter()
{
//调用基类的相应函数。
ParticleDemo::onEnter();
//创建一个CCParticleFlower类的粒子系统实例。
m_emitter = CCParticleFlower::create();
//占用它,对其引用计数器加一。
m_emitter->retain();
//将粒子系统加入到背景精灵的结点之下。
m_background->addChild(m_emitter, 10);
//加载星星的图片做为粒子系统的纹理。
m_emitter->setTexture( CCTextureCache::sharedTextureCache()->addImage(s_stars1) );
//设置粒子的生命值为10。
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";
}
(19) ParallaxParticle
描述:
视差的摸拟
截图:

源码解析:
//加载当前层时的处理。
void ParallaxParticle::onEnter()
{
//调用基类的相应函数。
ParticleDemo::onEnter();
//将背景精灵移除。
m_background->getParent()->removeChild(m_background, true);
m_background = NULL;
//创建一个CCParallaxNode结点p。
CCParallaxNode* p = CCParallaxNode::create();
//将p放入当前层中。
addChild(p, 5);
//创建两个以s_back3为纹理的精灵p1,p2。
CCSprite *p1 = CCSprite::create(s_back3);
CCSprite *p2 = CCSprite::create(s_back3);
//将p1,p2分别放入CCParallaxNode结点p中。
p->addChild( p1, 1, CCPointMake(0.5f,1), CCPointMake(0,250) );
p->addChild(p2, 2, CCPointMake(1.5f,1), CCPointMake(0,50) );
//创建一个CCParticleFlower类的粒子系统实例。
m_emitter = CCParticleFlower::create();
//占用它,对其引用计数器加一。
m_emitter->retain();
//加载火焰的图片做为粒子系统的纹理。
m_emitter->setTexture( CCTextureCache::sharedTextureCache()->addImage(s_fire) );
//将粒子系统emitter放入p1的结点下。
p1->addChild(m_emitter, 10);
//设置粒子系统的位置。
m_emitter->setPosition( CCPointMake(250,200) );
//创建一个CCParticleSun类的粒子系统实例。
CCParticleSun* par = CCParticleSun::create();
//将粒子系统par放入p2的结点下。
p2->addChild(par, 10);
//加载火焰的图片做为粒子系统的纹理。par->setTexture( CCTextureCache::sharedTextureCache()->addImage(s_fire) );
//创建动画move和反向动画move_back,由两个动画创建动画序列seq.
CCActionInterval* move = CCMoveBy::create(4, CCPointMake(300,0));
CCActionInterval* move_back = move->reverse();
CCFiniteTimeAction* seq = CCSequence::create( move, move_back, NULL);
//让CCParallaxNode结点p运行这个序列动画。
p->runAction(CCRepeatForever::create((CCActionInterval*)seq));
}
//取得标题。
std::string ParallaxParticle::title()
{
return "Parallax + Particles";
}
(20) DemoParticleFromFile
描述:
从PLIST文件中创建一个粒子系统。
截图:
源码解析:
//加载当前层时进行的处理。
void DemoParticleFromFile::onEnter()
{
//调用基类的相应函数。
ParticleDemo::onEnter();
//设置背景为黑色。
setColor(ccBLACK);
//将背景精灵移除并置空。
removeChild(m_background, true);
m_background = NULL;
//创建一个新的粒子系统。
m_emitter = new CCParticleSystemQuad();
//通过参数创建一个字符串做为PLIST文件名用于加载一个粒子系统。
std::string filename = "Particles/" + m_title + ".plist";
m_emitter->initWithFile(filename.c_str());
//将粒子系统加入当前结点下。
addChild(m_emitter, 10);
//设置粒子系统居中。
setEmitterPosition();
}
在createParticleLayer函数中有
case 19: return new DemoParticleFromFile("BoilingFoam");
case 20: return new DemoParticleFromFile("BurstPipe");
case 21: return new DemoParticleFromFile("Comet");
case 22: return new DemoParticleFromFile("debian");
case 23: return new DemoParticleFromFile("ExplodingRing");
case 24: return new DemoParticleFromFile("LavaFlow");
case 25: return new DemoParticleFromFile("SpinningPeas");
case 26: return new DemoParticleFromFile("SpookyPeas");
case 27: return new DemoParticleFromFile("Upsidedown");
case 28: return new DemoParticleFromFile("Flower");
case 29: return new DemoParticleFromFile("Spiral");
case 30: return new DemoParticleFromFile("Galaxy");
case 31: return new DemoParticleFromFile("Phoenix");
大家可以一一查看,其实原理就是通过PLIST文件创建不同型态的粒子系统。
(21) RadiusMode1
描述:
环形运动模式演示一。
截图:

源码解析:
//加载当前层时的处理
void RadiusMode1::onEnter()
{
//调用基类的相应处理
ParticleDemo::onEnter();
//设置背景色为黑色
setColor(ccBLACK);
//移除背景精灵并置空。
removeChild(m_background, true);
m_background = NULL;
//创建粒子系统,创建200个粒子。
m_emitter = new CCParticleSystemQuad();
m_emitter->initWithTotalParticles(200);
addChild(m_emitter, 10);
//加载图片做为粒子系统的纹理。
m_emitter->setTexture(CCTextureCache::sharedTextureCache()->addImage("Images/stars-grayscale.png"));
//设置粒子系统永远更新,宏kCCParticleDurationInfinity值为-1。
m_emitter->setDuration(kCCParticleDurationInfinity);
// 设置粒子系统运动模式为环型模式。
m_emitter->setEmitterMode(kCCParticleModeRadius);
// 环型模式的起始和结束半径以及相应的半径随机加成范围值。
m_emitter->setStartRadius(0);
m_emitter->setStartRadiusVar(0);
m_emitter->setEndRadius(160);
m_emitter->setEndRadiusVar(0);
// 设置环型运动模式的每秒旋转角度及相应的随机加成范围值。
m_emitter->setRotatePerSecond(180);
m_emitter->setRotatePerSecondVar(0);
// 设置初始时粒子系统的角度以及相应的随机加成范围值。
m_emitter->setAngle(90);
m_emitter->setAngleVar(0);
// 设置粒子系统的位置居于屏幕中央。
CCSize size = CCDirector::sharedDirector()->getWinSize();
m_emitter->setPosition(ccp(size.width/2, size.height/2));
m_emitter->setPosVar(CCPointZero);
// 设置初始时粒子的生命值为5。
m_emitter->setLife(5);
m_emitter->setLifeVar(0);
// 设置粒子本身起始和结束状态不旋转
m_emitter->setStartSpin(0);
m_emitter->setStartSpinVar(0);
m_emitter->setEndSpin(0);
m_emitter->setEndSpinVar(0);
//设置粒子系统发射粒子的起始颜色和随机加值范围。
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);
// 设置粒子系统发射粒子的起始大小和随机加值范围,结束值指定为宏kCCParticleStartSizeEqualToEndSize代表大小在粒子运动时不变化。
m_emitter->setStartSize(32);
m_emitter->setStartSizeVar(0);
m_emitter->setEndSize(kCCParticleStartSizeEqualToEndSize);
// 设置粒子系统的发射速率。
m_emitter->setEmissionRate(m_emitter->getTotalParticles() / m_emitter->getLife());
// 设置不使用高亮模式。
m_emitter->setBlendAdditive(false);
}
//取得标题。
std::string RadiusMode1::title()
{
return "Radius Mode: Spiral";
}
(22) RadiusMode2
描述:
环形运动模式演示一。
截图:
源码解析:
//加载当前层时的处理。
void RadiusMode2::onEnter()
{
//调用基类的相应函数。
ParticleDemo::onEnter();
//设置背景色为黑色。
setColor(ccBLACK);
//移除背景精灵并置空。
removeChild(m_background, true);
m_background = NULL;
//创建粒子系统,创建200个粒子。
m_emitter = new CCParticleSystemQuad();
m_emitter->initWithTotalParticles(200);
addChild(m_emitter, 10);
//加载图片做为粒子系统的纹理。m_emitter->setTexture(CCTextureCache::sharedTextureCache()->addImage("Images/stars-grayscale.png"));
//设置粒子系统永远更新,宏kCCParticleDurationInfinity值为-1。
m_emitter->setDuration(kCCParticleDurationInfinity);
// 设置粒子系统运动模式为环型模式。
m_emitter->setEmitterMode(kCCParticleModeRadius);
// 环型模式的起始和结束半径以及相应的半径随机加成范围值。
m_emitter->setStartRadius(100);
m_emitter->setStartRadiusVar(0);
m_emitter->setEndRadius(kCCParticleStartRadiusEqualToEndRadius);
m_emitter->setEndRadiusVar(0);
// 设置环型运动模式的每秒旋转角度及相应的随机加成范围值。
m_emitter->setRotatePerSecond(45);
m_emitter->setRotatePerSecondVar(0);
// 设置初始时粒子系统的角度以及相应的随机加成范围值。
m_emitter->setAngle(90);
m_emitter->setAngleVar(0);
// 设置粒子系统的位置居于屏幕中央。
CCSize size = CCDirector::sharedDirector()->getWinSize();
m_emitter->setPosition(ccp(size.width/2, size.height/2));
m_emitter->setPosVar(CCPointZero);
// 设置初始时粒子的生命值为4。
m_emitter->setLife(4);
m_emitter->setLifeVar(0);
// 设置粒子本身起始和结束状态不旋转
m_emitter->setStartSpin(0);
m_emitter->setStartSpinVar(0);
m_emitter->setEndSpin(0);
m_emitter->setEndSpinVar(0);
//设置粒子系统发射粒子的起始颜色和随机加值范围。
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);
// 设置粒子系统发射粒子的起始大小和随机加值范围,结束值指定为宏kCCParticleStartSizeEqualToEndSize代表大小在粒子运动时不变化。
m_emitter->setStartSize(32);
m_emitter->setStartSizeVar(0);
m_emitter->setEndSize(kCCParticleStartSizeEqualToEndSize);
// 设置粒子系统的发射速率。
m_emitter->setEmissionRate(m_emitter->getTotalParticles() / m_emitter->getLife());
// 设置不使用高亮模式。
m_emitter->setBlendAdditive(false);
}
//取得标题。
std::string RadiusMode2::title()
{
return "Radius Mode: Semi Circle";
}
(23) Issue704
描述:
从PLIST文件中创建一个粒子系统。
截图:
源码解析:
//加载当前层时的处理。
void Issue704::onEnter()
{
//调用基类的相应函数
ParticleDemo::onEnter();
//设置背景色为黑色。
setColor(ccBLACK);
//移除背景精灵并置空。
removeChild(m_background, true);
m_background = NULL;
//创建粒子系统,创建100个粒子。
m_emitter = new CCParticleSystemQuad();
m_emitter->initWithTotalParticles(100);
addChild(m_emitter, 10);
//加载图片做为粒子系统的纹理。m_emitter->setTexture(CCTextureCache::sharedTextureCache()->addImage("Images/fire.png"));
//设置粒子系统永远更新,宏kCCParticleDurationInfinity值为-1。
m_emitter->setDuration(kCCParticleDurationInfinity);
// 设置粒子系统运动模式为环型模式。
m_emitter->setEmitterMode(kCCParticleModeRadius);
// 环型模式的起始和结束半径以及相应的半径随机加成范围值。
m_emitter->setStartRadius(50);
m_emitter->setStartRadiusVar(0);
m_emitter->setEndRadius(kCCParticleStartRadiusEqualToEndRadius);
m_emitter->setEndRadiusVar(0);
// 设置环型运动模式的每秒旋转角度及相应的随机加成范围值。
m_emitter->setRotatePerSecond(0);
m_emitter->setRotatePerSecondVar(0);
// 设置初始时粒子系统的角度以及相应的随机加成范围值。
m_emitter->setAngle(90);
m_emitter->setAngleVar(0);
// 设置粒子系统的位置居于屏幕中央。
CCSize size = CCDirector::sharedDirector()->getWinSize();
m_emitter->setPosition(ccp(size.width/2, size.height/2));
m_emitter->setPosVar(CCPointZero);
// 设置初始时粒子的生命值为5。
m_emitter->setLife(5);
m_emitter->setLifeVar(0);
// 设置粒子本身起始和结束状态不旋转
m_emitter->setStartSpin(0);
m_emitter->setStartSpinVar(0);
m_emitter->setEndSpin(0);
m_emitter->setEndSpinVar(0);
//设置粒子系统发射粒子的起始颜色和随机加值范围。
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);
// 设置粒子系统发射粒子的起始大小和随机加值范围,结束值指定为宏kCCParticleStartSizeEqualToEndSize代表大小在粒子运动时不变化。
m_emitter->setStartSize(16);
m_emitter->setStartSizeVar(0);
m_emitter->setEndSize(kCCParticleStartSizeEqualToEndSize);
// 设置粒子系统的发射速率。
m_emitter->setEmissionRate(m_emitter->getTotalParticles() / m_emitter->getLife());
// 设置不使用高亮模式。
m_emitter->setBlendAdditive(false);
// 让粒子系统的发射器运行一个无限旋转的动画。
CCRotateBy* rot = CCRotateBy::create(16, 360);
m_emitter->runAction(CCRepeatForever::create(rot));
}
//取得标题。
std::string Issue704::title()
{
return "Issue 704. Free + Rot";
}
//取得幅标题。
std::string Issue704::subtitle()
{
return "Emitted particles should not rotate";
}
(24) Issue870
描述:
从PLIST文件中创建一个粒子系统。
截图:
源码解析:
//加载当前层时的处理。
void Issue870::onEnter()
{
//调用基类的相应函数。
ParticleDemo::onEnter();
//设置背景色为黑色。
setColor(ccBLACK);
//移除背景精灵并置空。
removeChild(m_background, true);
m_background = NULL;
//创建一个粒子系统,由一个PLIST文件来创建相应的粒子。
CCParticleSystemQuad *system = new CCParticleSystemQuad();
system->initWithFile("Particles/SpinningPeas.plist");
//加载纹得中的一个图块做为粒子的纹理。
system->setTextureWithRect(CCTextureCache::sharedTextureCache()->addImage("Images/particles.png"), CCRectMake(0,0,32,32));
addChild(system, 10);
//将粒子系统实例指针保存到成员变量中。在后面updateQuads使用。
m_emitter = system;
//图片中的图块索引。
m_nIndex = 0;
//让当前层每2秒调用一下更新粒子的绘制矩形函数。
schedule(schedule_selector(Issue870::updateQuads), 2.0f);
}
//更新粒子的绘制矩形函数。
void Issue870::updateQuads(float dt)
{
//图块索引加一,并限定在[0,4)间。
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";
}
(25) Issue1201
描述:
似乎从截图上看不到什么,仔细看,并移动鼠标。这个实例应该是一个类似慧尾的效果,只是很淡。
截图:
源码解析:
//加载当前层时的处理
void Issue1201::onEnter()
{
//调用基类的相应函数。
ParticleDemo::onEnter();
//设置背景色为黑色。
setColor(ccBLACK);
//移除背景精灵并置空。
removeChild(m_background, true);
m_background = NULL;
//创建一个RainbowEffect类的实例,创建5O个粒子。
RainbowEffect *particle = new RainbowEffect();
particle->initWithTotalParticles(50);
//将其加入到当前层结点下。
addChild(particle);
//将粒子系统的位置居于屏幕中央。
CCSize s = CCDirector::sharedDirector()->getWinSize();
particle->setPosition(ccp(s.width/2, s.height/2));
m_emitter = particle;
}
//取得标题。
std::string Issue1201::title()
{
return "Issue 1201. Unfinished";
}
//取得幅标题。
std::string Issue1201::subtitle()
{
return "Unfinished test. Ignore it";
}
(26) MultipleParticleSystems
描述:
多个粒子系统。
截图:

源码解析:
//加载当前层时的处理
void MultipleParticleSystems::onEnter()
{
//调用基类的相应函数。
ParticleDemo::onEnter();
//设置背景色为黑色。
setColor(ccBLACK);
//移除背景精灵并置空。
removeChild(m_background, true);
m_background = NULL;
//加载纹得中的一个图块做为粒子的纹理。CCTextureCache::sharedTextureCache()->addImage("Images/particles.png");
//创建5个粒子系统。
for (int i = 0; i<5; i++) {
//由相应的PLIST创建出粒子系统来。
CCParticleSystemQuad *particleSystem = CCParticleSystemQuad::create("Particles/SpinningPeas.plist");
//根据索引将粒子系统放在不同的位置。
particleSystem->setPosition(ccp(i*50 ,i*50));
//设置粒子系统运动影响方式类型为按组方式。
particleSystem->setPositionType(kCCPositionTypeGrouped);
addChild(particleSystem);
}
//粒子发射器指针置空。
m_emitter = NULL;
}
//取得标题。
std::string MultipleParticleSystems::title()
{
return "Multiple particle systems";
}
//取得幅标题。
std::string MultipleParticleSystems::subtitle()
{
return "v1.1 test: FPS should be lower than next test";
}
//更新函数。
void MultipleParticleSystems::update(float dt)
{
//取得用于标识粒子数量的文字标签。
CCLabelAtlas *atlas = (CCLabelAtlas*) getChildByTag(kTagParticleCount);
//定义一个计数器变量count
unsigned int count = 0;
//遍历所有粒子系统子结点
CCObject* pObj = NULL;
//CCARRAY_FOREACH为遍历CArray数组的宏
CCARRAY_FOREACH(m_pChildren, pObj)
{
//通过dynamic_cast来将数组元素转换成为相应的粒子系统指针。
CCParticleSystem* item = dynamic_cast<CCParticleSystem*>(pObj);
if (item != NULL)
{
//当前计数器变量count值加上当前粒子系统子结点的粒子数量,统计粒子总数。
count += item->getParticleCount();
}
}
//让文字标签显示相应的粒子数量。
char str[100] = {0};
sprintf(str, "%4d", count);
atlas->setString(str);
}
(27) MultipleParticleSystemBatched
描述:
使用批次结点进行多外粒子系统的渲染管理。
截图:

源码解析:
//当前层加载时的处理
void MultipleParticleSystemsBatched::onEnter()
{
//先调用基类的相应处理。
ParticleDemo::onEnter();
//设置背景色为黑色。
setColor(ccBLACK);
//移除背景精灵并置空。
removeChild(m_background, true);
m_background = NULL;
//创建一个新的粒子系统的批次结点。
CCParticleBatchNode *batchNode = new CCParticleBatchNode();
//初始化,渲染用的矩形信息容器的容量初始化为3000。
batchNode->initWithTexture(NULL, 3000);
//将粒子系统的批次结点放入当前结点之下。
addChild(batchNode, 1, 2);
//创建5个粒子系统。
for (int i = 0; i<5; i++) {
//由PLIST文件创建相应的粒子系统。
CCParticleSystemQuad *particleSystem = CCParticleSystemQuad::create("Particles/SpinningPeas.plist");
//设置粒子系统运动影响方式类型为按组方式。
particleSystem->setPositionType(kCCPositionTypeGrouped);
//根据索引将粒子系统放在不同的位置。
particleSystem->setPosition(ccp(i*50 ,i*50));
//设置使用粒子系统的纹理。
batchNode->setTexture(particleSystem->getTexture());
batchNode->addChild(particleSystem);
}
//已经放入到当前结点下,不再占用粒子系统批次结点,所以对其引用计数器减一操作。
batchNode->release();
//使用批次结点,则原指向所用的粒子系统发射器的指针置空。
m_emitter = NULL;
}
//更新处理。
void MultipleParticleSystemsBatched::update(float dt)
{ //取得用于标识粒子数量的文字标签。
CCLabelAtlas *atlas = (CCLabelAtlas*) getChildByTag(kTagParticleCount);
//定义一个计数器变量count
unsigned count = 0;
//根据索引取得粒子系统的批次结点。
CCNode* batchNode = getChildByTag(2);
//遍历所有粒子系统子结点
CCObject* pObj = NULL;
//CCARRAY_FOREACH为遍历CArray数组的宏
CCARRAY_FOREACH(batchNode->getChildren(), pObj)
{
//通过dynamic_cast来将数组元素转换成为相应的粒子系统指针。
CCParticleSystem* item = dynamic_cast<CCParticleSystem*>(pObj);
if (item != NULL)
{
//当前计数器变量count值加上当前粒子系统子结点的粒子数量,统计粒子总数。
count += item->getParticleCount();
}
}
//让文字标签显示相应的粒子数量。
char str[50] = {0};
sprintf(str, "%4d", count);
atlas->setString(str);
}
//取得标题。
std::string MultipleParticleSystemsBatched::title()
{
return "Multiple particle systems batched";
}
//取得幅标题。
std::string MultipleParticleSystemsBatched::subtitle()
{
return "v1.1 test: should perform better than previous test";
}
(28) AddAndDeleteParticleSystems
描述:
动态的增加和删除粒子系统。
截图:

源码解析:
//加载当前层时的处理
void AddAndDeleteParticleSystems::onEnter()
{
//调用基类的相应函数。
ParticleDemo::onEnter();
//设置背景色为黑色。
setColor(ccBLACK);
//移除背景精灵并置空。
removeChild(m_background, true);
m_background = NULL;
//创建一个粒子系统的批次结点,渲染用的矩形信息容器的容量初始化为16000。
m_pBatchNode = CCParticleBatchNode::createWithTexture((CCTexture2D*)NULL, 16000);
//将批次结点加入当前层中。
addChild(m_pBatchNode, 1, 2);
//创建6个粒子系统。
for (int i = 0; i<6; i++) {
//由相应的PLIST文件创建出粒子系统。
CCParticleSystemQuad *particleSystem = CCParticleSystemQuad::create("Particles/Spiral.plist");
//取出粒子系统所用的纹理设置为批次结点的纹理。
m_pBatchNode->setTexture(particleSystem->getTexture());
//设置粒子系统的运动方式为组运动方式,最大粒子数量为200。
particleSystem->setPositionType(kCCPositionTypeGrouped);
particleSystem->setTotalParticles(200);
//设置每个粒子系统的位置。
particleSystem->setPosition(ccp(i*15 +100,i*15+100));
//将粒子系统放入到批次结点中。
unsigned int randZ = rand() % 100;
m_pBatchNode->addChild(particleSystem, randZ, -1);
}
//让当前层每0.5秒触发一次函数removeSystem
chedule(schedule_selector(AddAndDeleteParticleSystems::removeSystem), 0.5f);
//因为使用的是粒子系统的批次结点,所以指向粒子系统的指针置空。
m_emitter = NULL;
}
//定时触发的函数。
void AddAndDeleteParticleSystems::removeSystem(float dt)
{
//取得批次结点中的粒子系统的数量。
int nChildrenCount = m_pBatchNode->getChildren()->count();
if (nChildrenCount > 0)
{
CCLOG("remove random system");
//产生一个随机索引。
unsigned int uRand = rand() % (nChildrenCount - 1);
//将对应索引的粒子系统从批次结点中删除。
pBatchNode->removeChild((CCNode*)m_pBatchNode->getChildren()->objectAtIndex(uRand), true);
//再由PLIST创建一个新的粒子系统。
CCParticleSystemQuad *particleSystem = CCParticleSystemQuad::create("Particles/Spiral.plist");
//add new
//设置粒子系统运动方式为组方式,粒子总数量为200
particleSystem->setPositionType(kCCPositionTypeGrouped);
particleSystem->setTotalParticles(200);
//设置粒子系统处于一个随机的位置。
particleSystem->setPosition(ccp(rand() % 300 ,rand() % 400));
//打印日志,将新粒子系统放入到批次结点中。
CCLOG("add a new system");
unsigned int randZ = rand() % 100;
m_pBatchNode->addChild(particleSystem, randZ, -1);
}
}
//更新处理
void AddAndDeleteParticleSystems::update(float dt)
{
//取得用于显示粒子数量的文字标签。
CCLabelAtlas *atlas = (CCLabelAtlas*) getChildByTag(kTagParticleCount);
unsigned int count = 0;
//取得粒子系统的批次结点。
CCNode* batchNode = getChildByTag(2);
//定义临时指针变量pObj,用于遍历所有的粒子系统结点。
CCObject* pObj = NULL;
CCARRAY_FOREACH(batchNode->getChildren(), pObj)
{
//通过dynamic_cast将物体基类指针转化为粒子系统结点指针。
CCParticleSystem* item = dynamic_cast<CCParticleSystem*>(pObj);
if (item != NULL)
{
//更新粒子的计数器值。
count += item->getParticleCount();
}
}
//写字,显示数量。
char str[100] = {0};
sprintf(str, "%4d", count);
atlas->setString(str);
}
//取得标题。
std::string AddAndDeleteParticleSystems::title()
{
return "Add and remove Particle System";
}
//取得幅标题。
std::string AddAndDeleteParticleSystems::subtitle()
{
return "v1.1 test: every 2 sec 1 system disappear, 1 appears";
}
(29) ReorderParticleSystems
描述:
粒子系统的Z值重新排序。
截图:

源码解析:
//加载当前层时的处理。
void ReorderParticleSystems::onEnter()
{
//调用基类的相应函数。
ParticleDemo::onEnter();
//设置背景色为黑色。
setColor(ccBLACK);
//移除背景精灵并置空。
removeChild(m_background ,true);
m_background = NULL;
//创建一个新的粒子系统的批次结点,渲染用的矩形信息容器的容量初始化为3000。
m_pBatchNode = CCParticleBatchNode::create("Images/stars-grayscale.png" ,3000);
//将粒子系统的批次结点放入到当前层结点下。
addChild(m_pBatchNode, 1, 2);
//使用for循环创建三个粒子系统。
for (int i = 0; i<3; i++) {
//创建第i个粒子系统。
CCParticleSystemQuad* particleSystem = new CCParticleSystemQuad();
//创建200个粒子。
particleSystem->initWithTotalParticles(200);
//取得批次结点的纹理设置为粒子系统的纹理。
particleSystem->setTexture(m_pBatchNode->getTexture());
//设置粒子系统一直调用Update
particleSystem->setDuration(kCCParticleDurationInfinity);
//设置粒子的运动方式为环型运动方式。
particleSystem->setEmitterMode(kCCParticleModeRadius);
//设置粒子系统的粒子起始角度为100。
particleSystem->setStartRadius(100);
particleSystem->setStartRadiusVar(0);
//指定粒子系统的粒子结束角度与起始角度相同,即角度不变化。
particleSystem->setEndRadius(kCCParticleStartRadiusEqualToEndRadius);
particleSystem->setEndRadiusVar(0); // not used when start == end
// 设置粒子系统的环型运动速率为每秒45度。
particleSystem->setRotatePerSecond(45);
particleSystem->setRotatePerSecondVar(0);
// 设置粒子系统的角度为90度。
particleSystem->setAngle(90);
particleSystem->setAngleVar(0);
//设置粒子系统的位置为零点
particleSystem->setPosVar(CCPointZero);
//设置粒子初始化的生命值为4。
particleSystem->setLife(4);
particleSystem->setLifeVar(0);
//设置粒子运动过程中自身不旋转。
particleSystem->setStartSpin(0);
particleSystem->setStartSpinVar(0);
particleSystem->setEndSpin(0);
particleSystem->setEndSpinVar(0);
//设置粒子的起始和结束的颜色,这里通过一个float数组来表示R,G,B的值,通过索引设置相应色彩分量值表现红,绿,蓝三种颜色。
float color[3] = {0,0,0};
color[i] = 1;
ccColor4F startColor = {color[0], color[1], color[2], 1.0f};
particleSystem->setStartColor(startColor);
ccColor4F startColorVar = {0, 0, 0, 0};
particleSystem->setStartColorVar(startColorVar);
ccColor4F endColor = startColor;
particleSystem->setEndColor(endColor);
ccColor4F endColorVar = startColorVar;
particleSystem->setEndColorVar(endColorVar);
// 设置粒子的起始大小。
particleSystem->setStartSize(32);
particleSystem->setStartSizeVar(0);
particleSystem->setEndSize(kCCParticleStartSizeEqualToEndSize);
//设置粒子系统发射粒子的速率。
particleSystem->setEmissionRate(particleSystem->getTotalParticles()/particleSystem->getLife());
// 设置粒子系统的位置,
particleSystem->setPosition(ccp(i*10+120 ,200));
//将粒子系统放入到批次结点下,设置粒子系统的运动方式为自由运动方式。
m_pBatchNode->addChild(particleSystem);
particleSystem->setPositionType(kCCPositionTypeFree);
//使用批次结点进行渲染,粒子系统已经放入到批次结点之下,故不再占用粒子系统,所以可以在这里对其引用计数器减一操作。
particleSystem->release();
//[pBNode addChild:particleSystem z:10 tag:0);
}
//每2秒调用一下reorderSystem函数。
schedule(schedule_selector(ReorderParticleSystems::reorderSystem), 2.0f);
m_emitter = NULL;
}
//定时触发的函数。
void ReorderParticleSystems::reorderSystem(float time)
{
//通过索引取得相应的批次系统结点,进行重新的Z值排序。
CCParticleSystem* system = (CCParticleSystem*)m_pBatchNode->getChildren()->objectAtIndex(1);
m_pBatchNode->reorderChild(system, system->getZOrder() - 1);
}
//更新函数。
void ReorderParticleSystems::update(float dt)
{
//取得用于显示粒子数量的文字标签。
CCLabelAtlas *atlas = (CCLabelAtlas*) getChildByTag(kTagParticleCount);
//创建临时变量用于统计粒子数量。
unsigned int count = 0;
//取得批次结点
CCNode* batchNode = getChildByTag(2);
//定义临时CCObject指针变量用于遍历所有的粒子系统。
CCObject* pObj = NULL;
CCARRAY_FOREACH(batchNode->getChildren(), pObj)
{
//通过dynamic_cast将物体基类指针转化为粒子系统结点指针。
CCParticleSystem* item = dynamic_cast<CCParticleSystem*>(pObj);
if (item != NULL)
{
//更新粒子数量的计数器。
count += item->getParticleCount();
}
}
//写字。
char str[100] = {0};
sprintf(str, "%4d", count);
atlas->setString(str);
}
//返回标题。
std::string ReorderParticleSystems::title()
{
return "reorder systems";
}
//返回幅标题。
std::string ReorderParticleSystems::subtitle()
{
return "changes every 2 seconds";
}
(30) PremultipliedAlphaTest
描述:
预乘aplha通道效果演示之一。什么是预乘?假设一个像素点,用RGBA 四个分量来表示,记做(R,G,B,A),那预乘后的像素就是(R*A,G*A,B*A, A),这里A的取值范围是[0,1]。所以,预乘就是每个颜色分量都与该像素的alpha分量预先相乘。可以发现,对于一个没有透明度,或者说透明度为1 的像素来说,预乘不预乘结果都是一样的。为什么要用预乘方式来表示像素?主要是这样会使公式更简单。而且实际上,在实际运算过程中,使用预乘像素进行运算在某些情况下效率会更高。
截图:

源码解析:
//返回标题。
std::string PremultipliedAlphaTest::title()
{
return "premultiplied alpha";
}
//返回副标题。
std::string PremultipliedAlphaTest::subtitle()
{
return "no black halo, particles should fade out";
}
//当前层加载时调用的处理。
void PremultipliedAlphaTest::onEnter()
{
//调用基类的相应函数。
ParticleDemo::onEnter();
//设置背景为蓝色。
this->setColor(ccBLUE);
//删除原来的背景精灵并置空。
this->removeChild(m_background, true);
m_background = NULL;
//由PLIST文件创建一个粒子系统。
m_emitter = CCParticleSystemQuad::create("Particles/BoilingFoam.plist");
//占用它,所以对其引用计数器加一。
m_emitter->retain();
//设置ALPHA混合方案为方案。
ccBlendFunc tBlendFunc = { GL_ONE, GL_ONE_MINUS_SRC_ALPHA };
m_emitter->setBlendFunc(tBlendFunc);
//提示纹理必须有ALPHA通道
CCAssert(m_emitter->getOpacityModifyRGB(), "Particle texture does not have premultiplied alpha, test is useless");
// Toggle next line to see old behavior
// this->emitter.opacityModifyRGB = NO;
//设置粒子系统的粒子起始和结束的颜色。
m_emitter->setStartColor(ccc4f(1, 1, 1, 1));
m_emitter->setEndColor(ccc4f(1, 1, 1, 0));
m_emitter->setStartColorVar(ccc4f(0, 0, 0, 0));
m_emitter->setEndColorVar(ccc4f(0, 0, 0, 0));
//将粒子系统加入到当前结点下。
this->addChild(m_emitter, 10);
}
(31) PremultipliedAlphaTest2:
描述:
预乘aplha通道效果演示之二。
截图:

源码解析:
//加载当前层时的处理。
void PremultipliedAlphaTest2::onEnter()
{
//调用基类的相应函数。
ParticleDemo::onEnter();
//设置背景为黑色。
this->setColor(ccBLACK);
//删除原来的背景精灵并置空。
this->removeChild(m_background, true);
m_background = NULL;
//由PLIST文件创建一个粒子系统。具体的ALPHA混合方案都由PLIST文件中的数据进行读取设置。
m_emitter = CCParticleSystemQuad::create("Particles/TestPremultipliedAlpha.plist");
//占用粒子系统,对其引用计数器加一。
m_emitter->retain();
//将粒子系统放入到当前结点下。
this->addChild(m_emitter ,10);
}
//取得标题。
std::string PremultipliedAlphaTest2::title()
{
return "premultiplied alpha 2";
}
//取得副标题。
std::string PremultipliedAlphaTest2::subtitle()
{
return "Arrows should be faded";
}
我去~,累死哥了。不过经过这么痛苦的注释之后,我相信大家会跟我一样越来越清楚Cocos2d-x里的粒子系统是什么原理以及怎样使用的.我们可以看到,PLIST作为Cocos2d-x粒子系统数据的的存储文件,它可以很方便的产生出粒子系统。在实际的游戏开发过程中,我们一般都会为粒子系统开发一个专用的编辑器,它应该具有Cocos2d-x粒子系统中的所用属性并能编辑后保存为PLIST文件以方便游戏使用。比如这样:

粒子系统深入分析三部曲结束了,恰逢新的一年到来之际,我衷心的祝愿各位同学能够2013身体健康,事业有成。下课!