cocos2d-x 笔记(五) TestCpp源码分析:Actions

Orca原创,转贴请标明链接Orca的移动开发轨迹。

目前整个学习笔记的版本是cocos2d-x 2.1.0beta3。

本篇对分析TestCpp当中的Actions。

ActionsTest.h就看下前面就可以了

#ifndef _ActionsTest_H_
#define _ActionsTest_H_

#include "../testBasic.h"
////----#include "cocos2d.h"

USING_NS_CC;

// 定义本篇中使用的枚举
enum
{
    ACTION_MANUAL_LAYER = 0,
    ACTION_MOVE_LAYER,
    ACTION_SCALE_LAYER,
    ACTION_ROTATE_LAYER,
    ACTION_SKEW_LAYER,
    ACTION_ROTATIONAL_SKEW_LAYER,
    ACTION_ROTATIONAL_SKEW_VS_STANDARD_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,
    ACTION_ISSUE1305_2_LAYER,
    ACTION_ISSUE1288_LAYER,
    ACTION_ISSUE1288_2_LAYER,
    ACTION_ISSUE1327_LAYER,
    ACTION_ISSUE1398_LAYER,
    ACTION_LAYER_COUNT,
};


// the class inherit from TestScene
// every Scene each test used must inherit from TestScene,
// make sure the test have the menu item for back to main menu
/************************************************************************/
/*  主测试屏幕                                                                     */
/************************************************************************/
class ActionsTestScene : public TestScene
{
public:
	// 本Test进入时调用的主要方法
    virtual void runThisTest();
};

// 动作Demo层
class ActionsDemo : public CCLayer
{
protected:
    CCSprite*    m_grossini;
    CCSprite*    m_tamara;
    CCSprite*    m_kathia;
public:
	// 进入时初始化的内容
    virtual void onEnter();
	// 退出时撤销的内容
    virtual void onExit();

	// 设置几个sprite居中
    void centerSprites(unsigned int numberOfSprites);
	// 设置sprite居左
    void alignSpritesLeft(unsigned int numberOfSprites);
    // 返回标题
	virtual std::string title();
	// 返回子标题
    virtual std::string subtitle();

	// 重启的callback
    void restartCallback(CCObject* pSender);
    // 下一个的callback
	void nextCallback(CCObject* pSender);
	// 返回的callback
    void backCallback(CCObject* pSender);
};

// ActionManual层
class ActionManual : public ActionsDemo
{
public:
	// 进入
    virtual void onEnter();
	// 子标题
    virtual std::string subtitle();
};
重点是接下来的Actionstest.cpp:

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

// 声明一下前进后退的三个方法
CCLayer* NextAction();
CCLayer* BackAction();
CCLayer* RestartAction();

// 当前进行的action的id
static int s_nActionIdx = -1;

/************************************************************************/
/*  创建新的层                                                                     */
/************************************************************************/
CCLayer* CreateLayer(int nIndex)
{
    CCLayer * pLayer = NULL;
	// 根据nIndex的不同而创建不同的层
    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_ROTATIONAL_SKEW_LAYER:
            pLayer = new ActionRotationalSkew(); break;
        case ACTION_ROTATIONAL_SKEW_VS_STANDARD_SKEW_LAYER:
            pLayer = new ActionRotationalSkewVSStandardSkew(); 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_ISSUE1398_LAYER:
            pLayer = new Issue1398(); 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()
{
	// 当前运行的layerid
    ++s_nActionIdx;
	// 超过最大值又返回第一个
    s_nActionIdx = s_nActionIdx % ACTION_LAYER_COUNT;

	// 创建对应的层
    CCLayer* pLayer = CreateLayer(s_nActionIdx);
    // 自动释放
	pLayer->autorelease();
	// 返回层
    return pLayer;
}

CCLayer* BackAction()
{
	// 当前运行的层id
    --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;
}


// 本测试类的runthisTest
void ActionsTestScene::runThisTest()
{
	// 默认第一个
    s_nActionIdx = -1;
	// 添加第一个层
    addChild(NextAction());

	// 切换场景
    CCDirector::sharedDirector()->replaceScene(this);
}

// 获得title
std::string ActionsDemo::title()
{
    return "ActionsTest";
}

// 获得子标题
std::string ActionsDemo::subtitle()
{
    return "";
}

// 进入时的操作
void ActionsDemo::onEnter()
{
	// 基类的进入操作
    CCLayer::onEnter();

    // Or you can create an sprite using a filename. only PNG is supported now. Probably TIFF too
    // 创建几个人物的sprite,并增加一个引用计数
	m_grossini = CCSprite::create(s_pPathGrossini);
    m_grossini->retain();

    m_tamara = CCSprite::create(s_pPathSister1); 
    m_tamara->retain();

    m_kathia = CCSprite::create(s_pPathSister2);
    m_kathia->retain();

	// 加入layer中
    addChild(m_grossini, 1);
    addChild(m_tamara, 2);
    addChild(m_kathia, 3);

	// 设置三个sprite的位置
    m_grossini->setPosition(ccp(VisibleRect::center().x, VisibleRect::bottom().y+VisibleRect::getVisibleRect().size.height/3));
    m_tamara->setPosition(ccp(VisibleRect::center().x, VisibleRect::bottom().y+VisibleRect::getVisibleRect().size.height*2/3));
    m_kathia->setPosition(ccp(VisibleRect::center().x, VisibleRect::bottom().y+VisibleRect::getVisibleRect().size.height/2)); 

    // add title and subtitle
    std::string str = title();
    const char * pTitle = str.c_str();
    CCLabelTTF* label = CCLabelTTF::create(pTitle, "Arial", 18);
    addChild(label, 1);
    label->setPosition( ccp(VisibleRect::center().x, VisibleRect::top().y - 30) );

	// 如果子标题不为空的话就创建对应的子标题
    std::string strSubtitle = subtitle();
    if( ! strSubtitle.empty() ) 
    {
        CCLabelTTF* l = CCLabelTTF::create(strSubtitle.c_str(), "Thonburi", 22);
        addChild(l, 1);
        l->setPosition( ccp(VisibleRect::center().x, VisibleRect::top().y - 60) );
    }    

    // 增加三个menuitem
    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) );

	// 创建menu(记住最后一个要是NULL)
    CCMenu *menu = CCMenu::create(item1, item2, item3, NULL);

	// 三个menuitem的位置
    menu->setPosition(CCPointZero);
    item1->setPosition(ccp(VisibleRect::center().x - item2->getContentSize().width*2, VisibleRect::bottom().y+item2->getContentSize().height/2));
    item2->setPosition(ccp(VisibleRect::center().x, VisibleRect::bottom().y+item2->getContentSize().height/2));
    item3->setPosition(ccp(VisibleRect::center().x + item2->getContentSize().width*2, VisibleRect::bottom().y+item2->getContentSize().height/2));

	// 把menu加入层中
    addChild(menu, 1);
}

