Cocos2d-x 2.0 之 Actions “三板斧” 之三

[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 TestCpp 之 ActionsTest深入分析

另:本章所用Cocos2d-x版本为:

cocos2d-2.0-x-2.0.2 @ Aug 30 2012

http://cn.cocos2d-x.org/download

  之前两斧子,相信大家已经对于动画的原理有了比较清楚的了解,这最后一斧子,咱们一起看一看ActionsTest.hcpp。我们打开头文件来看一下代码:

#ifndef _ActionsTest_H_
#define _ActionsTest_H_
//包含示例的基本头文件,因为要用到演示场景基类TestScene。这个类在之前的TestCpp框架分析中有讲解。
#include "../testBasic.h"
////----#include "cocos2d.h"
//使用Cocos2d的命名空间
USING_NS_CC;
//这里是一个枚举,列出了示例中所有的精灵动画类型
enum
{
    ACTION_MANUAL_LAYER = 0,//基本状态
    ACTION_MOVE_LAYER,		//移动动画
    ACTION_SCALE_LAYER,		//缩放动画
    ACTION_ROTATE_LAYER,		//旋转动画
    ACTION_SKEW_LAYER,		//扭曲动画
    ACTION_SKEWROTATE_LAYER,//扭曲与旋转组合动画
    ACTION_JUMP_LAYER,		//跳跃动画
    ACTION_CARDINALSPLINE_LAYER,//贝塞尔曲线动画
    ACTION_CATMULLROM_LAYER,//点构成的曲线动画
    ACTION_BEZIER_LAYER,		//贝塞尔曲线路径动画
    ACTION_BLINK_LAYER,		//闪现动画
    ACTION_FADE_LAYER,		//淡入淡出动画
    ACTION_TINT_LAYER,		//变色动画
    ACTION_ANIMATE_LAYER,	//帧动画
    ACTION_SEQUENCE_LAYER,	//动画序列
    ACTION_SEQUENCE2_LAYER,	//动画序列
    ACTION_SPAWN_LAYER,		//动画组合
    ACTION_REVERSE,			//反向播放动画
    ACTION_DELAYTIME_LAYER,	//动画暂停与继续播放
    ACTION_REPEAT_LAYER,		//重复播放动画
    ACTION_REPEATEFOREVER_LAYER,//无限循环播放动画
    ACTION_ROTATETOREPEATE_LAYER,//循环旋转动画一
    ACTION_ROTATEJERK_LAYER,//循环旋转动画二
    ACTION_CALLFUNC_LAYER,//动画与函数调用一
    ACTION_CALLFUNCND_LAYER,//动画与函数调用二
    ACTION_REVERSESEQUENCE_LAYER,//反向动画序列。
    ACTION_REVERSESEQUENCE2_LAYER,//反向动画序列二。
    ACTION_ORBIT_LAYER,//旋转摄像机动画
    ACTION_FLLOW_LAYER,//跟随动画
    ACTION_TARGETED_LAYER,//控制目标动画
    PAUSERESUMEACTIONS_LAYER,//暂停与恢复动画
    ACTION_ISSUE1305_LAYER,//1305号动画
    ACTION_ISSUE1305_2_LAYER,//1305号的动画二
    ACTION_ISSUE1288_LAYER,//1288号动画
    ACTION_ISSUE1288_2_LAYER,//1288的动画二
    ACTION_ISSUE1327_LAYER,//1327号动画
    ACTION_LAYER_COUNT,//动画最大数量
};

//看完这些枚举,我想说的是,精灵动画的类型真TMD丰富啊!竟然多到想不出名字~:)

//这是用于展示每种动画的基础场景类,它包含了一个返回主菜单的按钮。
class ActionsTestScene : public TestScene
{
public:
	//重虚函数runThisTest做一些初始化工作。
    virtual void runThisTest();
};
为了方便代码阅读,我将CPP中相应函数实现移过来,后面都按这种格式:
//演示动画所用场景基类的初始化函数重载
void ActionsTestScene::runThisTest()
{
	//先将索引置-1,后面调用NextAction()使其加1变为0,即演示第一个动画。
    s_nActionIdx = -1;
    addChild(NextAction());
	//运行当前场景。
    CCDirector::sharedDirector()->replaceScene(this);
}



//从CCLayer派生出一个基础的动画演示类,用于包含要表现动作的一些精灵。
class ActionsDemo : public CCLayer
{
protected:
	//动画的主角要出场啦!以下是三个图片精灵实例指针,其分别指向出场表演的男1号grossini,女1号tamara,女2号kathia,这一男两女将成为动画演示的三位演员。大家欢迎它们!
    CCSprite*    m_grossini;
    CCSprite*    m_tamara;
    CCSprite*    m_kathia;
public:
	//重载当前动画类被载入时要调用的函数onEnter做一些精灵生成的处理。
    virtual void onEnter();
	//重载当前动画类被卸载时要调用的函数onExit做一些释放处理。
    virtual void onExit();
	//这个函数用于指定需要几位演员出场时如果要求居中对齐该怎么站位。
    void centerSprites(unsigned int numberOfSprites);
	//这个函数用于指定需要几位演员出场时如果要求居左对齐该怎么站位。
    void alignSpritesLeft(unsigned int numberOfSprites);
	//取得动画的主标题
    virtual std::string title();
	//取得动画的副标题
    virtual std::string subtitle();
	//当在点击“重置”按钮时的回调函数
    void restartCallback(CCObject* pSender);
	//当在点击“下一个”按钮时的回调函数
    void nextCallback(CCObject* pSender);
	//当在点击“上一个”按钮时的回调函数。
    void backCallback(CCObject* pSender);
};
//取得演示动画CCLayer所用基类的主标题
std::string ActionsDemo::title()
{
    return "ActionsTest";
}
//取得演示动画CCLayer所用基类的副标题
std::string ActionsDemo::subtitle()
{
    return "";
}
//加载演示动画CCLayer所用基类时的初始化处理函数。
void ActionsDemo::onEnter()
{
    CCLayer::onEnter();

	//创建了三个演员。
	//男一号,其使用图片地址为s_pPathGrossini
    m_grossini = CCSprite::create(s_pPathGrossini);
    m_grossini->retain();

	//女一号,其使用图片地址为s_pPathSister1
    m_tamara = CCSprite::create(s_pPathSister1); 
	m_tamara->retain();
	
	//女二号,其使用图片地址为s_pPathSister2
    m_kathia = CCSprite::create(s_pPathSister2);
	m_kathia->retain();
	
	//将三位演员都放入当前演示动画所在的CCLayer中。
    addChild(m_grossini, 1);
    addChild(m_tamara, 2);
    addChild(m_kathia, 3);
	//取得屏幕的大小
    CCSize s = CCDirector::sharedDirector()->getWinSize();
	//男一号站在屏幕中下位置
	m_grossini->setPosition(CCPointMake(s.width/2, s.height/3));
	//女一号站在屏幕中上位置
	m_tamara->setPosition(CCPointMake(s.width/2, 2*s.height/3));
	//女二号站在屏幕正中间
    m_kathia->setPosition(CCPointMake(s.width/2, s.height/2)); 

    // 创建一个文字标签用于显示标题
    std::string str = title();
    const char * pTitle = str.c_str();
    CCLabelTTF* label = CCLabelTTF::create(pTitle, "Arial", 18);
    addChild(label, 1);
	//将文字标签放在屏幕正中靠上位置
    label->setPosition( CCPointMake(s.width/2, s.height - 30) );
	//创建一个文字标签用于显示副标题
    std::string strSubtitle = subtitle();
    if( ! strSubtitle.empty() ) 
    {
		//创建文件标签并放在主标题文字标签之下。
        CCLabelTTF* l = CCLabelTTF::create(strSubtitle.c_str(), "Thonburi", 22);
        addChild(l, 1);
        l->setPosition( CCPointMake(s.width/2, s.height - 60) );
    }    

    // 创建三个按钮(看名字应理解为图片菜单项,其实就是具有普通和按下两种状态的图片切换效果的按钮)用于控制演示的动画。
	// 第一个按钮,在按下时调用演示上一个动画的函数。
    CCMenuItemImage *item1 = CCMenuItemImage::create(s_pPathB1, s_pPathB2, this, menu_selector(ActionsDemo::backCallback) );
	// 第二个按钮,在按下时调用重新演示当前动画的函数。
    CCMenuItemImage *item2 = CCMenuItemImage::create(s_pPathR1, s_pPathR2, this, menu_selector(ActionsDemo::restartCallback) );
	// 第三个按钮,在按下时调用演示下一个动画的函数。
    CCMenuItemImage *item3 = CCMenuItemImage::create(s_pPathF1, s_pPathF2, this, menu_selector(ActionsDemo::nextCallback) );
	//由这三个按钮(也就是刚说的“图片菜单项”)生成一个菜单。因为CMenuItemImage和CCMenu都是CCNode的子类。所以这一句本质上是将若干CCNode做为一个新的CCNode的子节点并返回。
    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));
	//将菜单加入当前的演示动画CCLayer所用基类中。
    addChild(menu, 1);
}
//在当前演示动画CCLayer所用基类被释放时的处理函数
void ActionsDemo::onExit()
{
	//精灵的释放,代表三位演员的退场。
    m_grossini->release();
    m_tamara->release();
    m_kathia->release();

    CCLayer::onExit();
}
//重新演示当前动画的回调函数。
void ActionsDemo::restartCallback(CCObject* pSender)
{
	//创建一个新场景
    CCScene* s = new ActionsTestScene();
	//将RestartAction()函数返回的CCLayer加入场景中。
    s->addChild( RestartAction() );
	//将新场景做为游戏要显示的场景。
    CCDirector::sharedDirector()->replaceScene(s);
	//引用计数器减1操作,以使未来可以正确的被释放。
    s->release();
}
//演示下一个动画的回调函数。
void ActionsDemo::nextCallback(CCObject* pSender)
{
	//创建一个新场景
    CCScene* s = new ActionsTestScene();
	//将NextAction()函数返回的CCLayer加入场景中。
    s->addChild( NextAction() );
	//将新场景做为游戏要显示的场景。
    CCDirector::sharedDirector()->replaceScene(s);
	//引用计数器减1操作,以使未来可以正确的被释放。
    s->release();
}
//演示上一个动画的回调函数。
void ActionsDemo::backCallback(CCObject* pSender)
{
	//创建一个新场景
    CCScene* s = new ActionsTestScene();
	//将BackAction ()函数返回的CCLayer加入场景中。
    s->addChild( BackAction() );
	//将新场景做为游戏要显示的场景。
    CCDirector::sharedDirector()->replaceScene(s);
	//引用计数器减1操作,以使未来可以正确的被释放。
    s->release();
}
//这个函数用于指定需要几位演员出场时如果要求居中对齐该怎么站位。
void ActionsDemo::centerSprites(unsigned int numberOfSprites)
{
	//取得屏幕大小
    CCSize s = CCDirector::sharedDirector()->getWinSize();
    if( numberOfSprites == 0 )
    {	//如果指定没有演员,将三位演员都设为不显示
        m_tamara->setVisible(false);
        m_kathia->setVisible(false);
        m_grossini->setVisible(false);
    } 
    else if ( numberOfSprites == 1 ) 
    {	//如果指定只有一位演员来表演,则将男一号放在屏幕中央,两位女演员设为不显示。
        m_tamara->setVisible(false);
        m_kathia->setVisible(false);
        m_grossini->setPosition(CCPointMake(s.width/2, s.height/2));
    }
    else if( numberOfSprites == 2 ) 
    {   //如果指定两位演员来表演,则将两位女演员放在屏幕中心位置对齐的两边,并将男演员设为不显示。     
        m_kathia->setPosition( CCPointMake(s.width/3, s.height/2));
        m_tamara->setPosition( CCPointMake(2*s.width/3, s.height/2));
        m_grossini->setVisible(false);
    } 
    else if( numberOfSprites == 3 ) 
    {	//三位演员同时上场,分别放在屏幕左,中,右三个位置。
        m_grossini->setPosition( CCPointMake(s.width/2, s.height/2));
        m_tamara->setPosition( CCPointMake(s.width/4, s.height/2));
        m_kathia->setPosition( CCPointMake(3 * s.width/4, s.height/2));
    }
}
//这个函数用于指定需要几位演员出场时如果要求居左对齐该怎么站位。同上,只是位置略有差别。
void ActionsDemo::alignSpritesLeft(unsigned int numberOfSprites)
{
    CCSize s = CCDirector::sharedDirector()->getWinSize();

    if( numberOfSprites == 1 ) 
    {
        m_tamara->setVisible(false);
        m_kathia->setVisible(false);
        m_grossini->setPosition(CCPointMake(60, s.height/2));
    } 
    else if( numberOfSprites == 2 ) 
    {        
        m_kathia->setPosition( CCPointMake(60, s.height/3));
        m_tamara->setPosition( CCPointMake(60, 2*s.height/3));
        m_grossini->setVisible( false );
    } 
    else if( numberOfSprites == 3 ) 
    {
        m_grossini->setPosition( CCPointMake(60, s.height/2));
        m_tamara->setPosition( CCPointMake(60, 2*s.height/3));
        m_kathia->setPosition( CCPointMake(60, s.height/3));
    }
}



