Cocos2d-x 2.0 网格动画深入分析
[Cocos2d-x相关教程来源于红孩儿的游戏编程之路CSDN博客地址:http://blog.csdn.net/honghaier]
红孩儿Cocos2d-X学习园地QQ2群:44208467 加群写:Cocos2d-x
红孩儿Cocos2d-X学习园地QQ群:249941957 [暂满]加群写:Cocos2d-x
本章为我的Cocos2d-x教程一书初稿。望各位看官多提建议!
Cocos2d-x 2.0 网格动画深入分析
另:本章所用Cocos2d-x版本为:
cocos2d-2.0-x-2.0.2 @ Aug 30 2012
http://cn.cocos2d-x.org/download
写在前面:请各位大大在转载博文时注明来源,红孩儿每天熬夜写博实属不易,但屡有一些同学拿来主义,把本博的文章去头掐尾,抹掉作者,然后赤裸裸的改成自已的 " 原创 ",实在令人气愤。在此特声明:本博博文,欢迎您收藏,转载,如果有需要,也可以借用段落或插图,请您经我同意,我不是一个刻板吝啬的人。但如果直接剽窃,我将奋起反击!
在TestCpp中的EffectsTest示例中展示了一些屏幕特效,它是将屏幕划分为多个格子,并对这些格子进行了动画处理从而产生出相应的屏幕特效。今天我们来学习一下这些动画。
主要是涉及到以下几个文件:
CCGrid.h /cpp :网格数据及渲染,包括基本网格数据和3D网格数据,这是数据的基础。
CCActionGrid.h /cpp :网格基本动画,这是动画的基础。
CCActionGrid3D.h/cpp: 3D网格基本动画,这是3D网格动画的基础。
CCActionTiledGrid.h / cpp :网格衍生动画,这是最终的特效实现。
咱们首先来看 关于网格数据及渲染的文件:CCGrid.h
上面讲的是操控网格数据表现一些基本动画的类。下面我们来看一下由这些基本动画的类衍生出来的复杂动画。
打开CCActionTiledGrid.h:
最后我们来看一下EffectsTest的场景演示方面的代码:
EffectsTest.h:
//enum { kTagTextLayer = 1, kTagBackground = 1, kTagLabel = 2,};//动画的索引static int actionIdx=0; //效果标题列表。static std::string effectsList[] ={ "Shaky3D", "Waves3D", "FlipX3D", "FlipY3D", "Lens3D", "Ripple3D", "Liquid", "Waves", "Twirl", "ShakyTiles3D", "ShatteredTiles3D", "ShuffleTiles", "FadeOutTRTiles", "FadeOutBLTiles", "FadeOutUpTiles", "FadeOutDownTiles", "TurnOffTiles", "WavesTiles3D", "JumpTiles3D", "SplitRows", "SplitCols", "PageTurn3D",}; //由CCShaky3D派生出一个动画演示。class Shaky3DDemo : public CCShaky3D {public: //重载其创建函数。 static CCActionInterval* create(float t) { //调用基类相应函数创建一个具体的动画演示。 return CCShaky3D::create(5, false, ccg(15,10), t); }};//由CCWaves3D派生出一个动画演示。class Waves3DDemo : public CCWaves3D {public: //重载其创建函数。 static CCActionInterval* create(float t) { //调用基类相应函数创建一个具体的动画演示。 return CCWaves3D::create(5, 40, ccg(15,10), t); }};//由CCFlipX3D派生出一个动画演示。class FlipX3DDemo : public CCFlipX3D {public: //重载其创建函数。 static CCActionInterval* create(float t) { CCFlipX3D* flipx = CCFlipX3D::create(t); CCActionInterval* flipx_back = flipx->reverse(); CCDelayTime* delay = CCDelayTime::create(2); //调用基类相应函数创建一个具体的动画演示。 return (CCActionInterval*)(CCSequence::create(flipx, delay, flipx_back, NULL)); }};//由CCFlipY3D派生出一个动画演示。class FlipY3DDemo : public CCFlipY3D {public: //重载其创建函数。 static CCActionInterval* create(float t) { CCFlipY3D* flipy = CCFlipY3D::create(t); CCActionInterval* flipy_back = flipy->reverse(); CCDelayTime* delay = CCDelayTime::create(2); //调用基类相应函数创建一个具体的动画演示。 return (CCActionInterval*)(CCSequence::create(flipy, delay, flipy_back, NULL)); }};//由CCLens3D派生出一个动画演示。class Lens3DDemo : public CCLens3D {public: //重载其创建函数。 static CCActionInterval* create(float t) { CCSize size = CCDirector::sharedDirector()->getWinSize(); //调用基类相应函数创建一个具体的动画演示。 return CCLens3D::create(CCPointMake(size.width/2,size.height/2), 240, ccg(15,10), t); }};//由CCRipple3D派生出一个动画演示。class Ripple3DDemo : public CCRipple3D {public: //重载其创建函数。 static CCActionInterval* create(float t) { CCSize size = CCDirector::sharedDirector()->getWinSize(); //调用基类相应函数创建一个具体的动画演示。 return CCRipple3D::create(CCPointMake(size.width/2,size.height/2), 240, 4, 160, ccg(32,24), t); }};//由CCLiquid派生出一个动画演示。class LiquidDemo : public CCLiquid{public: //重载其创建函数。 static CCActionInterval* create(float t) { //调用基类相应函数创建一个具体的动画演示。 return CCLiquid::create(4, 20, ccg(16,12), t); }};//由CCWaves派生出一个动画演示。class WavesDemo : public CCWaves {public: //重载其创建函数。 static CCActionInterval* create(float t) {//调用基类相应函数创建一个具体的动画演示。 return CCWaves::create(4, 20, true, true, ccg(16,12), t); }};//由CCTwirl派生出一个动画演示。class TwirlDemo : public CCTwirl {public: //重载其创建函数。 static CCActionInterval* create(float t) {//调用基类相应函数创建一个具体的动画演示。 CCSize size = CCDirector::sharedDirector()->getWinSize(); return CCTwirl::create(CCPointMake(size.width/2, size.height/2), 1, 2.5f, ccg(12,8), t); }};//由CCShakyTiles3D派生出一个动画演示。class ShakyTiles3DDemo : public CCShakyTiles3D{public: //重载其创建函数。 static CCActionInterval* create(float t) {//调用基类相应函数创建一个具体的动画演示。 return CCShakyTiles3D::create(5, false, ccg(16,12), t) ; }};//由CCShatteredTiles3D派生出一个动画演示。class ShatteredTiles3DDemo : public CCShatteredTiles3D{public: //重载其创建函数。 static CCActionInterval* create(float t) {//调用基类相应函数创建一个具体的动画演示。 return CCShatteredTiles3D::create(5, false, ccg(16,12), t); }};//由CCShuffleTiles派生出一个动画演示。class ShuffleTilesDemo : public CCShuffleTiles{public: //重载其创建函数。 static CCActionInterval* create(float t) { CCShuffleTiles* shuffle = CCShuffleTiles::create(25, ccg(16,12), t); CCActionInterval* shuffle_back = shuffle->reverse(); CCDelayTime* delay = CCDelayTime::create(2);//调用基类相应函数创建一个具体的动画演示。 return (CCActionInterval*)(CCSequence::create(shuffle, delay, shuffle_back, NULL)); }};//由CCFadeOutTRTiles派生出一个动画演示。class FadeOutTRTilesDemo : public CCFadeOutTRTiles{public: //重载其创建函数。 static CCActionInterval* create(float t) { CCFadeOutTRTiles* fadeout = CCFadeOutTRTiles::create(ccg(16,12), t); CCActionInterval* back = fadeout->reverse(); CCDelayTime* delay = CCDelayTime::create(0.5f); //调用基类相应函数创建一个具体的动画演示。 return (CCActionInterval*)(CCSequence::create(fadeout, delay, back, NULL)); }};//由CCFadeOutBLTiles派生出一个动画演示。class FadeOutBLTilesDemo : public CCFadeOutBLTiles{public: //重载其创建函数。 static CCActionInterval* create(float t) { CCFadeOutBLTiles* fadeout = CCFadeOutBLTiles::create(ccg(16,12), t); CCActionInterval* back = fadeout->reverse(); CCDelayTime* delay = CCDelayTime::create(0.5f); //调用基类相应函数创建一个具体的动画演示。 return (CCActionInterval*)(CCSequence::create(fadeout, delay, back, NULL)); }};//由CCFadeOutUpTiles派生出一个动画演示。class FadeOutUpTilesDemo : public CCFadeOutUpTiles{public: //重载其创建函数。 static CCActionInterval* create(float t) { CCFadeOutUpTiles* fadeout = CCFadeOutUpTiles::create(ccg(16,12), t); CCActionInterval* back = fadeout->reverse(); CCDelayTime* delay = CCDelayTime::create(0.5f); //调用基类相应函数创建一个具体的动画演示。 return (CCActionInterval*)(CCSequence::create(fadeout, delay, back, NULL)); }};//由CCFadeOutDownTiles派生出一个动画演示。class FadeOutDownTilesDemo : public CCFadeOutDownTiles{public: //重载其创建函数。 static CCActionInterval* create(float t) { CCFadeOutDownTiles* fadeout = CCFadeOutDownTiles::create(ccg(16,12), t); CCActionInterval* back = fadeout->reverse(); CCDelayTime* delay = CCDelayTime::create(0.5f); //调用基类相应函数创建一个具体的动画演示。 return (CCActionInterval*)(CCSequence::create(fadeout, delay, back, NULL)); }};//由CCTurnOffTiles派生出一个动画演示。class TurnOffTilesDemo : public CCTurnOffTiles{public: //重载其创建函数。 static CCActionInterval* create(float t) { CCTurnOffTiles* fadeout = CCTurnOffTiles::create(25, ccg(48,32) , t); CCActionInterval* back = fadeout->reverse(); CCDelayTime* delay = CCDelayTime::create(0.5f); //调用基类相应函数创建一个具体的动画演示。 return (CCActionInterval*)(CCSequence::create(fadeout, delay, back, NULL)); }};//由CCWavesTiles3D派生出一个动画演示。class WavesTiles3DDemo : public CCWavesTiles3D{public: //重载其创建函数。 static CCActionInterval* create(float t) {//调用基类相应函数创建一个具体的动画演示。 return CCWavesTiles3D::create(4, 120, ccg(15,10), t); }};//由CCJumpTiles3D派生出一个动画演示。class JumpTiles3DDemo : public CCJumpTiles3D{public: //重载其创建函数。 static CCActionInterval* create(float t) { CCSize size = CCDirector::sharedDirector()->getWinSize(); //调用基类相应函数创建一个具体的动画演示。 return CCJumpTiles3D::create(2, 30, ccg(15,10), t); }};//由CCSplitRows派生出一个动画演示。class SplitRowsDemo : public CCSplitRows{public: //重载其创建函数。 static CCActionInterval* create(float t) { //调用基类相应函数创建一个具体的动画演示。 return CCSplitRows::create(9, t); }};//由CCSplitCols派生出一个动画演示。class SplitColsDemo : public CCSplitCols{public: //重载其创建函数。 static CCActionInterval* create(float t) { //调用基类相应函数创建一个具体的动画演示。 return CCSplitCols::create(9, t); }};//由CCPageTurn3D派生出一个动画演示。class PageTurn3DDemo : public CCPageTurn3D{public: //重载其创建函数。 static CCActionInterval* create(float t) { //调用基类相应函数创建一个具体的动画演示。 CCDirector::sharedDirector()->setDepthTest(true); return CCPageTurn3D::create(ccg(15,10), t); }};#define MAX_LAYER 22//创建相应的效果。CCActionInterval* createEffect(int nIndex, float t){ //设置 CCDirector::sharedDirector()->setDepthTest(false); //根据索引来创建相应的动画实例。 switch(nIndex) { case 0: return Shaky3DDemo::create(t); case 1: return Waves3DDemo::create(t); case 2: return FlipX3DDemo::create(t); case 3: return FlipY3DDemo::create(t); case 4: return Lens3DDemo::create(t); case 5: return Ripple3DDemo::create(t); case 6: return LiquidDemo::create(t); case 7: return WavesDemo::create(t); case 8: return TwirlDemo::create(t); case 9: return ShakyTiles3DDemo::create(t); case 10: return ShatteredTiles3DDemo::create(t); case 11: return ShuffleTilesDemo::create(t); case 12: return FadeOutTRTilesDemo::create(t); case 13: return FadeOutBLTilesDemo::create(t); case 14: return FadeOutUpTilesDemo::create(t); case 15: return FadeOutDownTilesDemo::create(t); case 16: return TurnOffTilesDemo::create(t); case 17: return WavesTiles3DDemo::create(t); case 18: return JumpTiles3DDemo::create(t); case 19: return SplitRowsDemo::create(t); case 20: return SplitColsDemo::create(t); case 21: return PageTurn3DDemo::create(t); } return NULL;}//取得相应的动画。CCActionInterval* getAction(){ CCActionInterval* pEffect = createEffect(actionIdx, 3); return pEffect;} //运行当前的场景。void EffectTestScene::runThisTest(){ //创建一个当前的动画演示层放入场景,并运行这个场景。 addChild(TextLayer::create()); CCDirector::sharedDirector()->replaceScene(this);}#define SID_RESTART 1//构造函数。TextLayer::TextLayer(void){ //调用基类LayerColor的初始化函数,设置当前层的背景色。 initWithColor( ccc4(32,128,32,255) ); // float x,y; //取得屏幕大小。 CCSize s = CCDirector::sharedDirector()->getWinSize(); x = s.width; y = s.height; //创建一个节点。 CCNode* node = CCNode::create(); //创建一个动画。 CCActionInterval* effect = getAction(); //将动画绑定到这个节点上。 node->runAction(effect); //将这个节点再放入到当前层中。 addChild(node, 0, kTagBackground); //创建第一个精灵做为背景。 CCSprite *bg = CCSprite::create(s_back3); node->addChild(bg, 0);// bg->setAnchorPoint( CCPointZero ); bg->setPosition(ccp(s.width/2, s.height/2)); //创建第二个精灵(女一号)。 CCSprite* grossini = CCSprite::create(s_pPathSister2); node->addChild(grossini, 1); grossini->setPosition( CCPointMake(x/3,y/2) ); //创建一个缩放动画及对应的反向动画。 CCActionInterval* sc = CCScaleBy::create(2, 5); CCActionInterval* sc_back = sc->reverse(); //让第二个精灵运行相应的动画序列。 grossini->runAction( CCRepeatForever::create((CCActionInterval*)(CCSequence::create(sc, sc_back, NULL)) ) ); //创建第三个精灵。(女二号) CCSprite* tamara = CCSprite::create(s_pPathSister1); node->addChild(tamara, 1);tamara->setPosition( CCPointMake(2*x/3,y/2) );//创建一个缩放动画及对应的反向动画。 CCActionInterval* sc2 = CCScaleBy::create(2, 5); CCActionInterval* sc2_back = sc2->reverse(); //让第三个精灵运行相应的动画序列。tamara->runAction( CCRepeatForever::create((CCActionInterval*)(CCSequence::create(sc2, sc2_back, NULL))) ); //创建一个文字标签。 CCLabelTTF* label = CCLabelTTF::create((effectsList[actionIdx]).c_str(), "Marker Felt", 32); //设置标签的位置并放入当前层中。 label->setPosition( CCPointMake(x/2,y-80) ); addChild(label); label->setTag( kTagLabel ); //创建三个菜单按钮分别代表运行上一个,重新运行当前动画,运行下一个动画。 CCMenuItemImage *item1 = CCMenuItemImage::create(s_pPathB1, s_pPathB2, this, menu_selector(TextLayer::backCallback) ); CCMenuItemImage *item2 = CCMenuItemImage::create(s_pPathR1, s_pPathR2, this, menu_selector(TextLayer::restartCallback) ); CCMenuItemImage *item3 = CCMenuItemImage::create(s_pPathF1, s_pPathF2, this, menu_selector(TextLayer::nextCallback) ); //由三个菜单按钮创建菜单。 CCMenu *menu = CCMenu::create(item1, item2, item3, NULL); //设置相应菜单按钮的位置。 menu->setPosition(CCPointZero); item1->setPosition(CCPointMake( s.width/2 - item2->getContentSize().width*2, item2->getContentSize().height/2)); item2->setPosition(CCPointMake( s.width/2, item2->getContentSize().height/2)); item3->setPosition(CCPointMake( s.width/2 + item2->getContentSize().width*2, item2->getContentSize().height/2)); //将菜单加入当前层中。 addChild(menu, 1); //对当前层调用一个函数。 schedule( schedule_selector(TextLayer::checkAnim) );}//检查动画。void TextLayer::checkAnim(float dt){ //取得对应结点。CCNode* s2 = getChildByTag(kTagBackground);//判断如果没有正在运行中的动画,并且其有格子数据,则将其格子数据释放并置空。 if ( s2->numberOfRunningActions() == 0 && s2->getGrid() != NULL) s2->setGrid(NULL);;}//析构。TextLayer::~TextLayer(void){}//创建一个当前层的函数。TextLayer* TextLayer::create(){ TextLayer* pLayer = new TextLayer(); pLayer->autorelease(); return pLayer;}//当前层被加载时的处理。void TextLayer::onEnter(){ CCLayer::onEnter();}//创建一个新场景。void TextLayer::newScene(){ CCScene* s = new EffectTestScene(); CCNode* child = TextLayer::create(); s->addChild(child); CCDirector::sharedDirector()->replaceScene(s); s->release();}//重启当前动画演示。void TextLayer::restartCallback(CCObject* pSender){ newScene();}//前进到下一个动画演示。void TextLayer::nextCallback(CCObject* pSender){ // update the action index actionIdx++; actionIdx = actionIdx % MAX_LAYER; newScene();}//回退到上一个动画演示。void TextLayer::backCallback(CCObject* pSender){ // update the action index actionIdx--; int total = MAX_LAYER; if( actionIdx < 0 ) actionIdx += total; newScene();}最后做个总结:
Cocos2d-x提供了屏幕画面上的一些基于网格的动画,首先将要渲染的画面输出到一张纹理上,然后跟据屏幕大小创建相应数量的网格,通过对于网格上的顶点进行改变,形成顶点的运动动画,然后将纹理贴在网格上再绘制出来,就能够出现很多屏幕特效了。
觉得怎么样?是不是恍然大悟呢?如果有这样的感觉,则我的辛苦就没有白费。
最后,祝大家元旦快乐!2013年新的一年有更大的飞跃!
- 2楼alphaJH27分钟前
- 顶起呀!
- 1楼jaoye6179小时前
- 好东西 又要学习了