// 退出时的操作
void ActionsDemo::onExit()
{
	// 释放这些spriete
    m_grossini->release();
    m_tamara->release();
    m_kathia->release();

	// 退出
    CCLayer::onExit();
}

// restart的callback
void ActionsDemo::restartCallback(CCObject* pSender)
{
	// 创建scene
    CCScene* s = new ActionsTestScene();
    // 增加Restart的层
	s->addChild( RestartAction() );
	// 切换scene
    CCDirector::sharedDirector()->replaceScene(s);
    // 手动释放
	s->release();
}

// next的callback
void ActionsDemo::nextCallback(CCObject* pSender)
{
	// 创建scene
    CCScene* s = new ActionsTestScene();
	// 增加next的层
    s->addChild( NextAction() );
	// 切换到next
    CCDirector::sharedDirector()->replaceScene(s);
    // 手动释放
	s->release();
}

// back的callback
void ActionsDemo::backCallback(CCObject* pSender)
{
	// 创建scene
    CCScene* s = new ActionsTestScene();
    // 增加back的层
	s->addChild( BackAction() );
	// 切换到back
    CCDirector::sharedDirector()->replaceScene(s);
	// 手动释放
    s->release();
}

void ActionsDemo::centerSprites(unsigned int numberOfSprites)
{
	// 获取屏幕size
    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(ccp(s.width/2, s.height/2));
    }
    else if( numberOfSprites == 2 ) 
    {        
        m_kathia->setPosition( ccp(s.width/3, s.height/2));
        m_tamara->setPosition( ccp(2*s.width/3, s.height/2));
        m_grossini->setVisible(false);
    } 
    else if( numberOfSprites == 3 ) 
    {
        m_grossini->setPosition( ccp(s.width/2, s.height/2));
        m_tamara->setPosition( ccp(s.width/4, s.height/2));
        m_kathia->setPosition( ccp(3 * s.width/4, s.height/2));
    }
}

void ActionsDemo::alignSpritesLeft(unsigned int numberOfSprites)
{
	// 获取size
    CCSize s = CCDirector::sharedDirector()->getWinSize();

	// 设置显示居左
    if( numberOfSprites == 1 ) 
    {
        m_tamara->setVisible(false);
        m_kathia->setVisible(false);
        m_grossini->setPosition(ccp(60, s.height/2));
    } 
    else if( numberOfSprites == 2 ) 
    {        
        m_kathia->setPosition( ccp(60, s.height/3));
        m_tamara->setPosition( ccp(60, 2*s.height/3));
        m_grossini->setVisible( false );
    } 
    else if( numberOfSprites == 3 ) 
    {
        m_grossini->setPosition( ccp(60, s.height/2));
        m_tamara->setPosition( ccp(60, 2*s.height/3));
        m_kathia->setPosition( ccp(60, s.height/3));
    }
}

//------------------------------------------------------------------
//
// ActionManual
//
//------------------------------------------------------------------
void ActionManual::onEnter()
{
	// 基类的onEnter
    ActionsDemo::onEnter();

	// 获取size
    CCSize s = CCDirector::sharedDirector()->getWinSize();

	// 对三个sprite的初始设置
    m_tamara->setScaleX( 2.5f);
    m_tamara->setScaleY( -1.0f);
    m_tamara->setPosition( ccp(100,70) );
    m_tamara->setOpacity( 128);

    m_grossini->setRotation( 120);
    m_grossini->setPosition( ccp(s.width/2, s.height/2));
    m_grossini->setColor( ccc3( 255,0,0));

    m_kathia->setPosition( ccp(s.width-100, s.height/2));
    m_kathia->setColor( ccBLUE);
}

// Manual层的子菜单
std::string ActionManual::subtitle()
{
    return "Manual Transformation";
}

//------------------------------------------------------------------
//
//    ActionMove
//
//------------------------------------------------------------------
void ActionMove::onEnter()
{
	// 
    ActionsDemo::onEnter();

	// 放置三个sprite
    centerSprites(3);

	// 获得winsize
    CCSize s = CCDirector::sharedDirector()->getWinSize();

	// 创建三个action
    CCActionInterval*  actionTo = CCMoveTo::create(2, ccp(s.width-40, s.height-40));
    CCActionInterval*  actionBy = CCMoveBy::create(2, ccp(80,80));
	// 注意第三个是actionBy的反向运动
    CCActionInterval*  actionByBack = actionBy->reverse();

	// 对三个sprite进行
    m_tamara->runAction( actionTo);
    m_grossini->runAction( CCSequence::create(actionBy, actionByBack, NULL));
    m_kathia->runAction(CCMoveTo::create(1, ccp(40,40)));
}