//这是第一个要演示的动画,其实它只是把三位演员显示出来。
class ActionManual : public ActionsDemo
{
public:
	//重载当前动画类被载入时要调用的函数onEnter做一些精灵生成的处理。
    virtual void onEnter();
	//重载取得动画的副标题
    virtual std::string subtitle();
};
//基础演示动画所用CCLayer被加载时的初始化处理函数。
void ActionManual::onEnter()
{	//调用基类的同名函数,加载三位演员。
    ActionsDemo::onEnter();
	//取得屏幕的大小
    CCSize s = CCDirector::sharedDirector()->getWinSize();
	//将女一号演员在X,Y方向上分别缩放后放在相应位置,并设置其半透明。
    m_tamara->setScaleX( 2.5f);
    m_tamara->setScaleY( -1.0f);
    m_tamara->setPosition( CCPointMake(100,70) );
	//透明度的取值为0~255,0代表完全透明,255代表完全不透明。
    m_tamara->setOpacity( 128);

	//男一号演员,这里让它旋转120度之后放在屏幕中心位置,并设置其全身颜色为红色。
    m_grossini->setRotation( 120);
    m_grossini->setPosition( CCPointMake(s.width/2, s.height/2));
	//色彩设置为红色。ccc3分别用R,G,B三元色做为参数返回色彩值。
    m_grossini->setColor( ccc3( 255,0,0));
	//女二号演员,这里设置位置为屏幕中心靠左。
    m_kathia->setPosition( CCPointMake(s.width-100, s.height/2));
	//色彩设置为蓝色,这以用预定义的宏ccBLUE来代表蓝色的色彩值。
    m_kathia->setColor( ccBLUE);
}
//取得当前演示动画的副标题。
std::string ActionManual::subtitle()
{
    return "Manual Transformation";
}


//第二种动画演示表现了三位演员的移动变化。
class ActionMove : public ActionsDemo
{
public:
    virtual void onEnter();
    virtual std::string subtitle();
};
//移动动画所用CCLayer被加载时的初始化处理函数。
void ActionMove::onEnter()
{	//调用基类的同名函数,加载三位演员。
    ActionsDemo::onEnter();
	//让三位演员以居中对齐方式进行站位。
    centerSprites(3);
	//取得屏幕的大小
    CCSize s = CCDirector::sharedDirector()->getWinSize();
	//创建三个时间渐变动画。第一个是由CCActionInterval子类CCMoveTo静态函数所创建的“2秒移动到某位置”,第二个是由CCActionInterval子类CCMoveTo静态函数所创建的“2秒移动多少距离”。第三个是第二个动画的反向播放。
    CCActionInterval*  actionTo = CCMoveTo::create(2, CCPointMake(s.width-40, s.height-40));
    CCActionInterval*  actionBy = CCMoveBy::create(2, CCPointMake(80,80));
    CCActionInterval*  actionByBack = actionBy->reverse();
	//让三个演员分别按照不同的动画形式来演示。女一号就按第一种动画来进行演示。
    m_tamara->runAction( actionTo);
	//男一号呢?它的演示是第二个动画和第三个动画的串联。CCSequence::create函数可以将多个动画串联在一起,按照串联的顺序进行逐个播放。
    m_grossini->runAction( CCSequence::create(actionBy, actionByBack, NULL));
	//女二号同女一号类似也是演示一个移动到某位置的动画。这里指定1秒内移动到40,40的位置。
    m_kathia->runAction(CCMoveTo::create(1, CCPointMake(40,40)));
}
//这里取得移动动画演示的副标题。
std::string ActionMove::subtitle()
{
    return "MoveTo / MoveBy";
}

//第三种动画演示表现了三位演员的缩放变化。
class ActionScale : public ActionsDemo
{
public:
    virtual void onEnter();
    virtual std::string subtitle();
};
//缩放动画演示
void ActionScale::onEnter()
{	
	//动画演示的初始化
    ActionsDemo::onEnter();
	//将三个演员按居中对齐进行站位
    centerSprites(3);
	//三个要演示的动画形式分别是
	//1.缩放到指定的程度
    CCActionInterval*  actionTo = CCScaleTo::create(2.0f, 0.5f);
	//2.当前缩放值再续继缩放多少
    CCActionInterval*  actionBy = CCScaleBy::create(2.0f, 1.0f, 10.0f);
	//3.同2
    CCActionInterval*  actionBy2 = CCScaleBy::create(2.0f, 5.0f, 1.0f);
	//让男一号演示动画1
    m_grossini->runAction( actionTo);
	//让女一号演示一个动画序列,这个序列为先演示动画2,再演示动画2的反向播放。
    m_tamara->runAction( CCSequence::create(actionBy, actionBy->reverse(), NULL));
	//女二号的动画同女一号
    m_kathia->runAction( CCSequence::create(actionBy2, actionBy2->reverse(), NULL));
}
//副标题
std::string ActionScale::subtitle()
{
    return "ScaleTo / ScaleBy";
}

//第四种动画演示表现了三位演员的旋转变化
class ActionRotate : public ActionsDemo
{
public:
    virtual void onEnter();
    virtual std::string subtitle();
};
void ActionRotate::onEnter()
{
	//动画演示的初始化
    ActionsDemo::onEnter();
	//将三个演员按居中对齐进行站位
    centerSprites(3);
	//定义几种旋转到某个角度的动画
    CCActionInterval*  actionTo = CCRotateTo::create( 2, 45);
    CCActionInterval*  actionTo2 = CCRotateTo::create( 2, -45);
    CCActionInterval*  actionTo0 = CCRotateTo::create(2 , 0);
	//女一号演示一个动画序列
    m_tamara->runAction( CCSequence::create(actionTo, actionTo0, NULL));
	//定义从现在的角度在2秒内继续旋转360度的动画
    CCActionInterval*  actionBy = CCRotateBy::create(2 ,  360);
	//定义actionBy的反向播放动画
    CCActionInterval*  actionByBack = actionBy->reverse();
	//男一号演示一个动画序列
    m_grossini->runAction( CCSequence::create(actionBy, actionByBack, NULL));
	//女二号演示一个动画序列,这个动画序列中有一个动画为actionTo0的拷贝,并将这个拷贝设为由内存管理器进行内存释放。这句里有两个知识点:(1)为什么要使用动画的拷贝?(2)为什么要调用autorelease?答案分别是:(1)目前的引擎机制要求每个动画只能有一个演员使用。当你调用runAction时会将动画加入动画管理器,而动画管理器调用addAction函数时,会在最后调用pAction->startWithTarget(pTarget);如果这个动画已经有一个演员在使用了,这里会覆盖掉之前的演员信息,动画只能被最后使用的演员占有。(2)因为create函数创建动画时,会在内部对动画调用autorelease,而copy函数只会新生成一个动画的复制品,不会对其进行调用autorelease。
    m_kathia->runAction( CCSequence::create(actionTo2, actionTo0->copy()->autorelease(), NULL));
}
//显示副标题
std::string ActionRotate::subtitle()
{
    return "RotateTo / RotateBy";
}

//第五种动画演示表现了三位演员的扭曲变化。
class ActionSkew : public ActionsDemo
{
    virtual void onEnter();
    virtual std::string subtitle();
};
void ActionSkew::onEnter()
{	
	//动画演示的初始化
    ActionsDemo::onEnter();
	//将三个演员按居中对齐进行站位
    centerSprites(3);
	//这里定义了五种动画
	//前两种动画是扭曲到指定程度
    CCActionInterval *actionTo = CCSkewTo::create(2, 37.2f, -37.2f);
    CCActionInterval *actionToBack = CCSkewTo::create(2, 0, 0);
	//然后两种动画是继续扭曲多少
    CCActionInterval *actionBy = CCSkewBy::create(2, 0.0f, -90.0f);
    CCActionInterval *actionBy2 = CCSkewBy::create(2, 45.0f, 45.0f);
	//最后一种动画是actionBy的反向播放
    CCActionInterval *actionByBack = actionBy->reverse();
	//女一号演示一个动画序列,这个动画序列有两个动画,先是actionTo,然后是actionToBack
    m_tamara->runAction(CCSequence::create(actionTo, actionToBack, NULL));
	//男一号演示一个动画序列,这个动画序列有两个动画,先是actionBy,然后是actionByBack
    m_grossini->runAction(CCSequence::create(actionBy, actionByBack, NULL));
	//女二号演示一个动画序列,这个动画序列也是有两个动画,先是actionBy2,然后是它的反向播放。
    m_kathia->runAction(CCSequence::create(actionBy2, actionBy2->reverse(), NULL));
}
//副标题
string ActionSkew::subtitle()
{
    return "SkewTo / SkewBy";
}

