cocos2d-x实战 C++卷 学习笔记--第7章 动作特效
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了cocos2d-x实战 C++卷 学习笔记--第7章 动作特效相关的知识,希望对你有一定的参考价值。
前言:
介绍cocos2d-x中的动作、特效。
动作:
动作(action)包括基本动作和基本动作的组合,这些基本动作有缩放、移动、旋转等,而且这些动作变化的速度也可以设定。
动作类是 Action。它的类图如下:
Action有3个子类,FiniteTimeAction 是一种受时间限制的动作,Follow 是一种允许精灵跟随另一个精灵的动作,Speed是在一个动作运行时改变其运动速率。
瞬时动作:
瞬时动作就是不等待立即执行的动作,瞬时动作的基类是ActionInstant。瞬时动作 ActionInstant 类图如下:
代码示例:
1 #ifndef __HELLOWORLD_SCENE_H__ 2 #define __HELLOWORLD_SCENE_H__ 3 4 #include "cocos2d.h" 5 #include "Action.h" 6 7 typedef enum 8 { 9 PLACE_TAG = 102, 10 FLIPX_TAG, 11 FLIPY_TAG, 12 HIDE_SHOW_TAG, 13 TOGGLE_TAG, 14 OTHER_ACTION, 15 All_TAG_NUM 16 }ActionTypes; 17 18 class HelloWorld : public cocos2d::Layer 19 { 20 public: 21 // there‘s no ‘id‘ in cpp, so we recommend returning the class instance pointer 22 static cocos2d::Scene* createScene(); 23 24 // Here‘s a difference. Method ‘init‘ in cocos2d-x returns bool, instead of returning ‘id‘ in cocos2d-iphone 25 virtual bool init(); 26 27 // a selector callback 28 void menuCloseCallback(cocos2d::Ref* pSender); 29 30 void menuItemCallback_01(cocos2d::Ref* pSender); 31 void menuItemCallback_02(cocos2d::Ref* pSender); 32 void menuItemCallback_03(cocos2d::Ref* pSender); 33 void menuItemCallback_04(cocos2d::Ref* pSender); 34 void menuItemCallback_05(cocos2d::Ref* pSender); 35 void menuItemCallback_06(cocos2d::Ref* pSender); 36 37 38 // implement the "static create()" method manually 39 CREATE_FUNC(HelloWorld); 40 }; 41 42 #endif // __HELLOWORLD_SCENE_H__
1 #include "HelloWorldScene.h" 2 3 USING_NS_CC; 4 5 Scene* HelloWorld::createScene() 6 { 7 // ‘scene‘ is an autorelease object 8 auto scene = Scene::create(); 9 10 // ‘layer‘ is an autorelease object 11 auto layer = HelloWorld::create(); 12 13 // add layer as a child to scene 14 scene->addChild(layer); 15 16 // return the scene 17 return scene; 18 } 19 20 // on "init" you need to initialize your instance 21 bool HelloWorld::init() 22 { 23 ////////////////////////////// 24 // 1. super init first 25 if ( !Layer::init() ) 26 { 27 return false; 28 } 29 30 Size visibleSize = Director::getInstance()->getVisibleSize(); 31 Point origin = Director::getInstance()->getVisibleOrigin(); 32 33 ///////////////////////////// 34 // 2. add a menu item with "X" image, which is clicked to quit the program 35 // you may modify it. 36 37 // add a "close" icon to exit the progress. it‘s an autorelease object 38 auto closeItem = MenuItemImage::create( 39 "CloseNormal.png", 40 "CloseSelected.png", 41 CC_CALLBACK_1(HelloWorld::menuCloseCallback, this)); 42 43 closeItem->setPosition(Point(origin.x + visibleSize.width - closeItem->getContentSize().width/2 , 44 origin.y + closeItem->getContentSize().height/2)); 45 46 // create menu, it‘s an autorelease object 47 auto menu = Menu::create(closeItem, NULL); 48 menu->setPosition(Point::ZERO); 49 this->addChild(menu, 1); 50 51 ///////////////////////////// 52 // 3. add your codes below... 53 54 Sprite* spbkground = Sprite::create("Demo1/Background480x800.png"); 55 // position the sprite on the center of the screen 56 spbkground->setPosition(Point(visibleSize.width / 2 + origin.x, visibleSize.height / 2 + origin.y)); 57 // add the sprite as a child to this layer 58 this->addChild(spbkground, 0); 59 60 /////////////////////// 61 auto label_1 = Label::createWithBMFont("Demo1/fonts/fnt2.fnt", "01 label"); 62 auto label_2 = Label::createWithBMFont("Demo1/fonts/fnt2.fnt", "02 label"); 63 auto label_3 = Label::createWithBMFont("Demo1/fonts/fnt2.fnt", "03 label"); 64 auto label_4 = Label::createWithBMFont("Demo1/fonts/fnt2.fnt", "04 label"); 65 auto label_5 = Label::createWithBMFont("Demo1/fonts/fnt2.fnt", "05 label"); 66 auto label_6 = Label::createWithBMFont("Demo1/fonts/fnt2.fnt", "06 label"); 67 68 MenuItemLabel* muLab1 = MenuItemLabel::create(label_1, CC_CALLBACK_1(HelloWorld::menuItemCallback_01, this)); 69 MenuItemLabel* muLab2 = MenuItemLabel::create(label_2, CC_CALLBACK_1(HelloWorld::menuItemCallback_02, this)); 70 MenuItemLabel* muLab3 = MenuItemLabel::create(label_3, CC_CALLBACK_1(HelloWorld::menuItemCallback_03, this)); 71 MenuItemLabel* muLab4 = MenuItemLabel::create(label_4, CC_CALLBACK_1(HelloWorld::menuItemCallback_04, this)); 72 MenuItemLabel* muLab5 = MenuItemLabel::create(label_5, CC_CALLBACK_1(HelloWorld::menuItemCallback_05, this)); 73 MenuItemLabel* muLab6 = MenuItemLabel::create(label_6, CC_CALLBACK_1(HelloWorld::menuItemCallback_06, this)); 74 75 muLab1->setTag(PLACE_TAG); 76 muLab2->setTag(FLIPX_TAG); 77 muLab3->setTag(FLIPY_TAG); 78 muLab4->setTag(HIDE_SHOW_TAG); 79 muLab5->setTag(TOGGLE_TAG); 80 muLab6->setTag(OTHER_ACTION); 81 82 Menu* mu = Menu::create(muLab1, muLab2, muLab3, muLab4, muLab5, muLab6,NULL); 83 mu->alignItemsVertically(); 84 mu->setPosition(Point(origin.x + visibleSize.width / 2, origin.y + visibleSize.height/2)); 85 86 this->addChild(mu); 87 return true; 88 } 89 90 91 void HelloWorld::menuCloseCallback(Ref* pSender) 92 { 93 #if (CC_TARGET_PLATFORM == CC_PLATFORM_WP8) || (CC_TARGET_PLATFORM == CC_PLATFORM_WINRT) 94 MessageBox("You pressed the close button. Windows Store Apps do not implement a close button.","Alert"); 95 return; 96 #endif 97 98 Director::getInstance()->end(); 99 100 #if (CC_TARGET_PLATFORM == CC_PLATFORM_ios) 101 exit(0); 102 #endif 103 } 104 105 106 107 108 void HelloWorld::menuItemCallback_01(cocos2d::Ref* pSender) 109 { 110 MenuItem* muItem = (MenuItem*)pSender; 111 auto sc = Scene::create(); 112 auto SecondLayer = CActionTest::create(); 113 SecondLayer->setTag(muItem->getTag()); 114 sc->addChild(SecondLayer); 115 auto reScene = TransitionSlideInL::create(1.0f, sc); 116 Director::getInstance()->replaceScene(reScene); 117 118 log("function:%s, line:%d", __FUNCTION__, __LINE__); 119 } 120 121 void HelloWorld::menuItemCallback_02(cocos2d::Ref* pSender) 122 { 123 MenuItem* muItem = (MenuItem*)pSender; 124 auto sc = Scene::create(); 125 auto SecondLayer = CActionTest::create(); 126 SecondLayer->setTag(muItem->getTag()); 127 sc->addChild(SecondLayer); 128 auto reScene = TransitionSlideInR::create(1.0f, sc); 129 Director::getInstance()->replaceScene(reScene); 130 131 log("function:%s, line:%d", __FUNCTION__, __LINE__); 132 } 133 134 void HelloWorld::menuItemCallback_03(cocos2d::Ref* pSender) 135 { 136 MenuItem* muItem = (MenuItem*)pSender; 137 auto sc = Scene::create(); 138 auto SecondLayer = CActionTest::create(); 139 SecondLayer->setTag(muItem->getTag()); 140 sc->addChild(SecondLayer); 141 auto reScene = TransitionSlideInB::create(1.0f, sc); 142 Director::getInstance()->replaceScene(reScene); 143 144 log("function:%s, line:%d", __FUNCTION__, __LINE__); 145 } 146 147 void HelloWorld::menuItemCallback_04(cocos2d::Ref* pSender) 148 { 149 MenuItem* muItem = (MenuItem*)pSender; 150 auto sc = Scene::create(); 151 auto SecondLayer = CActionTest::create(); 152 SecondLayer->setTag(muItem->getTag()); 153 sc->addChild(SecondLayer); 154 auto reScene = TransitionSlideInT::create(1.0f, sc); 155 Director::getInstance()->replaceScene(reScene); 156 157 log("function:%s, line:%d", __FUNCTION__, __LINE__); 158 } 159 160 void HelloWorld::menuItemCallback_05(cocos2d::Ref* pSender) 161 { 162 MenuItem* muItem = (MenuItem*)pSender; 163 auto sc = Scene::create(); 164 auto SecondLayer = CActionTest::create(); 165 SecondLayer->setTag(muItem->getTag()); 166 sc->addChild(SecondLayer); 167 auto reScene = TransitionPageTurn::create(1.0f, sc, true); 168 Director::getInstance()->replaceScene(reScene); 169 170 log("function:%s, line:%d", __FUNCTION__, __LINE__); 171 } 172 173 void HelloWorld::menuItemCallback_06(cocos2d::Ref* pSender) 174 { 175 MenuItem* muItem = (MenuItem*)pSender; 176 auto sc = Scene::create(); 177 auto SecondLayer = CActionTest::create(); 178 SecondLayer->setTag(muItem->getTag()); 179 sc->addChild(SecondLayer); 180 auto reScene = TransitionPageTurn::create(1.0f, sc, true); 181 Director::getInstance()->replaceScene(reScene); 182 183 log("function:%s, line:%d", __FUNCTION__, __LINE__); 184 }
1 #ifndef __ACTION_SCENE_H__ 2 #define __ACTION_SCENE_H__ 3 #include "cocos2d.h" 4 #include "HelloWorldScene.h" 5 class CActionTest : public cocos2d::Layer 6 { 7 public: 8 CActionTest(); 9 ~CActionTest(); 10 11 static cocos2d::Scene* createScene(); 12 CREATE_FUNC(CActionTest); 13 14 /// 初始化层 调用 15 virtual bool init(); 16 /// 进入层时调用 17 virtual void onEnter(); 18 /// 进入层而且过渡动画结束时调用 19 virtual void onEnterTransitionDidFinish(); 20 /// 退出层时 调用 21 virtual void onExit(); 22 /// 退出层 而且开始过渡动画时调用 23 virtual void onExitTransitionDidStart(); 24 /// 层对象被清除时调用 25 virtual void cleanup(); 26 27 void menuItemCallback_back(cocos2d::Ref* pSender); 28 void menuItemCallback_Action(cocos2d::Ref* pSender); 29 30 protected: 31 cocos2d::Sprite* spPlane; // 飞机 精灵 32 bool bShow; // 隐藏标识 33 }; 34 35 #endif // __ACTION_SCENE_H__
1 #include "Action.h" 2 3 USING_NS_CC; 4 5 CActionTest::CActionTest() 6 { 7 spPlane = NULL; 8 bShow = TRUE; 9 10 log("function:%s, line:%d", __FUNCTION__, __LINE__); 11 } 12 13 CActionTest::~CActionTest() 14 { 15 16 log("function:%s, line:%d", __FUNCTION__, __LINE__); 17 } 18 19 Scene* CActionTest::createScene() 20 { 21 Scene* sc = Scene::create(); 22 auto myLayer = CActionTest::create(); 23 sc->addChild(myLayer); 24 25 return sc; 26 } 27 28 29 bool CActionTest::init() 30 { 31 if (!Layer::init()) 32 { 33 return false; 34 } 35 36 //// 层的初始化 37 Size sz = Director::getInstance()->getVisibleSize(); 38 Point origion = Director::getInstance()->getVisibleOrigin(); 39 40 Sprite* spBkground = Sprite::create("Demo1/Background480x800.png"); 41 spBkground->setPosition(Point(origion.x + sz.width / 2, origion.y + sz.height / 2)); 42 this->addChild(spBkground); 43 44 MenuItemImage* muBack = MenuItemImage::create("Demo1/Back-up.png", 45 "Demo1/Back-down.png", 46 CC_CALLBACK_1(CActionTest::menuItemCallback_back, this)); 47 muBack->setPosition(Point(origion.x+100, origion.y+sz.height-100)); 48 49 MenuItemImage* muGo = MenuItemImage::create("Demo1/Go-up.png", 50 "Demo1/Go-down.png", 51 CC_CALLBACK_1(CActionTest::menuItemCallback_Action, this)); 52 muGo->setPosition(Point(origion.x + 150, origion.y + 100)); 53 54 Menu* mu = Menu::create(muBack, muGo, NULL); 55 mu->setPosition(Point::ZERO); 56 this->addChild(mu); 57 58 spPlane = Sprite::create("Demo1/Plane.png"); 59 spPlane->setPosition(Point(origion.x + sz.width / 2, origion.y + sz.height / 2)); 60 this->addChild(spPlane, 1); 61 62 log("function:%s, line:%d", __FUNCTION__, __LINE__); 63 return true; 64 } 65 66 /// 进入层时调用 67 void CActionTest::onEnter() 68 { 69 Layer::onEnter(); 70 71 log("function:%s, line:%d", __FUNCTION__, __LINE__); 72 } 73 74 /// 进入层而且过渡动画结束时调用 75 void CActionTest::onEnterTransitionDidFinish() 76 { 77 Layer::onEnterTransitionDidFinish(); 78 79 log("function:%s, line:%d", __FUNCTION__, __LINE__); 80 } 81 82 /// 退出层时 调用 83 void CActionTest::onExit() 84 { 85 Layer::onExit(); 86 87 log("function:%s, line:%d", __FUNCTION__, __LINE__); 88 } 89 90 /// 退出层 而且开始过渡动画时调用 91 void CActionTest::onExitTransitionDidStart() 92 { 93 Layer::onExitTransitionDidStart(); 94 95 log("function:%s, line:%d", __FUNCTION__, __LINE__); 96 } 97 98 /// 层对象被清除时调用 99 void CActionTest::cleanup() 100 { 101 Layer::cleanup(); 102 103 log("function:%s, line:%d", __FUNCTION__, __LINE__); 104 } 105 106 void CActionTest::menuItemCallback_back(cocos2d::Ref* pSender) 107 { 108 auto sc = HelloWorld::createScene(); 109 auto reScene = TransitionShrinkGrow::create(1.0f, sc); 110 Director::getInstance()->replaceScene(reScene); 111 112 log("function:%s, line:%d", __FUNCTION__, __LINE__); 113 } 114 115 void CActionTest::menuItemCallback_Action(cocos2d::Ref* pSender) 116 { 117 log("function:%s, line:%d, Tag=%d", __FUNCTION__, __LINE__, this->getTag()); 118 119 Size sz = Director::getInstance()->getVisibleSize(); 120 Point pt = Point(CCRANDOM_0_1() * sz.width, CCRANDOM_0_1() * sz.height); 121 ccBezierConfig bezier; 122 123 switch (this->getTag()) 124 { 125 case PLACE_TAG: 126 spPlane->runAction(Place::create(pt)); 127 log("PLACE_TAG,Position. x=%f, y=%f", pt.x, pt.y); 128 break; 129 130 case FLIPX_TAG: 131 spPlane->runAction(FlipX::create(true)); 132 break; 133 134 case FLIPY_TAG: 135 spPlane->runAction(FlipY::create(true)); 136 break; 137 138 case HIDE_SHOW_TAG: 139 if (bShow) 140 { 141 spPlane->runAction(Hide::create()); 142 bShow = false; 143 } 144 else 145 { 146 spPlane->runAction(Show::create()); 147 bShow = true; 148 } 149 break; 150 151 case TOGGLE_TAG: 152 spPlane->runAction(ToggleVisibility::create()); 153 break; 154 155 case OTHER_ACTION: 156 // spPlane->runAction(MoveTo::create(3.0f, Point(0, 0))); 157 // spPlane->runAction(MoveBy::create(1.0f, Point(200, 200))); 158 // spPlane->runAction(JumpTo::create(3.0f, Point(100, 300),100, 10)); 159 // spPlane->runAction(JumpBy::create(3.0f, Point(100, 300), 400, 8)); 160 //bezier.controlPoint_1 = Point(100, sz.height); 161 //bezier.controlPoint_2 = Point(100, -sz.height / 2); 162 //bezier.endPosition = Point(300, 600); 163 //spPlane->runAction(BezierTo::create(3.0f, bezier)); 164 165 // spPlane->runAction(ScaleTo::create(2.0f, 1.3)); 166 // spPlane->runAction(ScaleBy::create(2.0f, 0.5)); 167 // spPlane->runAction(RotateTo::create(3.0f, 181)); ///旋转角度超过180度,旋转方向会变 168 // spPlane->runAction(RotateTo::create(3.0f, 81)); ///旋转角度超过180度,旋转方向会变 169 // spPlane->runAction(RotateBy::create(3.0f, -100)); 170 // spPlane->runAction(Blink::create(3.0f, 5)); // 闪烁 171 // spPlane->runAction(TintTo::create(2.0f, 255, 0, 0)); 172 // spPlane->runAction(TintBy::create(2.0f, 255, 0, 0)); /// 这个 渲染,好像 颜色不正确 173 // spPlane->runAction(FadeTo::create(2.0f, 90)); 174 //spPlane->setOpacity(50); 175 //spPlane->runAction(FadeIn::create(2.0f)); 176 spPlane->runAction(FadeOut::create(3.0f)); 177 break; 178 179 default: 180 break; 181 } 182 183 log("function:%s, line:%d", __FUNCTION__, __LINE__); 184 }
关键代码分析1:
1 auto sc = Scene::create(); /// 生成新场景 2 auto SecondLayer = CActionTest::create(); 3 SecondLayer->setTag(muItem->getTag()); 4 sc->addChild(SecondLayer); ///将 CActionTest 层添加到 新场景 5 auto reScene = TransitionSlideInR::create(1.0f, sc); /// 生成 过渡场景(过渡动画) 6 Director::getInstance()->replaceScene(reScene); /// 场景替换
此处没有调用CAction::createScene()直接创建场景和层,而是采用上面的方法。主要是为了给场景传递参数。
(当然,你重写一个 带参数的 createScene(int Tag) ,将参数传入,也是可行的)
关键代码分析2:
/// 执行一个Place动作,Place动作是将精灵等Node对象移动到pt点。
spPlane->runAction(Place::create(pt));
//// 执行一个 FlipX 动作,FlipX 动作是将精灵等Node对象 水平方向翻转
spPlane->runAction(FlipX::create(true));
关键代码分析3:
Point pt = Point(CCRANDOM_0_1() * sz.width, CCRANDOM_0_1() * sz.height);
CCRANDOM_0_1() 宏 可以产生 0~1 之间的随机数。
间隔动作:
间隔动作执行完成需要一定的时间,可以设置 duration 属性来设置动作的执行时间。间隔动作基类是 ActionInterval。间隔动作ActionInterval类图如下:
上面的源码示例中,有用到 间隔动作。
关键代码分析:
1 // spPlane->runAction(MoveTo::create(3.0f, Point(0, 0))); 2 // spPlane->runAction(MoveBy::create(1.0f, Point(200, 200))); 3 // spPlane->runAction(JumpTo::create(3.0f, Point(100, 300),100, 10)); 4 // spPlane->runAction(JumpBy::create(3.0f, Point(100, 300), 400, 8)); 5 //bezier.controlPoint_1 = Point(100, sz.height); 6 //bezier.controlPoint_2 = Point(100, -sz.height / 2); 7 //bezier.endPosition = Point(300, 600); 8 //spPlane->runAction(BezierTo::create(3.0f, bezier)); 9 10 // spPlane->runAction(ScaleTo::create(2.0f, 1.3)); 11 // spPlane->runAction(ScaleBy::create(2.0f, 0.5)); 12 // spPlane->runAction(RotateTo::create(3.0f, 181)); ///旋转角度超过180度,旋转方向会变 13 // spPlane->runAction(RotateTo::create(3.0f, 81)); ///旋转角度超过180度,旋转方向会变 14 // spPlane->runAction(RotateBy::create(3.0f, -100)); 15 // spPlane->runAction(Blink::create(3.0f, 5)); // 闪烁 16 // spPlane->runAction(TintTo::create(2.0f, 255, 0, 0)); 17 // spPlane->runAction(TintBy::create(2.0f, 255, 0, 0)); /// 这个 渲染,好像 颜色不正确 18 // spPlane->runAction(FadeTo::create(2.0f, 90)); 19 //spPlane->setOpacity(50); 20 //spPlane->runAction(FadeIn::create(2.0f)); 21 spPlane->runAction(FadeOut::create(3.0f));
间隔动作中很多类是 XxxTo 和 XxxBy 的命名。
XxxTo是指运动到指定的位置,这个位置是 绝对的。
XxxBy是指运动到相对于本身的位置,这个位置是相对的位置。
以上是关于cocos2d-x实战 C++卷 学习笔记--第7章 动作特效的主要内容,如果未能解决你的问题,请参考以下文章
cocos2d-x实战 C++卷 学习笔记--第4章 使用菜单