std::string ActionMove::subtitle()
{
	// subtitle
    return "MoveTo / MoveBy";
}

//------------------------------------------------------------------
//
// ActionScale
//
//------------------------------------------------------------------
void ActionScale::onEnter()
{
    ActionsDemo::onEnter();

    centerSprites(3);

	// 创建三个scale的action,scaleto使用的是x,y比例一样的方式,剩下两个则是不一样的
    CCActionInterval*  actionTo = CCScaleTo::create(2.0f, 0.5f);
    CCActionInterval*  actionBy = CCScaleBy::create(2.0f, 1.0f, 10.0f);
    CCActionInterval*  actionBy2 = CCScaleBy::create(2.0f, 5.0f, 1.0f);

	// 运行这三个action
    m_grossini->runAction( actionTo);
    m_tamara->runAction( CCSequence::create(actionBy, actionBy->reverse(), NULL));
    m_kathia->runAction( CCSequence::create(actionBy2, actionBy2->reverse(), NULL));
}

std::string ActionScale::subtitle()
{
	// subtitle
    return "ScaleTo / ScaleBy";
}

//------------------------------------------------------------------
//
//    ActionSkew
//
//------------------------------------------------------------------
void ActionSkew::onEnter()
{
    ActionsDemo::onEnter();

    centerSprites(3);

	// 创建对应的skew action
    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);
    CCActionInterval *actionByBack = actionBy->reverse();

	// 运行
    m_tamara->runAction(CCSequence::create(actionTo, actionToBack, NULL));
    m_grossini->runAction(CCSequence::create(actionBy, actionByBack, NULL));

    m_kathia->runAction(CCSequence::create(actionBy2, actionBy2->reverse(), NULL));
}

string ActionSkew::subtitle()
{
    return "SkewTo / SkewBy";
}

// ActionRotationalSkew
void ActionRotationalSkew::onEnter()
{
    ActionsDemo::onEnter();

    this->centerSprites(3);

	// 创建rotate action
    CCRotateTo* actionTo = CCRotateTo::create(2, 37.2f, -37.2f);
    CCRotateTo* actionToBack = CCRotateTo::create(2, 0, 0);
    CCRotateBy* actionBy = CCRotateBy::create(2, 0.0f, -90.0f);
    CCRotateBy* actionBy2 = CCRotateBy::create(2, 45.0f, 45.0f);
    CCRotateBy* actionByBack = (CCRotateBy*)actionBy->reverse();
	// 运行
    m_tamara->runAction(CCSequence::create(actionTo, actionToBack, NULL));
    m_grossini->runAction(CCSequence::create(actionBy, actionByBack, NULL));

    m_kathia->runAction(CCSequence::create(actionBy2, actionBy2->reverse(), NULL));
}

std::string ActionRotationalSkew::subtitle()
{
    return "RotationalSkewTo / RotationalSkewBy";
}



//ActionRotationalSkewVSStandardSkew
void ActionRotationalSkewVSStandardSkew::onEnter()
{
    ActionsDemo::onEnter();

	// 先把这三个sprite给清除掉
    m_tamara->removeFromParentAndCleanup(true);
    m_grossini->removeFromParentAndCleanup(true);
    m_kathia->removeFromParentAndCleanup(true);

	// 获得winsize
    CCSize s = CCDirector::sharedDirector()->getWinSize();

	// 设置一个boxlayer的大小
    CCSize boxSize = CCSizeMake(100.0f, 100.0f);

	// 创建一个带颜色的layer
    CCLayerColor *box = CCLayerColor::create(ccc4(255,255,0,255));
    // 对这个layer设置anchor
	box->setAnchorPoint(ccp(0.5,0.5));
    box->setContentSize( boxSize );
	// 默认layer是不能改变锚点的,所以要改变锚点的话要先ignoreAnchorPointForPosition
    box->ignoreAnchorPointForPosition(false);
    box->setPosition(ccp(s.width/2, s.height - 100 - box->getContentSize().height/2));
    this->addChild(box);
    CCLabelTTF *label = CCLabelTTF::create("Standard cocos2d Skew", "Marker Felt", 16);
    label->setPosition(ccp(s.width/2, s.height - 100 + label->getContentSize().height));
    this->addChild(label);
	// 创建对应的skewby的action
    CCSkewBy* actionTo = CCSkewBy::create(2, 360, 0);
    CCSkewBy* actionToBack = CCSkewBy::create(2, -360, 0);
	// 运行action,要注意的是sequence、spawn等action创建时如果不使用CCArray创建,则最后一个参数一定是NULL
    box->runAction(CCSequence::create(actionTo, actionToBack, NULL));

	// 创建显示的box
    box = CCLayerColor::create(ccc4(255,255,0,255));
    box->setAnchorPoint(ccp(0.5,0.5));
    box->setContentSize(boxSize);
    box->ignoreAnchorPointForPosition(false);
    box->setPosition(ccp(s.width/2, s.height - 250 - box->getContentSize().height/2));
    this->addChild(box);
    label = CCLabelTTF::create("Rotational Skew", "Marker Felt", 16);
    label->setPosition(ccp(s.width/2, s.height - 250 + label->getContentSize().height/2));
    this->addChild(label);
	// rotate如果增加第二个参数,则也会出现skew的效果
    CCRotateBy* actionTo2 = CCRotateBy::create(2, 360, 0);
    CCRotateBy* actionToBack2 = CCRotateBy::create(2, -360, 0);
    box->runAction(CCSequence::create(actionTo2, actionToBack2, NULL));
}
std::string ActionRotationalSkewVSStandardSkew::subtitle()
{
    return "Skew Comparison";
}