//第六种动画演示表现的是前面几种变化的大杂烩。
class ActionSkewRotateScale : public ActionsDemo
{
    virtual void onEnter();
    virtual std::string subtitle();
};
void ActionSkewRotateScale::onEnter()
{
	//动画演示的初始化
    ActionsDemo::onEnter();
	//本动画用不到三位演员,在此将它们删除
    m_tamara->removeFromParentAndCleanup(true);
    m_grossini->removeFromParentAndCleanup(true);
    m_kathia->removeFromParentAndCleanup(true);
	//这里取得一个宽高均为100的大小
    CCSize boxSize = CCSizeMake(100.0f, 100.0f);
	//创建一个颜色层
    CCLayerColor *box = CCLayerColor::create(ccc4(255, 255, 0, 255));
	//设置锚点为左下角
    box->setAnchorPoint(ccp(0, 0));
	//设置当前颜色层的位置
    box->setPosition(ccp(190, 110));
	//设置颜色色的大小
    box->setContentSize(boxSize);
	//在颜色层上再加立两个子颜色层。
	//第一个是红色,放在左上角。
    static float markrside = 10.0f;
    CCLayerColor *uL = CCLayerColor::create(ccc4(255, 0, 0, 255));
    box->addChild(uL);
    uL->setContentSize(CCSizeMake(markrside, markrside));
    uL->setPosition(ccp(0.f, boxSize.height - markrside));
    uL->setAnchorPoint(ccp(0, 0));
	//第二个是蓝色,放在右上角。
    CCLayerColor *uR = CCLayerColor::create(ccc4(0, 0, 255, 255));
    box->addChild(uR);
    uR->setContentSize(CCSizeMake(markrside, markrside));
    uR->setPosition(ccp(boxSize.width - markrside, boxSize.height - markrside));
    uR->setAnchorPoint(ccp(0, 0));
    addChild(box);
	//定义几种动画,分别为扭曲,旋转,缩放。
    CCActionInterval *actionTo = CCSkewTo::create(2, 0.f, 2.f);
    CCActionInterval *rotateTo = CCRotateTo::create(2, 61.0f);
    CCActionInterval *actionScaleTo = CCScaleTo::create(2, -0.44f, 0.47f);

    CCActionInterval *actionScaleToBack = CCScaleTo::create(2, 1.0f, 1.0f);
    CCActionInterval *rotateToBack = CCRotateTo::create(2, 0);
    CCActionInterval *actionToBack = CCSkewTo::create(2, 0, 0);
	//让颜色层同时演示三个动画序列。这里要理解为什么它可以同时演示多个动画序列?我们之前将过runAction会将演员和动画通知动画管理器,这些动画会存入相应的动画集,动画管理器在每帧会更新相应的动画,这里虽然用的是动画序列,但是动画序列本身仍然是动画。所以调用多次runAction可以将多个动画或动画序列同时播放。
    box->runAction(CCSequence::create(actionTo, actionToBack, NULL));
    box->runAction(CCSequence::create(rotateTo, rotateToBack, NULL));
    box->runAction(CCSequence::create(actionScaleTo, actionScaleToBack, NULL));
}
//取得副标题。
string ActionSkewRotateScale::subtitle()
{
    return "Skew + Rotate + Scale";
}

//第七种动画演示表现的是如何让演员们按照抛物线跳跃。
class ActionJump : public ActionsDemo
{
public:
    virtual void onEnter();
    virtual std::string subtitle();
};
void ActionJump::onEnter()
{
	//动画演示的初始化
    ActionsDemo::onEnter();
	//将三个演员按居中对齐进行站位
    centerSprites(3);
	//定义一个动画,代表跳跃到某个位置
    CCActionInterval*  actionTo = CCJumpTo::create(2, CCPointMake(300,300), 50, 4);
	//定义一个动画,代表从现在的位置跳跃多远距离。
    CCActionInterval*  actionBy = CCJumpBy::create(2, CCPointMake(300,0), 50, 4);
	//定义一个只是向上跳的动画
    CCActionInterval*  actionUp = CCJumpBy::create(2, CCPointMake(0,0), 80, 4);
	//定义第二个动画的反向播放动画
    CCActionInterval*  actionByBack = actionBy->reverse();
	//三位演员分别运行相应动画。
    m_tamara->runAction( actionTo);
    m_grossini->runAction( CCSequence::create(actionBy, actionByBack, NULL));
	//CCRepeatForever是一个无限循环动画。它将指定的动画进行无限循环播放。
    m_kathia->runAction( CCRepeatForever::create(actionUp));
}
//显示副标题。
std::string ActionJump::subtitle()
{
    return "JumpTo / JumpBy";
}

//第八种动画演示表现的是让演员们按照贝塞尔曲线的路径运动。
class ActionBezier : public ActionsDemo
{
public:
    virtual void onEnter();
    virtual std::string subtitle();
};
void ActionBezier::onEnter()
{
	//动画演示的初始化
    ActionsDemo::onEnter();
	//取得屏幕大小
    CCSize s = CCDirector::sharedDirector()->getWinSize();

	//将三位演员按居中对齐进行站位
    centerSprites(3);

    // 创建第一个贝塞尔曲线
    ccBezierConfig bezier;
    bezier.controlPoint_1 = CCPointMake(0, s.height/2);
    bezier.controlPoint_2 = CCPointMake(300, -s.height/2);
    bezier.endPosition = CCPointMake(300,100);
	//创建一个贝塞尔曲线动画,这个CCBezierBy的意思是当前位置为曲线起点。曲线的其它点是相对于它的位置。
    CCActionInterval*  bezierForward = CCBezierBy::create(3, bezier);
	//创建上面动画的反向播放动画。
    CCActionInterval*  bezierBack = bezierForward->reverse();    
	//创建一个无限循环动画序列,这个动画序列由上面两个动画组成。    CCAction*  rep = CCRepeatForever::create((CCActionInterval*)CCSequence::create( bezierForward, bezierBack, NULL));


    // 创建第二个贝塞尔曲线
	// 设置一下女一号的当前位置。
    m_tamara->setPosition(CCPointMake(80,160));
    ccBezierConfig bezier2;
    bezier2.controlPoint_1 = CCPointMake(100, s.height/2);
    bezier2.controlPoint_2 = CCPointMake(200, -s.height/2);
    bezier2.endPosition = CCPointMake(240,160);
	//创建一个贝塞尔曲线动画,这个CCBezierTo的意思是演员当前位置为曲线起点。曲线的其它点是屏幕的绝对位置。
    CCActionInterval*  bezierTo1 = CCBezierTo::create(2, bezier2);    

    //设置一下女二号的当前位置。创建相同的动画。
    m_kathia->setPosition(CCPointMake(400,160));
	//如果刚才的ActionRotate 您理解的透彻,那这里其实也可以改成:CCActionInterval*  bezierTo2 = (CCActionInterval*)(bezierTo1->copy()->autorelease());

    CCActionInterval*  bezierTo2 = CCBezierTo::create(2, bezier2);
	//三位演员开始动画演示。
    m_grossini->runAction( rep);
    m_tamara->runAction(bezierTo1);
    m_kathia->runAction(bezierTo2);

}
//显示副标题。
std::string ActionBezier::subtitle()
{
    return "BezierBy / BezierTo";
}

//第九种动画演示表现的是演员们玩“我闪我闪乱你眼”
class ActionBlink : public ActionsDemo
{
public:
    virtual void onEnter();
    virtual std::string subtitle();
};
void ActionBlink::onEnter()
{
	//动画演示的初始化
    ActionsDemo::onEnter();
	//将二位女演员按居中对齐进行站位
    centerSprites(2);
	//这个CCBlink的create简单,就是指定几秒内共闪动几次。
    CCActionInterval*  action1 = CCBlink::create(2, 10);
    CCActionInterval*  action2 = CCBlink::create(2, 5);
	//两位演员开始表演“闪闪惹人爱”
    m_tamara->runAction( action1);
    m_kathia->runAction(action2);
}
//显示副标题。
std::string  ActionBlink::subtitle()
{
    return "Blink";
}


//第十种动画演示表现的是演员们淡入淡出
class ActionFade : public ActionsDemo
{
public:
    virtual void onEnter();
    virtual std::string subtitle();
};
void ActionFade::onEnter()
{
	//动画演示的初始化
    ActionsDemo::onEnter();
	//将二位女演员按居中对齐进行站位
    centerSprites(2);
	//设置女一号的透明度为0
    m_tamara->setOpacity( 0 );
	//CCFadeIn是一个淡入动画,参数为秒数。代表需要多久显示。
    CCActionInterval*  action1 = CCFadeIn::create(1.0f);
	//淡入的反向播放,其时是从算法上实现了淡出。
    CCActionInterval*  action1Back = action1->reverse();
	//CCFadeOut是一个淡出动画。参数为秒数。代表需要多久消融。
    CCActionInterval*  action2 = CCFadeOut::create(1.0f);
	//淡入的反向播放,其时是从算法上实现了淡入。
    CCActionInterval*  action2Back = action2->reverse();
	//两位女演员各自演员一个动画序列。
    m_tamara->runAction( CCSequence::create( action1, action1Back, NULL));
    m_kathia->runAction( CCSequence::create( action2, action2Back, NULL));
}
//显示副标题。
std::string  ActionFade::subtitle()
{
    return "FadeIn / FadeOut";
}

//第十一种动画演示表现的是演员们如何进行色彩渐变。
class ActionTint : public ActionsDemo
{
public:
    virtual void onEnter();
    virtual std::string subtitle();
};
void ActionTint::onEnter()
{
	//动画演示的初始化
    ActionsDemo::onEnter();
	//将二位女演员按居中对齐进行站位
    centerSprites(2);
	//创建三个变色动画,第一个是2秒时间变化到指定的色值。第二个是2秒时间从当前色彩状态变化多少色值,第三个是第二个动画的反向动画。
    CCActionInterval*  action1 = CCTintTo::create(2, 255, 0, 255);
    CCActionInterval*  action2 = CCTintBy::create(2, -127, -255, -127);
    CCActionInterval*  action2Back = action2->reverse();
	//女一号运行动画1。
    m_tamara->runAction( action1);
	//女二号运行一个动画序列,这个动画序列先运行动画2,然后运行动画3。
    m_kathia->runAction( CCSequence::create( action2, action2Back, NULL));
}

