动作往往不是单一而是复杂的组合。我们可以按照一定的次序将上述基本动作组合起来形成连贯的一套组合动作。组合动作包括以下几类顺序、并列、有限次数重复、无限次数重复、反动作和动画。动画我们会在下一节介绍本节我们重点顺序、并列、有限次数重复、无限次数重复和反动
下面我们通过一个实例介绍一下组合动作的使用这个实例如下图所示下图是一个操作菜单场景选择菜单可以进入到下图动作场景在下图动作场景中点击Go按钮可以执行我们选择的动作效果点击Back按钮可以返回到菜单场景。
下面我们再看看具体的程序代码首先看一下看HelloWorldScene.h文件它的代码如下
#ifndef __HELLOWORLD_SCENE_H__ #define __HELLOWORLD_SCENE_H__ #include "cocos2d.h" #include "MyActionScene.h" ① typedef enum { ② kSequence = 100, kSpawn, kRepeate, kRepeatForever1, kReverse } 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__
上述代码是中第①行是引入头文件MyActionScene.h。第②~③是定义个枚举类型ActionTypes枚举类型ActionTypes中定义了5个常量这5个常量对应5个菜单项。第④行声明了一个函数用来在选择不同菜单时候的回调。
在上诉代码大家比较熟悉了我们这里就不再介绍了。下面我们再看看下一个场景MyActionScene它的MyActionScene.h代码如下
#ifndef __MYACTION_SCENE_H__ #define __MYACTION_SCENE_H__ #include "cocos2d.h" #include "HelloWorldScene.h" class MyAction : public cocos2d::Layer { cocos2d::Sprite *sprite; public: staticcocos2d::Scene* createScene(); virtual bool init(); CREATE_FUNC(MyAction); void goMenu(cocos2d::Ref* pSender); void backMenu(cocos2d::Ref* pSender); voidOnSequence(cocos2d::Ref* pSender); ① void OnSpawn(cocos2d::Ref* pSender); void OnRepeat(cocos2d::Ref* pSender); void OnReverse(cocos2d::Ref* pSender); void OnRepeatForever(cocos2d::Ref* pSender); ② }; #endif // __MYACTION_SCENE_H__
在.h文件中第①②行代码是声明了5个用于菜单选择的回调函数。
MyActionScene的实现代码MyActionScene.ccp文件其中点击Go按钮时候调用的函数MyAction::goMenu代码如下
void MyAction::goMenu(Ref* pSender) { log("Tag= %i",this->getTag()); switch (this->getTag()) { casekSequence: this->OnSequence(pSender); break; casekSpawn: this->OnSpawn(pSender); break; casekRepeate: this->OnRepeat(pSender); break; casekRepeatForever1: this->OnRepeatForever(pSender); break; case kReverse: this->OnReverse(pSender); break; default: break; } }
我们在这个函数中根据选择菜单不同调用不同的函数。
MyActionScene.ccp中MyActionLayer::OnSequence代码如下 void MyAction::OnSequence(Ref* pSender) { Size size = Director::getInstance()->getVisibleSize(); Pointp = Point(size.width/2, 200); FiniteTimeAction* ac0 =(FiniteTimeAction*)sprite->runAction(Place::create(p)); ① FiniteTimeAction* ac1 = (FiniteTimeAction*)sprite->runAction( MoveTo::create(2,Point(size.width- 130, size.height - 200))); ② FiniteTimeAction* ac2 = (FiniteTimeAction*)sprite->runAction( JumpBy::create(2,Point(8, 8),6, 3)); ③ FiniteTimeAction* ac3 =(FiniteTimeAction*)sprite->runAction(Blink::create(2,3)); ④ FiniteTimeAction* ac4 = (FiniteTimeAction*)sprite->runAction( TintBy::create(0.5,0,255,255)); ⑤ sprite->runAction(Sequence::create(ac0,ac1, ac2, ac3, ac4, ac0, NULL)); ⑥ }
上述代码实现了顺序动作演示其中主要使用的类是SequenceSequence是派生于ActionInterval属性间隔动作。Sequence作用就是顺序排列若干个动作然后按先后次序逐个执行。代码⑥行执行SequenceSequence的create函数需要动作数组。代码第①行创建Place动作由于Sequence的create函数需要FiniteTimeAction类型的动作因此需要将表达式sprite->runAction(Place::create(p))强制转换为FiniteTimeAction*类型。类似的代码第②~⑤行都需要强制类型转换。第②行代码是创建MoveTo动作第③行代码是创建JumpBy动作。第④行代码是创建Blink动作。第⑤行代码是创建TintBy动作。
MyActionScene.ccp中MyActionLayer::OnSpawn这个函数是在演示并列动作时候调用的函数它的代码如下
void MyAction::OnSpawn(Ref* pSender) { Size size = Director::getInstance()->getVisibleSize(); Pointp = Point(size.width/2, 200); sprite->setRotation(0); ① sprite->setPosition(p); ② FiniteTimeAction* ac1 = (FiniteTimeAction*)sprite->runAction( MoveTo::create(2,Point(size.width- 100, size.height - 100))); ③ FiniteTimeAction* ac2 =(FiniteTimeAction*)sprite->runAction(RotateTo::create(2, 40)); ④ sprite->runAction(Spawn::create(ac1,ac2,NULL)); ⑤ }
上述代码实现了并列动作演示其中主要使用的类是Spawn类也从ActionInterval继承而来该类作用就是同时并列执行若干个动作但要求动作都必须 是可以同时执行的。比如:移动式翻转、改变色、改变大小等。第⑤行代码sprite->runAction(Spawn::create(ac1,ac2,NULL))执行并列动作create函数的动作类型数组。第①行代码sprite->setRotation(0)设置精灵旋转角度保持原来状态。第②行代码sprite->setPosition(p)是重新设置精灵位置。第③行代码创建MoveTo动作。第④行代码创建RotateTo动作。
MyActionScene.ccp中MyActionLayer::OnRepeat这个函数是在演示重复动作时候调用的函数它的代码如下
void MyAction::OnRepeat(Ref* pSender) { Size size = Director::getInstance()->getVisibleSize(); Pointp = Point(size.width/2, 200); sprite->setRotation(0); sprite->setPosition(p); FiniteTimeAction* ac1 = (FiniteTimeAction*)sprite->runAction( MoveTo::create(2,Point(size.width- 100, size.height - 100))); ① FiniteTimeAction* ac2 = (FiniteTimeAction*)sprite->runAction( JumpBy::create(2,Point(10,10), 20,5)); ② FiniteTimeAction* ac3 = (FiniteTimeAction*)sprite->runAction( JumpBy::create(2,Point(-10,-10),20,3)); ③ ActionInterval* seq = Sequence::create(ac1, ac2, ac3, NULL); ④ sprite->runAction(Repeat::create(seq,3)); ⑤ }
上述代码实现了重复动作演示其中主要使用的类是Repeat类也从ActionInterval继承而来。第①行代码是创建MoveTo动作。第②行代码是创建JumpBy动作。第③行代码是创建JumpBy动作。第④行代码是创建顺序动作对象seqseq的类型为ActionInterval*或FiniteTimeAction*。第⑤行代码sprite->runAction(Repeat::create(seq,3)) 重复运行顺序动作3次create函数参数的类型是FiniteTimeAction。
MyActionScene.ccp中MyActionLayer::OnRepeatForever这个函数是在演示无限重复动作时候调用的函数它的代码如下
void MyAction::OnRepeatForever(Ref*pSender) { Size size = Director::getInstance()->getVisibleSize(); Point p = Point(size.width/2, 500); sprite->setRotation(0); sprite->setPosition(p); ccBezierConfigbezier; ① bezier.controlPoint_1 = Point(0, size.height/2); bezier.controlPoint_2= Point(10, -size.height/2); bezier.endPosition= Point(10,20); ② FiniteTimeAction* ac1 =(FiniteTimeAction*)sprite->runAction(BezierBy::create(2,bezier)); ③ FiniteTimeAction* ac2 = (FiniteTimeAction*)sprite->runAction( TintBy::create(0.5,0, 255, 255)); ④ FiniteTimeAction* ac1Reverse = ((ActionInterval*)ac1)->reverse(); ⑤ FiniteTimeAction* ac2Repeat = (FiniteTimeAction*)sprite->runAction( Repeat::create((ActionInterval*)ac2,4)); ⑥ FiniteTimeAction* ac3 = (FiniteTimeAction*)sprite->runAction( Spawn::create(ac1,ac2Repeat,NULL)); ⑦ FiniteTimeAction* ac4 = (FiniteTimeAction*)sprite->runAction( Spawn::create(ac1Reverse,ac2Repeat,NULL)); ⑧ ActionInterval* seq = Sequence::create(ac3, ac4, NULL); ⑨ sprite->runAction(RepeatForever::create(seq)); ⑩ }
上述代码实现了重复动作演示其中主要使用的类是RepeatForever它也从ActionInterval继承而来。第⑩行代码sprite->runAction(RepeatForever::create(seq))是执行无限重复动作create函数参数的类型是FiniteTimeAction。代码第①~②行是定义贝塞尔曲线控制点。第③行代码创建贝塞尔曲线动作BezierBy。第④行代码创建动作TintBy。第⑤行代码是创建BezierBy动作的反转动作。第⑥行代码是创建重复动作。第⑦和⑧行代码是创建并列动作。第⑨行代码是创建顺序动作。
MyActionScene.ccp中MyActionLayer::OnReverse这个函数是在演示反动作时候调用的函数它的代码如下
void MyAction::OnReverse(Ref* pSender) { Size size = Director::getInstance()->getVisibleSize(); Pointp = Point(size.width/2, 300); sprite->setRotation(0); sprite->setPosition(p); FiniteTimeAction* ac1 = (FiniteTimeAction*)sprite->runAction( MoveBy::create(2,Point(40,60))); ① Action* ac2 = ac1->reverse(); ② ActionInterval* seq = Sequence::create(ac1, ac2, NULL); ③ sprite->runAction(Repeat::create(seq,2)); ④ }
上述代码实现了反动作演示支持顺序动作的反顺序动作反顺序动作不是一个类不是所有的动作类都支持反动作。XxxTo 类通常不支持反动作XxxBy类通常支持。第①行代码是创建一个移动MoveBy动作。第②行代码调用ac1的reverse()函数执行反动作。第③行代码是创建顺序动作。第④行代码sprite->runAction(Repeat::create(seq,2))是执行反动作。
更多内容请关注最新Cocos图书《Cocos2d-x实战 C++卷》
本书交流讨论网站http://www.cocoagame.net
更多精彩视频课程请关注智捷课堂Cocos课程http://v.51work6.com
欢迎加入Cocos2d-x技术讨论群257760386
《Cocos2d-x实战 C++卷》现已上线各大商店均已开售
京东http://item.jd.com/11584534.html
当当http://product.dangdang.com/23606265.html
互动出版网http://product.china-pub.com/3770734
《Cocos2d-x实战 C++卷》源码及样章下载地址
源码下载地址http://51work6.com/forum.php?mod=viewthread&tid=1155&extra=page%3D1
样章下载地址http://51work6.com/forum.php?mod=viewthread&tid=1157&extra=page%3D1
欢迎关注智捷iOS课堂微信公共平台