// ActionSkewRotateScale
void ActionSkewRotateScale::onEnter()
{
    ActionsDemo::onEnter();
	// 几乎和上个类一致,不特殊解释
    m_tamara->removeFromParentAndCleanup(true);
    m_grossini->removeFromParentAndCleanup(true);
    m_kathia->removeFromParentAndCleanup(true);

    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);

    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";
}

//------------------------------------------------------------------
//
//    ActionRotate
//
//------------------------------------------------------------------
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));

    CCActionInterval*  actionBy = CCRotateBy::create(2 ,  360);
    CCActionInterval*  actionByBack = actionBy->reverse();
    m_grossini->runAction( CCSequence::create(actionBy, actionByBack, NULL));

	// 注意这里,要重复使用必须copy->autorelease(),如果不这样的话,第一次调用的actionTo0就会自动失去效果
    m_kathia->runAction( CCSequence::create(actionTo2, actionTo0->copy()->autorelease(), NULL));
}

std::string ActionRotate::subtitle()
{
    return "RotateTo / RotateBy";
}

//------------------------------------------------------------------
//
// ActionJump
//
//------------------------------------------------------------------
void ActionJump::onEnter()
{
    ActionsDemo::onEnter();

    centerSprites(3);
	// 没多少区别
    CCActionInterval*  actionTo = CCJumpTo::create(2, ccp(300,300), 50, 4);
    CCActionInterval*  actionBy = CCJumpBy::create(2, ccp(300,0), 50, 4);
    CCActionInterval*  actionUp = CCJumpBy::create(2, ccp(0,0), 80, 4);
    // 这里将actionBy的动作做了一次倒转
	CCActionInterval*  actionByBack = actionBy->reverse();

    m_tamara->runAction( actionTo);
    m_grossini->runAction( CCSequence::create(actionBy, actionByBack, NULL));
	// 这里使用了repeatForever,动作将会一直持续下去
    m_kathia->runAction( CCRepeatForever::create(actionUp));
}
std::string ActionJump::subtitle()
{
    return "JumpTo / JumpBy";
}

//------------------------------------------------------------------
//
// ActionBezier
//
//------------------------------------------------------------------
void ActionBezier::onEnter()
{
    ActionsDemo::onEnter();

    CCSize s = CCDirector::sharedDirector()->getWinSize();

    //
    // startPosition can be any coordinate, but since the movement
    // is relative to the Bezier curve, make it (0,0)
    //

    centerSprites(3);

    // sprite 1
    ccBezierConfig bezier;
	// 贝塞尔曲线要控制controlpoint
    bezier.controlPoint_1 = ccp(0, s.height/2);
    bezier.controlPoint_2 = ccp(300, -s.height/2);
    bezier.endPosition = ccp(300,100);

    CCActionInterval*  bezierForward = CCBezierBy::create(3, bezier);
    CCActionInterval*  bezierBack = bezierForward->reverse();    
    CCAction*  rep = CCRepeatForever::create((CCActionInterval*)CCSequence::create( bezierForward, bezierBack, NULL));


    // sprite 2
    m_tamara->setPosition(ccp(80,160));
    ccBezierConfig bezier2;
    bezier2.controlPoint_1 = ccp(100, s.height/2);
    bezier2.controlPoint_2 = ccp(200, -s.height/2);
    bezier2.endPosition = ccp(240,160);

    CCActionInterval*  bezierTo1 = CCBezierTo::create(2, bezier2);    

    // sprite 3
    m_kathia->setPosition(ccp(400,160));
    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";
}

//------------------------------------------------------------------
//
// ActionBlink
//
//------------------------------------------------------------------
void ActionBlink::onEnter()
{
    ActionsDemo::onEnter();

    centerSprites(2);
	// 没有特殊要说的
    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";
}

//------------------------------------------------------------------
//
// ActionFade
//
//------------------------------------------------------------------
void ActionFade::onEnter()
{
    ActionsDemo::onEnter();

    centerSprites(2);

	// FadeIn和FadeOut是对透明度的处理。
    m_tamara->setOpacity( 0 );
    CCActionInterval*  action1 = CCFadeIn::create(1.0f);
    CCActionInterval*  action1Back = action1->reverse();

    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";
}

//------------------------------------------------------------------
//
// ActionTint
//
//------------------------------------------------------------------

void ActionTint::onEnter()
{
    ActionsDemo::onEnter();

    centerSprites(2);
	// 颜色的变幻
    CCActionInterval*  action1 = CCTintTo::create(2, 255, 0, 255);
    CCActionInterval*  action2 = CCTintBy::create(2, -127, -255, -127);
    CCActionInterval*  action2Back = action2->reverse();

    m_tamara->runAction( action1);
    m_kathia->runAction( CCSequence::create( action2, action2Back, NULL));
}

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

