[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(