cocos2d-x学习笔记(12)--粒子系统
本文出自http://www.wenbanana.com稻草人博客,欢迎访问!
这次我们要接触的是粒子系统,其实就是游戏中常说的武器系统。在cocos2d-x中文官方网站上http://cn.cocos2d-x.org/document,我截了下图:
上图就是所有的粒子效果,我们只要掌握其使用方法即可。在讲粒子系统之前,我要补充说明一些东西。
首先是CCSprite的继承关系:
可以看到CCSprite继承了CCNode类,而CCNode中包含addChild成员函数,所以CCSprite同样有addChild成员函数。可能之前一直只用layer和scene调用addChild,给大家造成一个习惯,以为只有CCLayer和CCScene类才有addChild,其实不然。再看看下面的继承关系图就一目了然:
接下来下,补充第二个说明:
例子:sprite->runAction(CCRepeateForever::actionWithAction( (CCActionInterval *)(CCSequence::actions (action1, action2, NULL) ) ));
首先我们看看CCSequence::actions的函数原型:
函数的返回值类型是CCFiniteTimeAction,但是我们看看CCRepeateForever::actionWithaction的函数原型:
函数接受的参数类型是CCActionInterval,有于类型不匹配,要转换,转换的根据看了下图就明白了:
CCActionInterval类继承了CCFiniteTimeAction类,那么上面例子的强制转换就存在合理性了。
最后一点就是在看这一节的笔记前,最好看看上一节的笔记cocos2d-x学习笔记(11)--坐标系,有助于理解这一节的代码;
以上的补充主要想说的事,大家在遇到什么不懂得地方的时候,可以多去官方网站去查查资料,那里才是最佳的学习地点。
step1:创建cocos2d-win32 application,并命名为particle;
step2:在HelloWorldScene.h中添加下面几个类:
class ParticleDemo:public CCLayer { protected: CCParticleSystem* m_emitter; CCSprite* m_background; public: ParticleDemo(); ~ParticleDemo(); virtual std::string title(); virtual void onEnter(); void backCallback(CCObject* pSender); void restartCallback(CCObject* pSender); void nextCallback(CCObject* pSender); virtual void registerWithTouchDispatcher(); virtual bool ccTouchBegan(CCTouch* touch, CCEvent* event); virtual void ccTouchMoved(CCTouch* touch, CCEvent* event); virtual void ccTouchEnded(CCTouch* touch, CCEvent* event); void setEmitterPosition(); }; /************************************************************************/ /* firework */ /************************************************************************/ class FireWork:public ParticleDemo { public: virtual void onEnter(); std::string title(); }; class DemoSun:public ParticleDemo { public: virtual void onEnter(); std::string title(); }; class DemoFlower:public ParticleDemo { public: virtual void onEnter(); std::string title(); }; class DemoExplosion:public ParticleDemo { public: virtual void onEnter(); std::string title(); }; class DemoSnow:public ParticleDemo { public: virtual void onEnter(); std::string title(); };
step3:在HelloWorldScene.cpp中添加如下全局变量及函数:
static int index = 1; const int MAX_INDEX = 5; CCLayer* runThisTest(int index) { switch(index) { case 1:return new FireWork(); case 2:return new DemoSun(); case 3:return new DemoFlower(); case 4:return new DemoExplosion(); case 5:return new DemoSnow(); } return NULL; }
在添加对应类的成员函数
/************************************************************************/ /* ParticleDemo */ /************************************************************************/ ParticleDemo::ParticleDemo() { m_emitter = NULL; setIsTouchEnabled(true); CCSize size = CCDirector::sharedDirector()->getWinSize(); //添加基本按钮 CCLabelTTF* pNextLabel = CCLabelTTF::labelWithString("Next ", "Arial", 30); CCLabelTTF*pBackLabel = CCLabelTTF::labelWithString("Back ", "Arial", 30); CCLabelTTF*pRestartLabel = CCLabelTTF::labelWithString("Restart ", "Arial", 30); CCMenuItemLabel* pNextItem = CCMenuItemLabel::itemWithLabel( pNextLabel, this, menu_selector(ParticleDemo::nextCallback)); CCMenuItemLabel* pBackItem = CCMenuItemLabel::itemWithLabel( pBackLabel, this, menu_selector(ParticleDemo::backCallback)); CCMenuItemLabel* pRestartItem = CCMenuItemLabel::itemWithLabel( pRestartLabel, this, menu_selector(ParticleDemo::restartCallback)); CCMenu* pNextMenu = CCMenu::menuWithItem(pNextItem); CCMenu* pBackMenu = CCMenu::menuWithItem(pBackItem); CCMenu* pRestartMenu = CCMenu::menuWithItem(pRestartItem); pNextItem->setPosition(ccp(size.width/2 +150, 50)); pBackItem->setPosition(ccp(size.width/2 - 150, 50)); pRestartItem->setPosition(ccp(size.width/2 , 50)); pNextMenu->setPosition(CCPointZero); pBackMenu->setPosition(CCPointZero); pRestartMenu->setPosition(CCPointZero); addChild(pNextMenu,1); addChild(pBackMenu, 1); addChild(pRestartMenu,1); m_background = CCSprite::spriteWithFile("HelloWorld.png"); addChild(m_background); m_background->setPosition(ccp(size.width / 2, size.height / 2)); CCActionInterval* move = CCMoveBy::actionWithDuration(4, ccp(300, 0)); CCActionInterval* move_back = move->reverse(); m_background->runAction(CCRepeatForever::actionWithAction((CCActionInterval*)(CCSequence::actions(move, move_back, NULL)))); } ParticleDemo::~ParticleDemo() { m_emitter->release(); } std::string ParticleDemo::title() { return "no title"; } void ParticleDemo::onEnter() { CCLayer::onEnter(); CCSize size = CCDirector::sharedDirector()->getWinSize(); //添加标题 std::string strTitle = title(); const char* ptitle = strTitle.c_str(); CCLabelTTF* pLabel = CCLabelTTF::labelWithString(ptitle, "Arial", 30); pLabel->setPosition(ccp(size.width/2, size.height-40)); addChild(pLabel, 1); } void ParticleDemo::backCallback(CCObject* pSender) { if(index == 1) return ; index--; CCScene* scene = new CCScene(); scene->addChild(runThisTest(index)); CCDirector::sharedDirector()->replaceScene(scene); scene->release(); } void ParticleDemo::restartCallback(CCObject* pSender) { CCScene* scene = new CCScene(); scene->addChild(runThisTest(index)); CCDirector::sharedDirector()->replaceScene(scene); scene->release(); } void ParticleDemo::nextCallback(CCObject* pSender) { if(index == MAX_INDEX) return ; index++; CCScene* scene = new CCScene(); scene->addChild(runThisTest(index)); CCDirector::sharedDirector()->replaceScene(scene); scene->release(); } void ParticleDemo::registerWithTouchDispatcher() { CCTouchDispatcher::sharedDispatcher()->addTargetedDelegate(this, 0, false); } void ParticleDemo::ccTouchEnded(CCTouch* touch, CCEvent* event) { CCPoint location = touch->locationInView(touch->view()); CCPoint convertedLocation = CCDirector::sharedDirector()->convertToGL(location); CCPoint pos = CCPointZero; pos = m_background->convertToWorldSpace(CCPointZero); m_emitter->setPosition(ccpSub(convertedLocation, pos) ); } void ParticleDemo::ccTouchMoved(CCTouch* touch, CCEvent* event) { ccTouchEnded(touch, event); } bool ParticleDemo::ccTouchBegan(CCTouch* touch, CCEvent* event) { return true; } void ParticleDemo::setEmitterPosition() { CCSize s = CCDirector::sharedDirector()->getWinSize(); m_emitter->setPosition( CCPointMake(s.width / 2, s.height / 2) ); } /************************************************************************/ /* firework */ /************************************************************************/ void FireWork::onEnter() { ParticleDemo::onEnter(); //添加标题 CCSize size = CCDirector::sharedDirector()->getWinSize(); std::string strTitle = title(); const char* ptitle = strTitle.c_str(); CCLabelTTF* pLabel = CCLabelTTF::labelWithString(ptitle, "Arial", 30); pLabel->setPosition(ccp(size.width/2, size.height-40)); addChild(pLabel, 1); m_emitter = CCParticleFireworks::node(); m_emitter->retain(); m_background->addChild(m_emitter, 10); m_emitter->setTexture(CCTextureCache::sharedTextureCache()->addImage("stars.png")); setEmitterPosition(); } std::string FireWork::title() { return "firework"; } /************************************************************************/ /* DemoSun */ /************************************************************************/ void DemoSun::onEnter() { ParticleDemo::onEnter(); //添加标题 CCSize size = CCDirector::sharedDirector()->getWinSize(); std::string strTitle = title(); const char* ptitle = strTitle.c_str(); CCLabelTTF* pLabel = CCLabelTTF::labelWithString(ptitle, "Arial", 30); pLabel->setPosition(ccp(size.width/2, size.height-40)); addChild(pLabel, 1); m_emitter = CCParticleSun::node(); m_emitter->retain(); m_background->addChild(m_emitter, 10); m_emitter->setTexture(CCTextureCache::sharedTextureCache()->addImage("fire.png")); setEmitterPosition(); } std::string DemoSun::title() { return "particle sun"; } void DemoFlower::onEnter() { ParticleDemo::onEnter(); m_emitter = CCParticleFlower::node(); m_emitter->retain(); m_background->addChild(m_emitter, 10); m_emitter->setTexture( CCTextureCache::sharedTextureCache()->addImage("fire.png") ); setEmitterPosition(); } std::string DemoFlower::title() { return "ParticleFlower"; } //------------------------------------------------------------------ // // DemoExplosion // //------------------------------------------------------------------ void DemoExplosion::onEnter() { ParticleDemo::onEnter(); m_emitter = CCParticleExplosion::node(); m_emitter->retain(); m_background->addChild(m_emitter, 10); m_emitter->setTexture( CCTextureCache::sharedTextureCache()->addImage("fire.png") ); m_emitter->setIsAutoRemoveOnFinish(true); setEmitterPosition(); } std::string DemoExplosion::title() { return "ParticleExplosion"; } //------------------------------------------------------------------ // // DemoSnow // //------------------------------------------------------------------ void DemoSnow::onEnter() { ParticleDemo::onEnter(); CCSize size = CCDirector::sharedDirector()->getWinSize(); m_emitter = CCParticleSnow::node(); m_emitter->retain(); m_background->addChild(m_emitter, 10); // gravity m_emitter->setGravity(CCPointMake(0,-10)); // speed of particles m_emitter->setSpeed(60); m_emitter->setTexture(CCTextureCache::sharedTextureCache()->addImage("fire.png")); m_emitter->setPosition(ccp(size.width / 2, size.height) ); } std::string DemoSnow::title() { return "particle snow"; }
程序中用的粒子图片大家可以自己自作,不同的图片会显示出不同的效果
step4:编译运行程序,就可以看到粒子效果,我这里只列举了五种效果,还有很多效果没有列举,想要看更多效果,可以自己去官方文档查找;
源代码下载地址: http://download.csdn.net/download/wen294299195/4525823