//------------------------------------------------------------------
//
// ActionAnimate
//
//------------------------------------------------------------------
void ActionAnimate::onEnter()
{
    ActionsDemo::onEnter();

    centerSprites(3);


    //
    // Manual animation
    //
	// 使用图片创建动画
	// 先创建一个空的animation
    CCAnimation* animation = CCAnimation::create();
    for( int i=1;i<15;i++)
    {
        char szName[100] = {0};
        sprintf(szName, "Images/grossini_dance_%02d.png", i);
        animation->addSpriteFrameWithFileName(szName);
    }
    // should last 2.8 seconds. And there are 14 frames.
	// 设置每一帧的时间
    animation->setDelayPerUnit(2.8f / 14.0f);
	// 设置结束后存储帧
    animation->setRestoreOriginalFrame(true);

	// 创建动画
    CCAnimate* action = CCAnimate::create(animation);
    m_grossini->runAction(CCSequence::create(action, action->reverse(), NULL));
    
    //
    // File animation
    //
    // With 2 loops and reverse
	// 通过plist文件创建
	// 获取animationcache的单例
    CCAnimationCache *cache = CCAnimationCache::sharedAnimationCache();
    // 添加进缓存
	cache->addAnimationsWithFile("animations/animations-2.plist");
    
	// 根据名字创建
	CCAnimation *animation2 = cache->animationByName("dance_1");

    CCAnimate* action2 = CCAnimate::create(animation2);
    m_tamara->runAction(CCSequence::create(action2, action2->reverse(), NULL));

// TODO:
//     observer_ = [[NSNotificationCenter defaultCenter] addObserverForName:CCAnimationFrameDisplayedNotification object:nil queue:nil usingBlock:^(NSNotification* notification) {
// 
//         NSDictionary *userInfo = [notification userInfo];
//         NSLog(@"object %@ with data %@", [notification object], userInfo );
//     }];


    //
    // File animation
    //
    // with 4 loops
    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";
}

//------------------------------------------------------------------
//
//    ActionSequence
//
//------------------------------------------------------------------
void ActionSequence::onEnter()
{
    ActionsDemo::onEnter();

    alignSpritesLeft(1);

    CCFiniteTimeAction*  action = CCSequence::create(
        CCMoveBy::create( 2, ccp(240,0)),
        CCRotateBy::create( 2,  540),
        NULL);

    m_grossini->runAction(action);
}

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

