首页 > 代码库 > Cocos2d-x如何控制动作速度

Cocos2d-x如何控制动作速度

基本动作和组合动作实现了针对精灵的各种运动和动画效果的改变。但这样的改变速度匀速的、线性的。通过ActionEase及其的派生类和Speed 类我们可以使精灵以非匀速或非线性速度运动,这样看起了效果更加逼真。

ActionEase的类图如下图所示。



下面我们通过一个实例介绍一下这些动作中速度的控制的使用,这个实例如下图所示,上图是一个操作菜单场景,选择菜单可以进入到下图动作场景,在下图动作场景中点击Go按钮可以执行我们选择的动作效果,点击Back按钮可以返回到菜单场景。


下面我们再看看具体的程序代码,首先看一下看HelloWorldScene.h文件,它的代码如下:

#ifndef __HELLOWORLD_SCENE_H__

#define __HELLOWORLD_SCENE_H__

 

#include "cocos2d.h"

#include "MyActionScene.h"

 

typedef enum                                                                                                                                         ①

{

    kEaseIn = 1

   ,kEaseOut

   ,kEaseInOut

   ,kEaseSineIn

   ,kEaseSineOut

   ,kEaseSineInOut

   ,kEaseExponentialIn

   ,kEaseExponentialOut

   ,kEaseExponentialInOut

   ,kSpeed

   

} ActionTypes;                                                                                                                            

 

 

class HelloWorld : public cocos2d::Layer

{

public:

   static cocos2d::Scene* createScene();

   virtual bool init(); 

   void OnClickMenu(cocos2d::Ref* pSender);

   

   CREATE_FUNC(HelloWorld);

};

 

#endif // __HELLOWORLD_SCENE_H__

上述代码第①~②是定义个枚举类型ActionTypes,枚举类型ActionTypes中定义了10个常量,这10个常量对应10个菜单项。

HelloWorldScene的实现代码HelloWorldScene.ccp文件,它的主要代码如下:

bool HelloWorld::init()

{

    if( !Layer::init() )

    {

         returnfalse;

    }

 

    SizevisibleSize = Director::getInstance()->getVisibleSize();

    Pointorigin = Director::getInstance()->getVisibleOrigin();

 

    autobg = Sprite::create("background.png");

    bg->setPosition(Point(visibleSize.width/2,visibleSize.height /2));

    this->addChild(bg);

 

    autopItmLabel1 = Label::createWithBMFont("fonts/fnt2.fnt","EaseIn");

    autopItmMenu1 = MenuItemLabel::create(pItmLabel1,

              CC_CALLBACK_1(HelloWorld::OnClickMenu, this));

    pItmMenu1->setTag(kEaseIn);

 

    autopItmLabel2 = Label::createWithBMFont("fonts/fnt2.fnt","EaseOut");

    autopItmMenu2 = MenuItemLabel::create(pItmLabel2,

             CC_CALLBACK_1(HelloWorld::OnClickMenu,this));

    pItmMenu2->setTag(kEaseOut);

 

    autopItmLabel3 = Label::createWithBMFont("fonts/fnt2.fnt","EaseInOut");

    autopItmMenu3 = MenuItemLabel::create(pItmLabel3,

             CC_CALLBACK_1(HelloWorld::OnClickMenu,this));

    pItmMenu3->setTag(kEaseInOut);

 

    autopItmLabel4 = Label::createWithBMFont("fonts/fnt2.fnt","EaseSineIn");

    autopItmMenu4 = MenuItemLabel::create(pItmLabel4,

             CC_CALLBACK_1(HelloWorld::OnClickMenu,this));

    pItmMenu4->setTag(kEaseSineIn);

 

    autopItmLabel5 = Label::createWithBMFont("fonts/fnt2.fnt", "EaseSineOut");

    autopItmMenu5 = MenuItemLabel::create(pItmLabel5,

             CC_CALLBACK_1(HelloWorld::OnClickMenu,this));

    pItmMenu5->setTag(kEaseSineOut);

 

    autopItmLabel6 = Label::createWithBMFont("fonts/fnt2.fnt","EaseSineInOut");

    autopItmMenu6 = MenuItemSprite::create(pItmLabel6,

             CC_CALLBACK_1(HelloWorld::OnClickMenu,this));

    pItmMenu6->setTag(kEaseSineInOut);

 

    autopItmLabel7 = Label::createWithBMFont("fonts/fnt2.fnt","EaseExponentialIn");

    autopItmMenu7 = MenuItemSprite::create(pItmLabel7,

             CC_CALLBACK_1(HelloWorld::OnClickMenu,this));

    pItmMenu7->setTag(kEaseExponentialIn);

 

    autopItmLabel8 = Label::createWithBMFont("fonts/fnt2.fnt","EaseExponentialOut");

    autopItmMenu8 = MenuItemLabel::create(pItmLabel8,

             CC_CALLBACK_1(HelloWorld::OnClickMenu,this));

    pItmMenu8->setTag(kEaseExponentialOut);

 

    autopItmLabel9 = Label::createWithBMFont("fonts/fnt2.fnt","EaseExponentialInOut");

    autopItmMenu9 = MenuItemLabel::create(pItmLabel9,

             CC_CALLBACK_1(HelloWorld::OnClickMenu,this));

    pItmMenu9->setTag(kEaseExponentialInOut);

 

    autopItmLabel10 = Label::createWithBMFont("fonts/fnt2.fnt","Speed");

    autopItmMenu10 = MenuItemLabel::create(pItmLabel10,

             CC_CALLBACK_1(HelloWorld::OnClickMenu,this));

    pItmMenu10->setTag(kSpeed);

 

    automn = Menu::create(pItmMenu1,pItmMenu2,pItmMenu3,pItmMenu4,pItmMenu5,

         pItmMenu6,pItmMenu7,pItmMenu8,pItmMenu9,pItmMenu10,NULL);

 

    mn->alignItemsInColumns(2,2, 2, 2, 2, NULL);

 this->addChild(mn);

 

    returntrue;

}

 