std::string  ActionTint::subtitle()
{
    return "TintTo / TintBy";
}


//第十二种动画演示表现的是演员的逐帧动作动画。
class ActionAnimate : public ActionsDemo
{
public:
    virtual void onEnter();
    virtual void onExit();
    virtual std::string title();
    virtual std::string subtitle();
};
void ActionAnimate::onEnter()
{
	//动画演示的初始化
    ActionsDemo::onEnter();
	//将三位演员按居中对齐进行站位
    centerSprites(3);
	//创建一个序列帧动画。
    CCAnimation* animation = CCAnimation::create();
	//载入15张图片做为每帧显示的精灵图片。
    for( int i=1;i<15;i++)
    {
        char szName[100] = {0};
        sprintf(szName, "Images/grossini_dance_%02d.png", i);
        animation->addSpriteFrameWithFileName(szName);
    }
    //设置帧间隔时间。
    animation->setDelayPerUnit(2.8f / 14.0f);
	//设置动画结束后保持初始帧数据不进行释放。
    animation->setRestoreOriginalFrame(true);
	//创建序列帧动画。
    CCAnimate* action = CCAnimate::create(animation);
	//男一号动行一个动画序列,这个动画序列先播放一遍序列帧动画,然后再反向播放一遍序列帧动画。
    m_grossini->runAction(CCSequence::create(action, action->reverse(), NULL));
    
    //下面演示了通过一个plist文件来播放一个序列帧动画。
	//先取得序列帧动画管理器。
    CCAnimationCache *cache = CCAnimationCache::sharedAnimationCache();
	//加载一个plist文件
    cache->addAnimationsWithFile("animations/animations-2.plist");
	//取得plist文件中的对应序列帧动画信息
    CCAnimation *animation2 = cache->animationByName("dance_1");
	//以此信息创建一个序列帧动画。
    CCAnimate* action2 = CCAnimate::create(animation2);
	//女一号运行一个动画序列,这个动画序列先播放一遍序列帧动画,然后再反向播放一遍序列帧动画。
    m_tamara->runAction(CCSequence::create(action2, action2->reverse(), NULL));

	//产生一个plist文件中的对应序列帧动画信息的拷贝
    CCAnimation *animation3 = (CCAnimation *)animation2->copy()->autorelease();
	//设置动画信息中的动画循环次数
    animation3->setLoops(4);
	//以此信息创建一个序列帧动画。
    CCAnimate* action3 = CCAnimate::create(animation3);
	//女二号运行此动画。
    m_kathia->runAction(action3);
}

void ActionAnimate::onExit()
{
    ActionsDemo::onExit();
    //TODO:[[NSNotificationCenter defaultCenter] removeObserver:observer_];
}

std::string ActionAnimate::title()
{
    return "Animation";
}

std::string ActionAnimate::subtitle()
{
    return "Center: Manual animation. Border: using file format animation";
}

//第十三种动画演示的是多种动画如何组成动画序列。
class ActionSequence : public ActionsDemo
{
public:
    virtual void onEnter();
    virtual std::string subtitle();
};

void ActionSequence::onEnter()
{
	//动画演示的初始化
    ActionsDemo::onEnter();
	//只需要男一号上场
    alignSpritesLeft(1);
	//创建一个动画序列,先运行一个移动动画,再运行一个旋转动画。
    CCFiniteTimeAction*  action = CCSequence::create(
        CCMoveBy::create( 2, CCPointMake(240,0)),
        CCRotateBy::create( 2,  540),
        NULL);
	//男一号演示此动画。
    m_grossini->runAction(action);
}

std::string ActionSequence::subtitle()
{
    return "Sequence: Move + Rotate";
}

//第十四种动画演示表现的是如何使多种动画在组成动画序列中能够进行响应控制。
class ActionSequence2 : public ActionsDemo
{
public:
    virtual void onEnter();
    virtual std::string subtitle();

    void callback1();
    void callback2(CCNode* sender);
    void callback3(CCNode* sender, void* data);
};
void ActionSequence2::onEnter()
{
	//动画演示的初始化
    ActionsDemo::onEnter();
	//只需要男一号上场
    alignSpritesLeft(1);
	//男一号设置不显示
    m_grossini->setVisible(false);
	//创建一个序列动画。这个序列动画包含了一些动画和回调函数, CCCallFunc为不带参数的回调函数,CCCallFuncN为以演示当前动画的演员为参数的回调函数,CCCallFuncND为以演示当前动画的演员和一个用户输入值为参数的回调函数。
    CCFiniteTimeAction*  action = CCSequence::create(
        CCPlace::create(CCPointMake(200,200)),
        CCShow::create(),
        CCMoveBy::create(1, CCPointMake(100,0)),
        CCCallFunc::create(this, callfunc_selector(ActionSequence2::callback1)),
        CCCallFuncN::create(this, callfuncN_selector(ActionSequence2::callback2)),
        CCCallFuncND::create(this, callfuncND_selector(ActionSequence2::callback3), (void*)0xbebabeba),
        NULL);
	//男一号运行此动画序列。
    m_grossini->runAction(action);
}
//不带参数的回调函数
void ActionSequence2::callback1()
{
    CCSize s = CCDirector::sharedDirector()->getWinSize();
    CCLabelTTF *label = CCLabelTTF::create("callback 1 called", "Marker Felt", 16);
    label->setPosition(CCPointMake( s.width/4*1,s.height/2));

    addChild(label);
}
//以演示当前动画的演员为参数的回调函数
void ActionSequence2::callback2(CCNode* sender)
{
    CCSize s = CCDirector::sharedDirector()->getWinSize();
    CCLabelTTF *label = CCLabelTTF::create("callback 2 called", "Marker Felt", 16);
    label->setPosition(CCPointMake( s.width/4*2,s.height/2));

    addChild(label);
}
//以演示当前动画的演员和一个用户输入值为参数的回调函数
void ActionSequence2::callback3(CCNode* sender, void* data)
{
    CCSize s = CCDirector::sharedDirector()->getWinSize();
    CCLabelTTF *label = CCLabelTTF::create("callback 3 called", "Marker Felt", 16);
    label->setPosition(CCPointMake( s.width/4*3,s.height/2));

    addChild(label);
}

std::string ActionSequence2::subtitle()
{
    return "Sequence of InstantActions";
}

//第十五种动画演示表现的是几种动画的并行,即如何同时进行多种动画。
class ActionSpawn : public ActionsDemo
{
public:
    virtual void onEnter();
    virtual std::string subtitle();
};
void ActionSpawn::onEnter()
{
	//动画演示的初始化
    ActionsDemo::onEnter();
	//只需要男一号上场
    alignSpritesLeft(1);
	//创建一个动画组合,使用方法与动画序列类似了,这里同时播放了跳跃和旋转的动画。
    CCAction*  action = CCSpawn::create(
        CCJumpBy::create(2, CCPointMake(300,0), 50, 4),
        CCRotateBy::create( 2,  720),
        NULL);
	//让男一行运行此动画组合。
    m_grossini->runAction(action);
}

std::string ActionSpawn::subtitle()
{
    return "Spawn: Jump + Rotate";
}

//第十六种动画演示表现的是动画的倒退重播,就像你看DVD按着后退键。
class ActionReverse : public ActionsDemo
{
public:
    virtual void onEnter();
    virtual std::string subtitle();
};
void ActionReverse::onEnter()
{
	//动画演示的初始化
    ActionsDemo::onEnter();
	//只需要男一号上场
    alignSpritesLeft(1);
	//创建一个跳跃动画。
    CCActionInterval*  jump = CCJumpBy::create(2, CCPointMake(300,0), 50, 4);
	//创建一个动画序列,先运行上面的跳跃动画,再运其反向动画。
    CCFiniteTimeAction*  action = CCSequence::create( jump, jump->reverse(), NULL);
	//男一号运行动画。
    m_grossini->runAction(action);
}

std::string ActionReverse::subtitle()
{
    return "Reverse an action";
}

//第十七种动画演示表现的是动画的暂停与继续播放。
class ActionDelayTime : public ActionsDemo
{
public:
    virtual void onEnter();
    virtual std::string subtitle();
};
void ActionDelayTime::onEnter()
{
	//动画演示的初始化
    ActionsDemo::onEnter();
	//只需要男一号上场
    alignSpritesLeft(1);
	//创建一个移动动画。
    CCActionInterval*  move = CCMoveBy::create(1, CCPointMake(150,0));
	//创建一个动画序列,先播放移动动画,再暂停2秒,然后再播放移动动画。
    CCFiniteTimeAction*  action = CCSequence::create( move, CCDelayTime::create(2), move, NULL);
	//男一行运行此动画序列。
    m_grossini->runAction(action);
}

std::string ActionDelayTime::subtitle()
{
    return "DelayTime: m + delay + m";
}


//第十八种动画演示表现的是动画的重复播放。
class ActionRepeat : public ActionsDemo
{
public:
    virtual void onEnter();
    virtual std::string subtitle();
};
void ActionRepeat::onEnter()
{	//动画演示的初始化
    ActionsDemo::onEnter();
	//两位演员上场
    alignSpritesLeft(2);
	//创建一个移动动画。
    CCActionInterval*  a1 = CCMoveBy::create(1, CCPointMake(150,0));
	//创建一个循环3次的序列动画。序列动画先设置精灵位置在60,60,然后播放上面的移动动画。
    CCActionInterval*  action1 = CCRepeat::create(
        CCSequence::create( CCPlace::create(CCPointMake(60,60)), a1, NULL) , 
        3); 
	//创建一个无限循环动画。这个无限循环的动画是一个动画序列,先播放第一个移动动画,再播放其反向动画。
    CCAction*  action2 = CCRepeatForever::create(
        (CCActionInterval*)(CCSequence::create((CCActionInterval*)(a1->copy()->autorelease()), a1->reverse(), NULL))
        );
	//女二号播放循环3次的序列动画
    m_kathia->runAction(action1);
	//女一号播放无限循环动画。
    m_tamara->runAction(action2);
}

std::string ActionRepeat::subtitle()
{
    return "Repeat / RepeatForever actions";
}

//第十九种动画演示表现的是动画的无限循环旋转。
class ActionRepeatForever : public ActionsDemo
{
public:
    virtual void onEnter();
    virtual std::string subtitle();