//------------------------------------------------------------------
//
//    ActionSequence2
//
//------------------------------------------------------------------
void ActionSequence2::onEnter()
{
    ActionsDemo::onEnter();

    alignSpritesLeft(1);

    m_grossini->setVisible(false);
	// 这里我稍微改了一下,最后传递了一个参数
	CCString *str = CCStringMake("next");
	str->retain();
	// 创建了三个不同的callbackfunc
    CCFiniteTimeAction*  action = CCSequence::create(
        CCPlace::create(ccp(200,200)),
        CCShow::create(),
        CCMoveBy::create(1, ccp(100,0)),
        CCCallFunc::create(this, callfunc_selector(ActionSequence2::callback1)),
        CCCallFuncN::create(this, callfuncN_selector(ActionSequence2::callback2)),
        CCCallFuncND::create(this, callfuncND_selector(ActionSequence2::callback3), str),
        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(ccp( 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(ccp( s.width/4*2,s.height/2));

    addChild(label);
}

void ActionSequence2::callback3(CCNode* sender, void* data)
{
    CCSize s = CCDirector::sharedDirector()->getWinSize();
	// 测试刚才传过来的参数对不对
	CCLOG("%s", ((CCString *)data)->getCString());
    CCLabelTTF *label = CCLabelTTF::create("callback 3 called", "Marker Felt", 16);
    label->setPosition(ccp( s.width/4*3,s.height/2));

    addChild(label);
}

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

//------------------------------------------------------------------
//
//    ActionCallFunc
//
//------------------------------------------------------------------
void ActionCallFunc::onEnter()
{
    ActionsDemo::onEnter();

	// 类似,没有多少可说的
    centerSprites(3);

    CCFiniteTimeAction*  action = CCSequence::create(
        CCMoveBy::create(2, ccp(200,0)),
        CCCallFunc::create(this, callfunc_selector(ActionCallFunc::callback1)), 
        NULL);

    CCFiniteTimeAction*  action2 = CCSequence::create(
        CCScaleBy::create(2 ,  2),
        CCFadeOut::create(2),
        CCCallFuncN::create(this, callfuncN_selector(ActionCallFunc::callback2)), 
        NULL);

    CCFiniteTimeAction*  action3 = CCSequence::create(
        CCRotateBy::create(3 , 360),
        CCFadeOut::create(2),
        CCCallFuncND::create(this, callfuncND_selector(ActionCallFunc::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(ccp( 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(ccp( 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";
}

//------------------------------------------------------------------
//
// ActionCallFuncND
//
//------------------------------------------------------------------
void ActionCallFuncND::onEnter()
{
    ActionsDemo::onEnter();

    centerSprites(1);

	// 类似,但这次使用了一个自动移除的方法
    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";
}

void ActionCallFuncND::removeFromParentAndCleanup(CCNode* pSender, void* data)
{
	// 检查传过来的参数
    bool bCleanUp = data != NULL;
	// 如果传过来的参数为真,则移除节点并清除所有的action
    m_grossini->removeFromParentAndCleanup(bCleanUp);
}

//------------------------------------------------------------------
//
// ActionSpawn
//
//------------------------------------------------------------------

void ActionSpawn::onEnter()
{
    ActionsDemo::onEnter();

	// 设置一个角色
    alignSpritesLeft(1);

	// 创建action,同时进行jump和rotate
    CCAction*  action = CCSpawn::create(
        CCJumpBy::create(2, ccp(300,0), 50, 4),
        CCRotateBy::create( 2,  720),
        NULL);

    m_grossini->runAction(action);
}

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


//------------------------------------------------------------------
//
// ActionRepeatForever
//
//------------------------------------------------------------------
void ActionRepeatForever::onEnter()
{
    ActionsDemo::onEnter();

    centerSprites(1);
	// 先延迟一秒,然后再无限重复callfunc
    CCFiniteTimeAction*  action = CCSequence::create(
        CCDelayTime::create(1),
        CCCallFuncN::create( this, callfuncN_selector(ActionRepeatForever::repeatForever) ), 
        NULL);

    m_grossini->runAction(action);
}

void ActionRepeatForever::repeatForever(CCNode* pSender)
{
	// 创建了一个每秒旋转360度的action
    CCRepeatForever *repeat = CCRepeatForever::create( CCRotateBy::create(1.0f, 360) );

    pSender->runAction(repeat);
}

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


//------------------------------------------------------------------
//
// ActionRotateToRepeat
//
//------------------------------------------------------------------
void ActionRotateToRepeat::onEnter()
{
    ActionsDemo::onEnter();

	// 创建两个人物
    centerSprites(2);

    CCActionInterval*  act1 = CCRotateTo::create(1, 90);
    CCActionInterval*  act2 = CCRotateTo::create(1, 0);
    CCActionInterval*  seq = (CCActionInterval*)(CCSequence::create(act1, act2, NULL));
    CCAction*  rep1 = CCRepeatForever::create(seq);
	// 注意这里依然是使用了copy->autorelease的方式
    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";
}


//------------------------------------------------------------------
//
// ActionRotateJerk
//
//------------------------------------------------------------------
void ActionRotateJerk::onEnter()
{
    ActionsDemo::onEnter();
	// 没什么需要解释的
    centerSprites(2);

    CCFiniteTimeAction*  seq = CCSequence::create(
        CCRotateTo::create(0.5f, -20),
        CCRotateTo::create(0.5f, 20),
        NULL);

    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";
}

//------------------------------------------------------------------
//
// ActionReverse
//
//------------------------------------------------------------------
void ActionReverse::onEnter()
{
    ActionsDemo::onEnter();

    alignSpritesLeft(1);
	// 创建跳和返回
    CCActionInterval*  jump = CCJumpBy::create(2, ccp(300,0), 50, 4);
    CCFiniteTimeAction*  action = CCSequence::create( jump, jump->reverse(), NULL);

    m_grossini->runAction(action);
}

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


//------------------------------------------------------------------
//
// ActionDelayTime
//
//------------------------------------------------------------------
void ActionDelayTime::onEnter()
{
    ActionsDemo::onEnter();

    alignSpritesLeft(1);

	// 创建延时再移动
    CCActionInterval*  move = CCMoveBy::create(1, ccp(150,0));
    CCFiniteTimeAction*  action = CCSequence::create( move, CCDelayTime::create(2), move, NULL);

    m_grossini->runAction(action);
}

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


//------------------------------------------------------------------
//
// ActionReverseSequence
//
//------------------------------------------------------------------
void ActionReverseSequence::onEnter()
{
    ActionsDemo::onEnter();

    alignSpritesLeft(1);

    CCActionInterval*  move1 = CCMoveBy::create(1, ccp(250,0));
    CCActionInterval*  move2 = CCMoveBy::create(1, ccp(0,50));
    CCFiniteTimeAction*  seq = CCSequence::create( move1, move2, move1->reverse(), NULL);
	// 创建移动到A,移动到B,反移动,以及整个序列action倒过来。
    CCFiniteTimeAction*  action = CCSequence::create( seq, seq->reverse(), NULL);

    m_grossini->runAction(action);
}

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


//------------------------------------------------------------------
//
// ActionReverseSequence2
//
//------------------------------------------------------------------
void ActionReverseSequence2::onEnter()
{
    ActionsDemo::onEnter();

    alignSpritesLeft(2);


    // Test:
    //   Sequence should work both with IntervalAction and InstantActions
    CCActionInterval*  move1 = CCMoveBy::create(1, ccp(250,0));
    CCActionInterval*  move2 = CCMoveBy::create(1, ccp(0,50));
    CCToggleVisibility*  tog1 = new CCToggleVisibility();
    CCToggleVisibility*  tog2 = new CCToggleVisibility();
    tog1->autorelease();
    tog2->autorelease();
	// 创建移动到A,隐藏,移动到B,显示,然后反作用A,再反回来
    CCFiniteTimeAction*  seq = CCSequence::create( move1, tog1, move2, tog2, move1->reverse(), NULL);
    CCActionInterval*  action = CCRepeat::create((CCActionInterval*)(CCSequence::create( seq, seq->reverse(), NULL)), 3);



    // Test:
    //   Also test that the reverse of Hide is Show, and vice-versa
    m_kathia->runAction(action);

    CCActionInterval*  move_tamara = CCMoveBy::create(1, ccp(100,0));
    CCActionInterval*  move_tamara2 = CCMoveBy::create(1, ccp(50,0));
	// 这里使用InstantAction来处理。这种类型的action是立即完成的
    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";
}

//------------------------------------------------------------------
//
// ActionRepeat
//
//------------------------------------------------------------------
void ActionRepeat::onEnter()
{
    ActionsDemo::onEnter();

    alignSpritesLeft(2);

	// 创建repeat的action,也没有什么需要解释的
    CCActionInterval*  a1 = CCMoveBy::create(1, ccp(150,0));
    CCActionInterval*  action1 = CCRepeat::create(
        CCSequence::create( CCPlace::create(ccp(60,60)), a1, NULL) , 
        3); 
    CCAction*  action2 = CCRepeatForever::create(
        (CCActionInterval*)(CCSequence::create((CCActionInterval*)(a1->copy()->autorelease()), a1->reverse(), NULL))
        );

    m_kathia->runAction(action1);
    m_tamara->runAction(action2);
}

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

//------------------------------------------------------------------
//
// ActionOrbit
//
//------------------------------------------------------------------
void ActionOrbit::onEnter()
{
    ActionsDemo::onEnter();
	// 放置3个sprite
    centerSprites(3);

	// 这里使用orbitcamera,旋转摄像机。在2秒内在半径为1的球面上绕纵轴旋转180度
	// 这个有点复杂,先不管它了,以后用的着的时候再专门研究一下。
    CCActionInterval*  orbit1 = CCOrbitCamera::create(2,1, 0, 0, 180, 0, 0);
    CCFiniteTimeAction*  action1 = CCSequence::create(
        orbit1,
        orbit1->reverse(),
        NULL);

	// 第二个
    CCActionInterval*  orbit2 = CCOrbitCamera::create(2,1, 0, 0, 180, -45, 0);
    CCFiniteTimeAction*  action2 = CCSequence::create(
        orbit2,
        orbit2->reverse(),
        NULL);

    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, ccp(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";
}

//------------------------------------------------------------------
//
// ActionFollow
//
//------------------------------------------------------------------
void ActionFollow::onEnter()
{
    ActionsDemo::onEnter();

    centerSprites(1);
    CCSize s = CCDirector::sharedDirector()->getWinSize();

    m_grossini->setPosition(ccp(-200, s.height / 2));
    CCActionInterval* move      = CCMoveBy::create(2, ccp(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);
	// 创建了一个follow的action,用来跟随这个node。参数是在follow时跟着follow的范围
    this->runAction(CCFollow::create(m_grossini, CCRectMake(0, 0, s.width * 2 - 100, s.height)));
}

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

void ActionTargeted::onEnter()
{
    ActionsDemo::onEnter();
    centerSprites(2);

	// 创建jump和rotate的action
    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();

	// 以下两个action是控制目标动画,直接控制目标对象运行某个action
    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";
}

void Issue1305::onEnter()
{
    ActionsDemo::onEnter();
    centerSprites(0);

	// 创建了一个临时sprite
    m_pSpriteTmp = CCSprite::create("Images/grossini.png");
    /* c++ can't support block, so we use CCCallFuncN instead.
    [spriteTmp_ runAction:[CCCallBlockN actionWithBlock:^(CCNode* node) {
        NSLog(@"This message SHALL ONLY appear when the sprite is added to the scene, NOT BEFORE");
    }] ];
    */
	// 这个sprite将会运行一个回调函数log
    m_pSpriteTmp->runAction(CCCallFuncN::create(this, callfuncN_selector(Issue1305::log)));
    // 因为没有加入layer进行绘制,所以先retain一下
	m_pSpriteTmp->retain();
	// 将会在两秒后执行addSprite方法1次
    scheduleOnce(schedule_selector(Issue1305::addSprite), 2);
}

void Issue1305::log(CCNode* pSender)
{
	// 当完成了addSprite方法后显示这条LOG
    CCLog("This message SHALL ONLY appear when the sprite is added to the scene, NOT BEFORE");
}

void Issue1305::onExit()
{
	// 退出时释放掉,因为之前retain了
    m_pSpriteTmp->release();
    ActionsDemo::onExit();
}

void Issue1305::addSprite(float dt)
{
	// 设置位置并加入
    m_pSpriteTmp->setPosition(ccp(250,250));
    addChild(m_pSpriteTmp);
}

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.";
}

void Issue1305_2::onEnter()
{
    ActionsDemo::onEnter();
    centerSprites(0);

	// 先创建一个sprite
    CCSprite *spr = CCSprite::create("Images/grossini.png");
    spr->setPosition(ccp(200,200));
    addChild(spr);

	// 移动action
    CCMoveBy* act1 = CCMoveBy::create(2 ,ccp(0, 100));
    /* c++ can't support block, so we use CCCallFuncN instead.
    id act2 = [CCCallBlock actionWithBlock:^{
        NSLog(@"1st block");
    }];
    id act3 = [CCMoveBy create:2 position:ccp(0, -100)];
    id act4 = [CCCallBlock actionWithBlock:^{
        NSLog(@"2nd block");
    }];
    id act5 = [CCMoveBy create:2 position:ccp(100, -100)];
    id act6 = [CCCallBlock actionWithBlock:^{
        NSLog(@"3rd block");
    }];
    id act7 = [CCMoveBy create:2 position:ccp(-100, 0)];
    id act8 = [CCCallBlock actionWithBlock:^{
        NSLog(@"4th block");
    }];
    */

	// 创建一些不同的callfunc
    CCCallFunc* act2 = CCCallFunc::create(this, callfunc_selector(Issue1305_2::printLog1));
    CCMoveBy* act3 = CCMoveBy::create(2, ccp(0, -100));
    CCCallFunc* act4 = CCCallFunc::create(this, callfunc_selector(Issue1305_2::printLog2));
    CCMoveBy* act5 = CCMoveBy::create(2, ccp(100, -100));
    CCCallFunc* act6 = CCCallFunc::create(this, callfunc_selector(Issue1305_2::printLog3));
    CCMoveBy* act7 = CCMoveBy::create(2, ccp(-100, 0));
    CCCallFunc* act8 = CCCallFunc::create(this, callfunc_selector(Issue1305_2::printLog4));

	// 依次运行
    CCFiniteTimeAction* actF = CCSequence::create(act1, act2, act3, act4, act5, act6, act7, act8, NULL);

    //    [spr runAction:actF];
	// 使用actionManager来为这个sprite加入action
    CCDirector::sharedDirector()->getActionManager()->addAction(actF ,spr, false);

}

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

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

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

void Issue1305_2::printLog4()
{
    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";
}

void Issue1288::onEnter()
{
    ActionsDemo::onEnter();
    centerSprites(0);

	// 创建一个sprite
    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);
    CCRepeat* act4 = CCRepeat::create(act3, 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.";
}

void Issue1288_2::onEnter()
{
    ActionsDemo::onEnter();
    centerSprites(0);
	// 没啥可说的
    CCSprite *spr = CCSprite::create("Images/grossini.png");
    spr->setPosition(ccp(100, 100));
    addChild(spr);

    CCMoveBy* act1 = CCMoveBy::create(0.5, ccp(100, 0));
    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";
}


void Issue1327::onEnter()
{
    ActionsDemo::onEnter();
    centerSprites(0);
	// 
    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));

    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());
}

//Issue1398
void Issue1398::incrementInteger()
{
    m_nTestInteger++;
    CCLog("incremented to %d", m_nTestInteger);
}

void Issue1398::onEnter()
{
    ActionsDemo::onEnter();
    this->centerSprites(0);

    m_nTestInteger = 0;
    CCLog("testInt = %d", m_nTestInteger);

    this->runAction(
        CCSequence::create(
            CCCallFuncND::create(this, callfuncND_selector(Issue1398::incrementIntegerCallback), (void*)"1"),
            CCCallFuncND::create(this, callfuncND_selector(Issue1398::incrementIntegerCallback), (void*)"2"),
            CCCallFuncND::create(this, callfuncND_selector(Issue1398::incrementIntegerCallback), (void*)"3"),
            CCCallFuncND::create(this, callfuncND_selector(Issue1398::incrementIntegerCallback), (void*)"4"),
            CCCallFuncND::create(this, callfuncND_selector(Issue1398::incrementIntegerCallback), (void*)"5"),
            CCCallFuncND::create(this, callfuncND_selector(Issue1398::incrementIntegerCallback), (void*)"6"),
            CCCallFuncND::create(this, callfuncND_selector(Issue1398::incrementIntegerCallback), (void*)"7"),
            CCCallFuncND::create(this, callfuncND_selector(Issue1398::incrementIntegerCallback), (void*)"8"),
            NULL));
}

void Issue1398::incrementIntegerCallback(CCNode* pSender, void* data)
{
    this->incrementInteger();
    CCLog((char*)data);
}

std::string Issue1398::subtitle()
{
    return "See console: You should see an 8";
}

std::string Issue1398::title()
{
    return "Issue 1398";
}

/** ActionCatmullRom
 */
void ActionCatmullRom::onEnter()
{
    ActionsDemo::onEnter();
    
    this->centerSprites(2);
    
    CCSize s = CCDirector::sharedDirector()->getWinSize();
    
	//
	// sprite 1 (By)
	//
	// startPosition can be any coordinate, but since the movement
	// is relative to the Catmull Rom curve, it is better to start with (0,0).
	//
	
    m_tamara->setPosition(ccp(50, 50));
	
    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));
    
    CCCatmullRomBy *action = CCCatmullRomBy::create(3, array);
    CCFiniteTimeAction *reverse = action->reverse();
	
    CCFiniteTimeAction *seq = CCSequence::create(action, reverse, NULL);
	
    m_tamara->runAction(seq);
	
	
	//
	// sprite 2 (To)
	//
	// The startPosition is not important here, because it uses a "To" action.
	// The initial position will be the 1st point of the Catmull Rom path
	//    
    
    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));
    
    CCCatmullRomTo *action2 = CCCatmullRomTo::create(3, array2);
    CCFiniteTimeAction *reverse2 = action2->reverse();
	
    CCFiniteTimeAction *seq2 = CCSequence::create(action2, reverse2, NULL);
	
    m_kathia->runAction(seq2);
    
    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();
    
	// move to 50,50 since the "by" path will start at 50,50
	kmGLPushMatrix();
	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";
}

/** ActionCardinalSpline
 */
void ActionCardinalSpline::onEnter()
{
    ActionsDemo::onEnter();
	
    this->centerSprites(2);
	
    CCSize s = CCDirector::sharedDirector()->getWinSize();
    
	// 创建一个CCPointArray
    CCPointArray *array = CCPointArray::create(20);
    
	// 在array里面增加控制点
    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));
    
	//
	// sprite 1 (By)
	//
	// Spline with no tension (tension==0)
	//
    
	// 根据控制点创建cardinalsplineby 的action
    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);
	
	//
	// sprite 2 (By)
	//
	// Spline with high tension (tension==1)
	//
    
    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);
	
    m_pArray = array;
	// 为了之后再使用一次所以要先retain
    array->retain();
}

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