void HelloWorld::OnClickMenu(Ref* pSender)

{

    MenuItem*nmitem = (MenuItem*)pSender;

 

    auto  sc = Scene::create();

    auto  layer = MyAction::create();

    layer->setTag(nmitem->getTag());

 

    sc->addChild(layer);

 

    autoreScene = TransitionSlideInR::create(1.0f, sc);

    Director::getInstance()->replaceScene(reScene);

}

在上诉代码大家比较熟悉了,我们这里就不再介绍了。下面我们再看看下一个场景MyActionScene,它的MyActionScene.ccp,它的主要代码如下:

void MyAction::goMenu(Ref* pSender)

{  

    log("Tag = %i",this->getTag());

   FiniteTimeAction * ac1 = (FiniteTimeAction *)MoveBy::create(2,Point(200, 0));

   FiniteTimeAction * ac2 = ((FiniteTimeAction *)ac1)->reverse();

   

   ActionInterval * ac = Sequence::create(ac1, ac2, NULL);

   

   switch (this->getTag()) {

       case kEaseIn:

           sprite->runAction(EaseIn::create(ac, 3));                                                                        ①

            break;

       case kEaseOut:

           sprite->runAction(EaseOut::create(ac, 3));                                                            ②

            break;

       case kEaseInOut:

            sprite->runAction(EaseInOut::create(ac,3));                                                         ③

            break;

       case kEaseSineIn:

           sprite->runAction(EaseSineIn::create(ac));                                                           ④

            break;

       case kEaseSineOut:

           sprite->runAction(EaseSineOut::create(ac));                                                                  ⑤

            break;

       case kEaseSineInOut:

           sprite->runAction(EaseSineInOut::create(ac));                                                              ⑥

            break;

       case kEaseExponentialIn:

           sprite->runAction(EaseExponentialIn::create(ac));                                                       ⑦

            break;

       case kEaseExponentialOut:

           sprite->runAction(EaseExponentialOut::create(ac));                                                     ⑧

            break;

       case kEaseExponentialInOut:

           sprite->runAction(EaseExponentialInOut::create(ac));                                        ⑨

            break;

       case kSpeed:

           sprite->runAction(Speed::create(ac, (CCRANDOM_0_1() * 5)));                                  ⑩

            break;

   }

}

第①行代码sprite->runAction(EaseIn::create(ac, 3))是以3倍速度由慢至快。第②代码sprite->runAction(EaseOut::create(ac, 3))是以3倍速度由快至慢。第③代码sprite->runAction(EaseInOut::create(ac, 3))是以3倍速度由慢至快再由快至慢。

第④代码sprite->runAction(EaseSineIn::create(ac))是采用正弦变换速度由慢至快。第⑤代码sprite->runAction(EaseSineOut::create(ac))是采用正弦变换速度由快至慢。第⑥代码sprite->runAction(EaseOut::create(ac, 3)) 是采用正弦变换速度由慢至快再由快至慢。

第⑦代码sprite->runAction(EaseExponentialIn::create(ac))采用指数变换速度由慢至快。第⑧代码sprite->runAction(EaseExponentialOut::create(ac))采用指数变换速度由快至慢。第⑨代码sprite->runAction(EaseExponentialInOut::create(ac)) 采用指数变换速度由慢至快再由快至慢。

第⑩代码sprite->runAction(Speed::create(ac, (CCRANDOM_0_1() * 5))) 随机设置变换速度。



更多内容请关注Cocos2d-x系列图书《Cocos2d-x实战(卷Ⅰ):C++开发》
本书交流讨论网站:http://www.cocoagame.net
欢迎加入cocos2d-x技术讨论群:257760386、327403678