    void repeatForever(CCNode* pTarget);
};
void ActionRepeatForever::onEnter()
{	//动画演示的初始化
    ActionsDemo::onEnter();
	//只需要男一号上场
    centerSprites(1);
	//创建一个动画序列,先暂停1秒,然后调用
    CCFiniteTimeAction*  action = CCSequence::create(
        CCDelayTime::create(1),
        CCCallFuncN::create( this, callfuncN_selector(ActionRepeatForever::repeatForever) ), 
        NULL);
	//男一号运行此动画。
    m_grossini->runAction(action);
}
//回调函数。
void ActionRepeatForever::repeatForever(CCNode* pSender)
{
	//创建一个无限循环的旋转动画。
    CCRepeatForever *repeat = CCRepeatForever::create( CCRotateBy::create(1.0f, 360) );
	//让男一号运行此无限循环动画。
    pSender->runAction(repeat);
}

std::string ActionRepeatForever::subtitle()
{
    return "CallFuncN + RepeatForever";
}


//第二十种动画演示表现的是动画的无限循环旋转到某个角度。
class ActionRotateToRepeat : public ActionsDemo
{
public:
    virtual void onEnter();
    virtual std::string subtitle();
};
void ActionRotateToRepeat::onEnter()
{	//动画演示的初始化
    ActionsDemo::onEnter();
	//需要两位演员
    centerSprites(2);
	//创建一个1秒内旋转到90度的动画
    CCActionInterval*  act1 = CCRotateTo::create(1, 90);
	//创建一个1秒内旋转到0度的动画
	CCActionInterval*  act2 = CCRotateTo::create(1, 0);
	//创建一个动画序列,先运行动动画1,再运行动画2
    CCActionInterval*  seq = (CCActionInterval*)(CCSequence::create(act1, act2, NULL));
	//创建一个无限循环播放动画序列的动画。
	CCAction*  rep1 = CCRepeatForever::create(seq);
	//创建一个循环10次播放动画序列的动画。
    CCActionInterval*  rep2 = CCRepeat::create((CCFiniteTimeAction*)(seq->copy()->autorelease()), 10);
	//两位演员分别播放相应的循环动画。
    m_tamara->runAction(rep1);
    m_kathia->runAction(rep2);
}

std::string ActionRotateToRepeat ::subtitle()
{
    return "Repeat/RepeatForever + RotateTo";
}

//第二十一种动画演示表现的是动画的旋转与反向旋转。
class ActionRotateJerk : public ActionsDemo
{
public:
    virtual void onEnter();
    virtual std::string subtitle();
};
void ActionRotateJerk::onEnter()
{	//动画演示的初始化
    ActionsDemo::onEnter();
	//需要两位演员
    centerSprites(2);
	//创建一个动画序列,先播放一个0.5秒旋转到-20度的动画,再播放一个0.5秒旋转到20度的动画。
    CCFiniteTimeAction*  seq = CCSequence::create(
        CCRotateTo::create(0.5f, -20),
        CCRotateTo::create(0.5f, 20),
        NULL);
	//创建一个循环播放10次上面的动画序列的循环动画。
	CCActionInterval*  rep1 = CCRepeat::create(seq, 10);
	//创建一个无限循环播放上面的动画序列的循环动画。
    CCAction*  rep2 = CCRepeatForever::create( (CCActionInterval*)(seq->copy()->autorelease()) );
	//两位演员分别播放各自的循环动画。
    m_tamara->runAction(rep1);
    m_kathia->runAction(rep2);
}

std::string ActionRotateJerk::subtitle()
{
    return "RepeatForever / Repeat + Rotate";
}

//第二十二种动画演示表现的是动画过程中的函数响应。
class ActionCallFunc : public ActionsDemo
{
public:
    virtual void onEnter();
    virtual std::string subtitle();

    void callback1();
    void callback2(CCNode* pTarget);
    void callback3(CCNode* pTarget, void* data);
};
void ActionCallFunc::onEnter()
{	//动画演示的初始化
    ActionsDemo::onEnter();
	//需要三位演员
    centerSprites(3);
	//创建一个动画序列,先播放一个2秒横向移动200的动画,然后调用一个回调函数。
    CCFiniteTimeAction*  action = CCSequence::create(
        CCMoveBy::create(2, CCPointMake(200,0)),
        CCCallFunc::create(this, callfunc_selector(ActionCallFunc::callback1)), 
        NULL);
	//创建一个动画序列,先播放一个2秒放大2倍的动画,再播放一个2秒的淡出动画,之后调用一个回调函数。
    CCFiniteTimeAction*  action2 = CCSequence::create(
        CCScaleBy::create(2 ,  2),
        CCFadeOut::create(2),
        CCCallFuncN::create(this, callfuncN_selector(ActionSequence2::callback2)), 
        NULL);
	//创建一个动画序列,先播放一个3秒内旋转360度的动画,然后是一个2秒内淡出的动画,之后调用一个回调函数。
    CCFiniteTimeAction*  action3 = CCSequence::create(
        CCRotateBy::create(3 , 360),
        CCFadeOut::create(2),
        CCCallFuncND::create(this, callfuncND_selector(ActionSequence2::callback3), (void*)0xbebabeba), 
        NULL);
	//三位演员分别演示相应的动画。
    m_grossini->runAction(action);
    m_tamara->runAction(action2);
    m_kathia->runAction(action3);
}

//第一个回调函数。
void ActionCallFunc::callback1()
{
    CCSize s = CCDirector::sharedDirector()->getWinSize();
    CCLabelTTF *label = CCLabelTTF::create("callback 1 called", "Marker Felt", 16);
    label->setPosition(CCPointMake( s.width/4*1,s.height/2));

    addChild(label);
}
//第二个回调函数。
void ActionCallFunc::callback2(CCNode* pSender)
{
    CCSize s = CCDirector::sharedDirector()->getWinSize();
    CCLabelTTF *label = CCLabelTTF::create("callback 2 called", "Marker Felt", 16);
    label->setPosition(CCPointMake( s.width/4*2,s.height/2));

    addChild(label);
}
//第三个回调函数。
void ActionCallFunc::callback3(CCNode* pTarget, void* data)
{
    CCSize s = CCDirector::sharedDirector()->getWinSize();
    CCLabelTTF *label = CCLabelTTF::create("callback 3 called", "Marker Felt", 16);
    label->setPosition(CCPointMake( s.width/4*3,s.height/2));
    addChild(label);
}

std::string ActionCallFunc::subtitle()
{
    return "Callbacks: CallFunc and friends";
}

//第二十二种动画演示表现的是动画过程中的带参数的函数响应。
class ActionCallFuncND : public ActionsDemo
{
public:
    virtual void onEnter();
    virtual std::string title();
    virtual std::string subtitle();
    void removeFromParentAndCleanup(CCNode* pSender, void* data);
};
void ActionCallFuncND::onEnter()
{	//动画演示的初始化
    ActionsDemo::onEnter();
	//只需要男演员上场。
    centerSprites(1);
	//创建一个动画序列,首先播放一个2秒横向移动200的动画,然后调用一个回调函数,可带一个参数true。
    CCFiniteTimeAction* action = CCSequence::create(CCMoveBy::create(2.0f, ccp(200,0)),
        CCCallFuncND::create(this, callfuncND_selector(ActionCallFuncND::removeFromParentAndCleanup), (void*)true),
        NULL);
	//男演员演示动画
    m_grossini->runAction(action);
}

std::string ActionCallFuncND::title()
{
    return "CallFuncND + auto remove";
}

std::string ActionCallFuncND::subtitle()
{
    return "CallFuncND + removeFromParentAndCleanup. Grossini dissapears in 2s";
}
//带参数的回调函数。data在这里为true。
void ActionCallFuncND::removeFromParentAndCleanup(CCNode* pSender, void* data)
{
    bool bCleanUp = data != NULL;
    m_grossini->removeFromParentAndCleanup(bCleanUp);
}

//第二十三种动画演示表现的是动画的序列播放与反向序列播放。
class ActionReverseSequence : public ActionsDemo
{
public:
    virtual void onEnter();
    virtual std::string subtitle();
};
void ActionReverseSequence::onEnter()
{
	//动画演示的初始化
    ActionsDemo::onEnter();
	//只需要男演员上场。
    alignSpritesLeft(1);
	//创建一个移动动画。
	CCActionInterval*  move1 = CCMoveBy::create(1, CCPointMake(250,0));
	//创建第二个移动动画。
	CCActionInterval*  move2 = CCMoveBy::create(1, CCPointMake(0,50));
	//创建一个动画序列,首先播放第一个移动动画,再播放第二个移动动画,最后播放第一个移动动画的反向动画。
    CCFiniteTimeAction*  seq = CCSequence::create( move1, move2, move1->reverse(), NULL);
	//创建一个动画序列,先播放第一个动画序列,然后播放这个动画序列的反向动画序列。
    CCFiniteTimeAction*  action = CCSequence::create( seq, seq->reverse(), NULL);
	//男演员演示这个动画序列。
    m_grossini->runAction(action);
}

std::string ActionReverseSequence::subtitle()
{
    return "Reverse a sequence";
}

//第二十四种动画演示表现的是动画的序列播放与反向序列播放。
class ActionReverseSequence2 : public ActionsDemo
{
public:
    virtual void onEnter();
    virtual std::string subtitle();
};
void ActionReverseSequence2::onEnter()
{	//动画演示的初始化
    ActionsDemo::onEnter();
	//需要两位演员。
    alignSpritesLeft(2);
    //创建一个移动动画。
	CCActionInterval*  move1 = CCMoveBy::create(1, CCPointMake(250,0));
	//创建第二个移动动画。
	CCActionInterval*  move2 = CCMoveBy::create(1, CCPointMake(0,50));
	//创建两个精灵显示隐藏切换动画。这个动画会判断精灵显示状态,如果显示则切换为隐藏,如果隐藏则切换为显示。
    CCToggleVisibility*  tog1 = new CCToggleVisibility();
    CCToggleVisibility*  tog2 = new CCToggleVisibility();
    tog1->autorelease();
	tog2->autorelease();
	//创建动画序列,先播第一个移动动画,然后隐藏,然后播第二个移动动画,然后显示,再播第一个移动动画的反向动画。
	CCFiniteTimeAction*  seq = CCSequence::create( move1, tog1, move2, tog2, move1->reverse(), NULL);
	//创建第二个动画序列,先播放第一个动画序列,再播放它的反向动画序列。
    CCActionInterval*  action = CCRepeat::create((CCActionInterval*)(CCSequence::create( seq, seq->reverse(), NULL)), 3);



    //女二号播放第二个动画序列.
    m_kathia->runAction(action);
	//创建一个移动动画。
	CCActionInterval*  move_tamara = CCMoveBy::create(1, CCPointMake(100,0));
	//创建第二个移动动画。
	CCActionInterval*  move_tamara2 = CCMoveBy::create(1, CCPointMake(50,0));
	//创建一个隐藏动画,这个动画的过程中精灵是处于隐藏状态。
    CCActionInstant*  hide = new CCHide();
	hide->autorelease();
	//创建一个动画序列,先运行第一个移动动画,然后隐动画,最后第二个移动动画。
	CCFiniteTimeAction*  seq_tamara = CCSequence::create( move_tamara, hide, move_tamara2, NULL);
	//创建动画序列的反向动画序列。
	CCFiniteTimeAction*  seq_back = seq_tamara->reverse();
	//女一号运行一个动画序列,这个动画序列会先运行第一个动画序列,然后再运行它的反向动画序列。
    m_tamara->runAction( CCSequence::create( seq_tamara, seq_back, NULL));
}
std::string ActionReverseSequence2::subtitle()
{
    return "Reverse sequence 2";
}