void ActionCardinalSpline::draw()
{
    ActionsDemo::draw();
	
	// move to 50,50 since the "by" path will start at 50,50
	kmGLPushMatrix();
	kmGLTranslatef(50, 50, 0);
	// 根据ccparray来绘制线条
	ccDrawCardinalSpline(m_pArray, 0, 100);
	kmGLPopMatrix();
    
    CCSize s = CCDirector::sharedDirector()->getWinSize();
    
	kmGLPushMatrix();
	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";
}

/** PauseResumeActions
 */

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)));
    
    this->schedule(schedule_selector(PauseResumeActions::pause), 3, false, 0);
    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);
	// 通过actionmanager来计数
    m_pPausedTargets = director->getActionManager()->pauseAllRunningActions();
    // 保持目标指针
	CC_SAFE_RETAIN(m_pPausedTargets);
}

void PauseResumeActions::resume(float dt)
{
    CCLog("Resuming");
    CCDirector *director = CCDirector::sharedDirector();
    director->getActionManager()->resumeTargets(m_pPausedTargets);
}

其实有不少地方也没有深入去解释,不过大致是这样了。基本上老实看完这里面的代码,对action的控制方式也就有了一定了解,可以自己尝试如何写action了。

你可能感兴趣的:(cocos2d-x 笔记(五) TestCpp源码分析:Actions)