//第二十五种动画演示表现的是旋转摄像机动画,这时会用到摄像机球型运动算法,摄像机会处在一个以目标物为球心的球体表面,其可以在球体表面上绕横向和纵向轴旋转。
class ActionOrbit : public ActionsDemo
{
public:
    virtual void onEnter();
    virtual std::string subtitle();
};
void ActionOrbit::onEnter()
{	//动画演示的初始化
    ActionsDemo::onEnter();
	//需要三位演员。
    centerSprites(3);
	//创建第一个旋转摄像机动画。
	//创建的这个动画为2秒内在半径为1的球面上绕纵向轴转180度。
	CCActionInterval*  orbit1 = CCOrbitCamera::create(2,1, 0, 0, 180, 0, 0);
	//创建第一个动画序列,先运行摄像机动画,再运行它的反向动画。
    CCFiniteTimeAction*  action1 = CCSequence::create(
        orbit1,
        orbit1->reverse(),
        NULL);
	//创建第二个旋转摄像机动画以及动画序列。
	//创建的这个动画为2秒内在半径为1的球面上,位置点在横向轴旋转-45度,然后动画过程会沿以旋转后的坐标系在纵向轴转180度。
    CCActionInterval*  orbit2 = CCOrbitCamera::create(2,1, 0, 0, 180, -45, 0);
    CCFiniteTimeAction*  action2 = CCSequence::create(
        orbit2,
        orbit2->reverse(),
        NULL);
	//创建第三个旋转摄像机动画及动画序列。
	//创建的这个动画为2秒内在半径为1的球面上,位置点在横向轴旋转90度,然后动画过程会沿以旋转后的坐标系在纵向轴转180度,注意,这时候在世界坐标系中看,其实是沿横向轴转180度~!
    CCActionInterval*  orbit3 = CCOrbitCamera::create(2,1, 0, 0, 180, 90, 0);
    CCFiniteTimeAction*  action3 = CCSequence::create(
        orbit3,
        orbit3->reverse(),
        NULL);

   	//三位演员分别播放相应的无限循环动画。 m_kathia->runAction(CCRepeatForever::create((CCActionInterval*)action1));
    m_tamara->runAction(CCRepeatForever::create((CCActionInterval*)action2));
    m_grossini->runAction(CCRepeatForever::create((CCActionInterval*)action3));
	//创建一个移动动画。
	CCActionInterval*  move = CCMoveBy::create(3, CCPointMake(100,-100));
	//创建这个移动动画的反向动画。
	CCActionInterval*  move_back = move->reverse();
	//将这两个动画放到一个动画序列中。
	CCFiniteTimeAction*  seq = CCSequence::create(move, move_back, NULL);
	//创建一个无限循环动画,播放这个动画序列。
	CCAction*  rfe = CCRepeatForever::create((CCActionInterval*)seq);
	//三位演员要同时播放这个无限循环动画。
    m_kathia->runAction(rfe);
    m_tamara->runAction((CCAction*)(rfe->copy()->autorelease()));
    m_grossini->runAction((CCAction*)(rfe->copy()->autorelease()));
}

std::string ActionOrbit::subtitle()
{
    return "OrbitCamera action";
}


//第二十六种动画演示表现的是跟随动画。
class ActionFollow : public ActionsDemo
{
public:
    virtual void onEnter();
    virtual std::string subtitle();
};
void ActionFollow::onEnter()
{
	//动画演示的初始化
    ActionsDemo::onEnter();
	//只需要一位演员上场
	centerSprites(1);
	//取得可视区域的大小
    CCSize s = CCDirector::sharedDirector()->getWinSize();
	//男一号设置位置。
	m_grossini->setPosition(CCPointMake(-200, s.height / 2));
	//创建一个移动动画。
	CCActionInterval* move      = CCMoveBy::create(2, CCPointMake(s.width * 3, 0));
	//创建这个移动动画的反向动画。
	CCActionInterval* move_back = move->reverse();
	//创建一个动画序列,先播放移动动画,再播放其反向动画。
	CCFiniteTimeAction* seq       = CCSequence::create(move, move_back, NULL);
	//创建一个无限循环动画,播放这个动画序列。
    CCAction* rep               = CCRepeatForever::create((CCActionInterval*)seq);
	//男一号演员这个无限循环动画。
    m_grossini->runAction(rep);
	//当前层运行一个跟随动画,跟随男一号,并设置其包围区域。
    this->runAction(CCFollow::create(m_grossini, CCRectMake(0, 0, s.width * 2 - 100, s.height)));
}

std::string ActionFollow::subtitle()
{
    return "Follow action";
}

//第二十七种动画演示表现的是控制目标动画。
class ActionTargeted : public ActionsDemo
{
public:
    virtual void onEnter();
    virtual std::string title();
    virtual std::string subtitle();
};
void ActionTargeted::onEnter()
{	
	//动画演示的初始化
	ActionsDemo::onEnter();
	//需要两位演员上场
	centerSprites(2);
	//先创建一个跳跃动画。
	CCJumpBy* jump1 = CCJumpBy::create(2,CCPointZero,100,3);
	//再创建一个相同的跳跃动画。
	CCJumpBy* jump2 = (CCJumpBy*)jump1->copy()->autorelease();
	//创建一个旋转动画。
	CCRotateBy* rot1 =  CCRotateBy::create(1, 360);
	//再创建一个相同的旋转动画。
    CCRotateBy* rot2 = (CCRotateBy*)rot1->copy()->autorelease();
	//创建第一个控制目标动画,让女二号播放第二个跳跃动画。
	CCTargetedAction *t1 = CCTargetedAction::create(m_kathia, jump2);
	//创建第二个控制目标动画,让女二号播放第二个旋转动画。
    CCTargetedAction *t2 = CCTargetedAction::create(m_kathia, rot2);

	//创建一个动画序列,先播放一个第一个跳跃动画,再播放第一个控制目标动画,再播放第一个旋转动画,再播放第二个控制目标动画。
	CCSequence* seq = (CCSequence*)CCSequence::create(jump1, t1, rot1, t2, NULL);
	//创建一个无限循环动画,播放上面的动画序列。
    CCRepeatForever *always = CCRepeatForever::create(seq);
	//女一号运行这个无限循环动画。
    m_tamara->runAction(always);
}

std::string ActionTargeted::title()
{
    return "ActionTargeted";
}

std::string ActionTargeted::subtitle()
{
    return "Action that runs on another target. Useful for sequences";
}

//第二十八种动画演示表现的是1305号动画。
class Issue1305 : public ActionsDemo
{
public:
    virtual void onEnter();
    virtual void onExit();
    void log(CCNode* pSender);
    void addSprite(float dt);
    virtual std::string title();
    virtual std::string subtitle();
private:
    CCSprite* m_pSpriteTmp;
};
void Issue1305::onEnter()
{	
	//动画演示的初始化
	ActionsDemo::onEnter();
	//空无一人
    centerSprites(0);
	//创建一个精灵
    m_pSpriteTmp = CCSprite::create("Images/grossini.png");
	//让精灵运行一个回调函数打印一个日志。注意:在这里没有让精灵加入当前Layer,所以它不会真正的runAction,必须等它被挂在Layer下后才能被遍历更新。
	
	m_pSpriteTmp->runAction(CCCallFuncN::create(this, callfuncN_selector(Issue1305::log)));
	//占用精灵,故引用计数加一。
    m_pSpriteTmp->retain();
	//当前结点在2秒后调用回调函数增加一个精灵。
    scheduleOnce(schedule_selector(Issue1305::addSprite), 2);
}
//精灵调用的回调函数。
void Issue1305::log(CCNode* pSender)
{
    CCLog("This message SHALL ONLY appear when the sprite is added to the scene, NOT BEFORE");
}

void Issue1305::onExit()
{
    m_pSpriteTmp->release();
    ActionsDemo::onExit();
}

void Issue1305::addSprite(float dt)
{
	//在这里设置精灵的位置并将其加入到当前的Layer下。
    m_pSpriteTmp->setPosition(ccp(250,250));
    addChild(m_pSpriteTmp);
}

上面这个动画运行后,等2秒创建出精灵,然后动作管理器才能执行精灵运行的函数打印日志,输出到Output窗口。

Cocos2d-x 2.0 之 Actions “三板斧” 之三_第1张图片

std::string Issue1305::title()
{
    return "Issue 1305";
}

std::string Issue1305::subtitle()
{
    return "In two seconds you should see a message on the console. NOT BEFORE.";
}
//第二十九种动画演示表现的是1305号动画二。
class Issue1305_2 : public ActionsDemo
{
public:
    virtual void onEnter();
    void log1();
    void log2();
    void log3();
    void log4();
    virtual std::string title();
    virtual std::string subtitle();
};
void Issue1305_2::onEnter()
{
	//动画演示的初始化
	ActionsDemo::onEnter();
	//不需要演员上场
    centerSprites(0);
	//创建一个精灵.加载一个图。
	CCSprite *spr = CCSprite::create("Images/grossini.png");
	//设置位置
	spr->setPosition(ccp(200,200));
	//加入当前Layer。
    addChild(spr);
	//创建一个移动动画。
    CCMoveBy* act1 = CCMoveBy::create(2 ,ccp(0, 100));
   	//创建一个回调函数。
	CCCallFunc* act2 = CCCallFunc::create(this, callfunc_selector(Issue1305_2::log1)) ;
	//创建第二个移动动画。
	CCMoveBy* act3 = CCMoveBy::create(2, ccp(0, -100));
	//创建第二个回调函数。
	CCCallFunc* act4 = CCCallFunc::create(this, callfunc_selector(Issue1305_2::log2)) ;
	//创建第三个移动动画。
	CCMoveBy* act5 = CCMoveBy::create(2, ccp(100, -100));
	//创建第三个回调函数。
	CCCallFunc* act6 = CCCallFunc::create(this, callfunc_selector(Issue1305_2::log3)) ;
	//创建第四个移动动画。
	CCMoveBy* act7 = CCMoveBy::create(2, ccp(-100, 0));
	//创建第四个回调函数。
    CCCallFunc* act8 = CCCallFunc::create(this, callfunc_selector(Issue1305_2::log4)) ;
	//创建一个动画序列,将前面的动画都顺序包含进来。
    CCFiniteTimeAction* actF = CCSequence::create(act1, act2, act3, act4, act5, act6, act7, act8, NULL);

   //通过动画管理器来指定精灵播放动画序列。    CCDirector::sharedDirector()->getActionManager()->addAction(actF ,spr, false);

}

void Issue1305_2::log1()
{
    CCLog("1st block");
}

void Issue1305_2::log2()
{
    CCLog("2nd block");
}

void Issue1305_2::log3()
{
    CCLog("3rd block");
}

void Issue1305_2::log4()
{
    CCLog("4th block");
}

std::string Issue1305_2::title()
{
    return "Issue 1305 #2";
}

std::string Issue1305_2::subtitle()
{
    return "See console. You should only see one message for each block";
}
//第三十种动画演示表现的是1288号动画。
class Issue1288 : public ActionsDemo
{
public:
    virtual void onEnter();
    virtual std::string title();
    virtual std::string subtitle();
};
void Issue1288::onEnter()
{
	//动画演示的初始化
	ActionsDemo::onEnter();
	//不需要演员上场。
    centerSprites(0);
	//创建一个精灵,设置其位置并加入当前Layer。
    CCSprite *spr = CCSprite::create("Images/grossini.png");
    spr->setPosition(ccp(100, 100));
    addChild(spr);
	//创建两个移动动画。
    CCMoveBy* act1 = CCMoveBy::create(0.5, ccp(100, 0));
	CCMoveBy* act2 = (CCMoveBy*)act1->reverse();
	//将两个动画放入一个新创建的动画序列。
	CCFiniteTimeAction* act3 = CCSequence::create(act1, act2, NULL);
	//创建一个循环2次播放动画序列的动画。
    CCRepeat* act4 = CCRepeat::create(act3, 2);
	//让精灵播放这个循环2次播放动画序列的动画。
    spr->runAction(act4);
}

std::string Issue1288::title()
{
    return "Issue 1288";
}

std::string Issue1288::subtitle()
{
    return "Sprite should end at the position where it started.";
}
//第三十种动画演示表现的是1288号动画二。
class Issue1288_2 : public ActionsDemo
{
public:
    virtual void onEnter();
    virtual std::string title();
    virtual std::string subtitle();
};
void Issue1288_2::onEnter()
{
	//动画演示的初始化
	ActionsDemo::onEnter();
	//不需要演员上场。
    centerSprites(0);
	//创建一个精灵,设置其位置并加入当前Layer。
    CCSprite *spr = CCSprite::create("Images/grossini.png");
    spr->setPosition(ccp(100, 100));
    addChild(spr);
	//创建一个移动动画。
	CCMoveBy* act1 = CCMoveBy::create(0.5, ccp(100, 0));
	//创建一个循环播放1次上面的移动动画,并让精灵运行它。
    spr->runAction(CCRepeat::create(act1, 1));
}

std::string Issue1288_2::title()
{
    return "Issue 1288 #2";
}

std::string Issue1288_2::subtitle()
{
    return "Sprite should move 100 pixels, and stay there";
}
//第三十一种动画演示表现的是1327号动画。
class Issue1327 : public ActionsDemo
{
public:
    virtual void onEnter();
    virtual std::string subtitle();
    virtual std::string title();
    void logSprRotation(CCNode* pSender);
};
void Issue1327::onEnter()
{
	//动画演示的初始化
	ActionsDemo::onEnter();
	//不需要演员上场。
    centerSprites(0);
	//创建一个精灵,设置其位置并加入当前Layer。
    CCSprite *spr = CCSprite::create("Images/grossini.png");
    spr->setPosition(ccp(100, 100));
    addChild(spr);
	//又是一堆回调函数和旋转动画。
    CCCallFuncN* act1 = CCCallFuncN::create(this, callfuncN_selector(Issue1327::logSprRotation));
    CCRotateBy* act2 = CCRotateBy::create(0.25, 45);
    CCCallFuncN* act3 = CCCallFuncN::create(this, callfuncN_selector(Issue1327::logSprRotation));
    CCRotateBy* act4 = CCRotateBy::create(0.25, 45);
    CCCallFuncN* act5 = CCCallFuncN::create(this, callfuncN_selector(Issue1327::logSprRotation));
    CCRotateBy* act6 = CCRotateBy::create(0.25, 45);
    CCCallFuncN* act7 = CCCallFuncN::create(this, callfuncN_selector(Issue1327::logSprRotation));
    CCRotateBy* act8 = CCRotateBy::create(0.25, 45);
    CCCallFuncN* act9 = CCCallFuncN::create(this, callfuncN_selector(Issue1327::logSprRotation));
	//创建一个动画序列,将上面9个动画顺序放入。
	CCFiniteTimeAction* actF = CCSequence::create(act1, act2, act3, act4, act5, act6, act7, act8, act9, NULL);
	//精灵运行这个动画序列。
    spr->runAction(actF);
}

std::string Issue1327::title()
{
    return "Issue 1327";
}

std::string Issue1327::subtitle()
{
    return "See console: You should see: 0, 45, 90, 135, 180";
}

void Issue1327::logSprRotation(CCNode* pSender)
{
    CCLog("%f", ((CCSprite*)pSender)->getRotation());
}
//第三十二种动画演示表现的是由点构成的曲线动画。
class ActionCatmullRom : public ActionsDemo
{
public:
    ~ActionCatmullRom();
    
    virtual void onEnter();
    virtual void draw();
    virtual std::string subtitle();
    virtual std::string title();
private:
    CCPointArray *m_pArray1;
    CCPointArray *m_pArray2;
};
void ActionCatmullRom::onEnter()
{	//动画演示初始化
    ActionsDemo::onEnter();
    //2位演员上场
    this->centerSprites(2);
    //取得可视区域大小。
    CCSize s = CCDirector::sharedDirector()->getWinSize();
    //女一号设置位置。
    m_tamara->setPosition(ccp(50, 50));
	//创建一个位置点数组,初始化数组大小为20.
    CCPointArray *array = CCPointArray::create(20);
    //放入一堆位置点。
    array->addControlPoint(ccp(0, 0));
    array->addControlPoint(ccp(80, 80));
    array->addControlPoint(ccp(s.width - 80, 80));
    array->addControlPoint(ccp(s.width - 80, s.height - 80));
    array->addControlPoint(ccp(80, s.height - 80));
    array->addControlPoint(ccp(80, 80));
    array->addControlPoint(ccp(s.width / 2, s.height / 2));
    //创建一个3秒钟按点数组构成的曲线移动的动画,位置点为相对位置。
	CCCatmullRomBy *action = CCCatmullRomBy::create(3, array);
	//创建它的反向动画。
    CCFiniteTimeAction *reverse = action->reverse();
	//创建一个动画序列,将原动画和反向动画顺序放入。
    CCFiniteTimeAction *seq = CCSequence::create(action, reverse, NULL);
	//女一号运行这个动画序列。
    m_tamara->runAction(seq);
	
	
	//再创建一个位置点数组。
    CCPointArray *array2 = CCPointArray::create(20);
    //又放入一堆位置点。
    array2->addControlPoint(ccp(s.width / 2, 30));
    array2->addControlPoint(ccp(s.width  -80, 30));
    array2->addControlPoint(ccp(s.width - 80, s.height - 80));
    array2->addControlPoint(ccp(s.width / 2, s.height - 80));
    array2->addControlPoint(ccp(s.width / 2, 30));
   //创建一个3秒钟按点数组构成的曲线移动的动画,位置点为绝对位置。
	CCCatmullRomTo *action2 = CCCatmullRomTo::create(3, array2);
	//创建它的反向动画。
    CCFiniteTimeAction *reverse2 = action2->reverse();
	//创建一个动画序列,将原动画和反向动画顺序放入。
    CCFiniteTimeAction *seq2 = CCSequence::create(action2, reverse2, NULL);
	
	//女二号运行这个动画序列。
    m_kathia->runAction(seq2);
    //将两个位置点数组的地址保存到成员指针变量,并对引用计数器加1防止被释放掉。
    m_pArray1 = array;
    m_pArray1->retain();
    m_pArray2 = array2;
    m_pArray2->retain();
}

ActionCatmullRom::~ActionCatmullRom()
{
	//当前演示层释放时,一并释放点数组。
    m_pArray1->release();
    m_pArray2->release();
}

void ActionCatmullRom::draw()
{
    ActionsDemo::draw();
    
	//绘制相对位置曲线
	//先将当前OPENGL的矩阵状态压栈
	kmGLPushMatrix();
	//移动到50,50点的位置
	kmGLTranslatef(50, 50, 0);
	//以这个点为原点绘制相对路径
	ccDrawCatmullRom(m_pArray1, 50);
	//恢复矩阵状态
	kmGLPopMatrix();

    //再绘制绝对位置的曲线
	ccDrawCatmullRom(m_pArray2,50);
}

string ActionCatmullRom::title()
{
    return "CatmullRomBy / CatmullRomTo";
}

string ActionCatmullRom::subtitle()
{
    return "Catmull Rom spline paths. Testing reverse too";
}
//第三十三种动画演示表现的是由点构成的贝塞尔曲线动画。
class ActionCardinalSpline : public ActionsDemo
{
public:
    ~ActionCardinalSpline();
    
    virtual void onEnter();
    virtual void draw();
    virtual std::string subtitle();
    virtual std::string title();
private:
    CCPointArray *m_pArray;
};
void ActionCardinalSpline::onEnter()
{
	//动画演示初始化
    ActionsDemo::onEnter();
    //2位演员上场
    this->centerSprites(2);
    //取得可视区域大小。
    CCSize s = CCDirector::sharedDirector()->getWinSize();
	//创建一个位置点数组,初始化数组大小为20.
    CCPointArray *array = CCPointArray::create(20);
    //放入一堆位置点。
    array->addControlPoint(ccp(0, 0));
    array->addControlPoint(ccp(s.width/2-30, 0));
    array->addControlPoint(ccp(s.width/2-30, s.height-80));
    array->addControlPoint(ccp(0, s.height-80));
    array->addControlPoint(ccp(0, 0));
    //创建一个3秒钟按点数组构成的贝塞尔曲线移动的动画,位置点为相对位置。
	CCCardinalSplineBy *action = CCCardinalSplineBy::create(3, array, 0);
	//创建它的反向动画。
    CCActionInterval *reverse = action->reverse();
	//创建一个动画序列,将原动画和反向动画顺序放入。
    CCFiniteTimeAction *seq = CCSequence::create(action, reverse, NULL);
	//女一号设置位置并运行此曲线动画。
    m_tamara->setPosition(ccp(50, 50));
    m_tamara->runAction(seq);
	
//创建一个3秒钟按点数组构成的贝塞尔曲线移动的动画,位置点为相对位置。    	CCCardinalSplineBy *action2 = CCCardinalSplineBy::create(3, array, 1);
	//创建它的反向动画。
    CCActionInterval *reverse2 = action2->reverse();
	//创建一个动画序列,将原动画和反向动画顺序放入。
    CCFiniteTimeAction *seq2 = CCSequence::create(action2, reverse2, NULL);
	//女二号设置位置并运行此曲线动画。
    m_kathia->setPosition(ccp(s.width/2, 50));
    m_kathia->runAction(seq2);
	//将位置点数组的地址保存到成员指针变量,并对引用计数器加1防止被释放掉。
    m_pArray = array;
    array->retain();
}

ActionCardinalSpline::~ActionCardinalSpline()
{
    m_pArray->release();
}

void ActionCardinalSpline::draw()
{
    ActionsDemo::draw();
	
	//绘制第一个相对位置曲线
	//先将当前OPENGL的矩阵状态压栈
	kmGLPushMatrix();
	//移动到50,50点的位置
	kmGLTranslatef(50, 50, 0);
	//以这个点为原点绘制相对路径
	ccDrawCardinalSpline(m_pArray, 0, 100);
	//恢复矩阵状态
	kmGLPopMatrix();

    CCSize s = CCDirector::sharedDirector()->getWinSize();
    //绘制第二个相对位置曲线
	//先将当前OPENGL的矩阵状态压栈
	kmGLPushMatrix();
	//移动到s.width/2, 50的位置
	kmGLTranslatef(s.width/2, 50, 0);
	//以这个点为原点绘制相对路径
	ccDrawCardinalSpline(m_pArray, 1, 100);
	//恢复矩阵状态
	kmGLPopMatrix();
}

string ActionCardinalSpline::title()
{
    return "CardinalSplineBy / CardinalSplineAt";
}

string ActionCardinalSpline::subtitle()
{
    return "Cardinal Spline paths. Testing different tensions for one array";
}
//第三十四种动画演示表现的是控制暂停和恢复动画。
class PauseResumeActions : public ActionsDemo
{
public:
    PauseResumeActions();
    virtual ~PauseResumeActions();
    virtual void onEnter();
    virtual std::string subtitle();
    virtual std::string title();
    
    void pause(float dt);
    void resume(float dt);
private:
    CCSet *m_pPausedTargets;
};
PauseResumeActions::PauseResumeActions()
: m_pPausedTargets(NULL)
{

}

PauseResumeActions::~PauseResumeActions()
{
    CC_SAFE_RELEASE(m_pPausedTargets);
}

void PauseResumeActions::onEnter()
{	//动画演示初始化
    ActionsDemo::onEnter();
	//两位演员上场。
    this->centerSprites(2);
    //女一号运行一个无限循环的动画。
    m_tamara->runAction(CCRepeatForever::create(CCRotateBy::create(3, 360)));
 	//男一行运行一个反方向无限循环的动画。   m_grossini->runAction(CCRepeatForever::create(CCRotateBy::create(3, -360)));
	//女二号的动画同女一号一样。
    m_kathia->runAction(CCRepeatForever::create(CCRotateBy::create(3, 360)));
    //当前层在3秒后调用回调函数暂停。
	this->schedule(schedule_selector(PauseResumeActions::pause), 3, false, 0);
	//当前层在5秒后调用回调函数恢复。
    this->schedule(schedule_selector(PauseResumeActions::resume), 5, false, 0);
}

string PauseResumeActions::title()
{
    return "PauseResumeActions";
}

string PauseResumeActions::subtitle()
{
    return "All actions pause at 3s and resume at 5s";
}
//暂停的回调函数,用于暂停动画。
void PauseResumeActions::pause(float dt)
{
	CCLog("Pausing");
	//取得显示设备
    CCDirector *director = CCDirector::sharedDirector();
	//如果原来有要暂停的目标容器,释放暂停的目标容器
	CC_SAFE_RELEASE(m_pPausedTargets);
	//调用显示设备的接口暂停所有的动画并将这些动画返回给容器
	m_pPausedTargets = director->getActionManager()->pauseAllRunningActions();
	//因为占用它,所以对此引用计数器加1
    CC_SAFE_RETAIN(m_pPausedTargets);
}
//恢复的回调函数,用于恢复暂停的动画。
void PauseResumeActions::resume(float dt)
{
	CCLog("Resuming");
	//取得显示设备
	
	CCDirector *director = CCDirector::sharedDirector();
	//调用显示设备的接口恢复所有的暂停的动画
    director->getActionManager()->resumeTargets(m_pPausedTargets);
}
#endif

每一个演示完毕!大家明白了么?当然CPP里还有一点东西还需要说一下。


#include "ActionsTest.h"
#include "../testResource.h"
#include "cocos2d.h"

//这里定义三个全局函数,用于动画演示控制
CCLayer* NextAction();//演示下一个动画
CCLayer* BackAction();//演示上一个动画
CCLayer* RestartAction();//重新演示当前动画
//要演示的动画索引
static int s_nActionIdx = -1;
//创建相应的动画
CCLayer* CreateLayer(int nIndex)
{
	//在头文件里我们看到大量的动画演示类,它们都是由CCLayer基类派生的。这里定义一个CCLayer类用于指向下面创建的相应动画演示实例。
    CCLayer * pLayer = NULL;
	//根据索引new出相应的动画演示实例。
    switch (nIndex)
    {
        case ACTION_MANUAL_LAYER:
            pLayer = new ActionManual(); break;
        case ACTION_MOVE_LAYER:
            pLayer = new ActionMove(); break;
        case ACTION_SCALE_LAYER:
            pLayer = new ActionScale(); break;
        case ACTION_ROTATE_LAYER:
            pLayer = new ActionRotate(); break;
        case ACTION_SKEW_LAYER:
            pLayer = new ActionSkew(); break;
        case ACTION_SKEWROTATE_LAYER:
            pLayer = new ActionSkewRotateScale(); break;
        case ACTION_JUMP_LAYER:
            pLayer = new ActionJump(); break;
        case ACTION_BEZIER_LAYER:
            pLayer = new ActionBezier(); break;
        case ACTION_BLINK_LAYER:
            pLayer = new ActionBlink(); break;
        case ACTION_FADE_LAYER:
            pLayer = new ActionFade(); break;
        case ACTION_TINT_LAYER:
            pLayer = new ActionTint(); break;
        case ACTION_ANIMATE_LAYER:
            pLayer = new ActionAnimate(); break;
        case ACTION_SEQUENCE_LAYER:
            pLayer = new ActionSequence(); break;
        case ACTION_SEQUENCE2_LAYER:
            pLayer = new ActionSequence2(); break;
        case ACTION_SPAWN_LAYER:
            pLayer = new ActionSpawn(); break;
        case ACTION_REVERSE:
            pLayer = new ActionReverse(); break;
        case ACTION_DELAYTIME_LAYER:
            pLayer = new ActionDelayTime(); break;
        case ACTION_REPEAT_LAYER:
            pLayer = new ActionRepeat(); break;
        case ACTION_REPEATEFOREVER_LAYER:
            pLayer = new ActionRepeatForever(); break;
        case ACTION_ROTATETOREPEATE_LAYER:
            pLayer = new ActionRotateToRepeat(); break;
        case ACTION_ROTATEJERK_LAYER:
            pLayer = new ActionRotateJerk(); break;    
        case ACTION_CALLFUNC_LAYER:
            pLayer = new ActionCallFunc(); break;
        case ACTION_CALLFUNCND_LAYER:
            pLayer = new ActionCallFuncND(); break;
        case ACTION_REVERSESEQUENCE_LAYER:
            pLayer = new ActionReverseSequence(); break;
        case ACTION_REVERSESEQUENCE2_LAYER:
            pLayer = new ActionReverseSequence2(); break;
        case ACTION_ORBIT_LAYER:
            pLayer = new ActionOrbit(); break;
        case ACTION_FLLOW_LAYER:
            pLayer = new ActionFollow(); break;
        case ACTION_TARGETED_LAYER:
            pLayer = new ActionTargeted(); break;
        case ACTION_ISSUE1305_LAYER:
            pLayer = new Issue1305(); break;
        case ACTION_ISSUE1305_2_LAYER:
            pLayer = new Issue1305_2(); break;
        case ACTION_ISSUE1288_LAYER:
            pLayer = new Issue1288(); break;
        case ACTION_ISSUE1288_2_LAYER:
            pLayer = new Issue1288_2(); break;
        case ACTION_ISSUE1327_LAYER:
            pLayer = new Issue1327(); break;
        case ACTION_CARDINALSPLINE_LAYER:
            pLayer = new ActionCardinalSpline(); break;
        case ACTION_CATMULLROM_LAYER:
            pLayer = new ActionCatmullRom(); break;
        case PAUSERESUMEACTIONS_LAYER:
            pLayer = new PauseResumeActions(); break;

    default:
        break;
    }

    return pLayer;
}
//演示下一个动画的函数实现
CCLayer* NextAction()
{
    ++s_nActionIdx;
    s_nActionIdx = s_nActionIdx % ACTION_LAYER_COUNT;

    CCLayer* pLayer = CreateLayer(s_nActionIdx);
    pLayer->autorelease();

    return pLayer;
}
//演示上一个动画的函数实现
CCLayer* BackAction()
{
    --s_nActionIdx;
    if( s_nActionIdx < 0 )
        s_nActionIdx += ACTION_LAYER_COUNT;    

    CCLayer* pLayer = CreateLayer(s_nActionIdx);
    pLayer->autorelease();

    return pLayer;
}
//重新演示当前动画的函数实现。
CCLayer* RestartAction()
{
    CCLayer* pLayer = CreateLayer(s_nActionIdx);
    pLayer->autorelease();

    return pLayer;
}

三板斧,威力十足,如果还有什么不懂的。那我真没得好说了。下课!



你可能感兴趣的:(Cocos2d-x 2.0 之 Actions “三板斧” 之三)