cocos2d-x实战 C++卷 学习笔记--第7章 动作、特效(一)
前言:
介绍cocos2d-x中的动作、特效。
动作:
动作(action)包括基本动作和基本动作的组合,这些基本动作有缩放、移动、旋转等,而且这些动作变化的速度也可以设定。
动作类是 Action。它的类图如下:
Action有3个子类,FiniteTimeAction 是一种受时间限制的动作,Follow 是一种允许精灵跟随另一个精灵的动作,Speed是在一个动作运行时改变其运动速率。
瞬时动作:
瞬时动作就是不等待立即执行的动作,瞬时动作的基类是ActionInstant。瞬时动作 ActionInstant 类图如下:
代码示例:
#ifndef __HELLOWORLD_SCENE_H__ #define __HELLOWORLD_SCENE_H__ #include "cocos2d.h" #include "Action.h" typedef enum { PLACE_TAG = , FLIPX_TAG, FLIPY_TAG, HIDE_SHOW_TAG, TOGGLE_TAG, OTHER_ACTION, All_TAG_NUM }ActionTypes; class HelloWorld : public cocos2d::Layer { public: // there's no 'id' in cpp, so we recommend returning the class instance pointer static cocos2d::Scene* createScene(); // Here's a difference. Method 'init' in cocos2d-x returns bool, instead of returning 'id' in cocos2d-iphone virtual bool init(); // a selector callback void menuCloseCallback(cocos2d::Ref* pSender); void menuItemCallback_01(cocos2d::Ref* pSender); void menuItemCallback_02(cocos2d::Ref* pSender); void menuItemCallback_03(cocos2d::Ref* pSender); void menuItemCallback_04(cocos2d::Ref* pSender); void menuItemCallback_05(cocos2d::Ref* pSender); void menuItemCallback_06(cocos2d::Ref* pSender); // implement the "static create()" method manually CREATE_FUNC(HelloWorld); }; #endif // __HELLOWORLD_SCENE_H__
HelloWorldScene.h
#include "HelloWorldScene.h" USING_NS_CC; Scene* HelloWorld::createScene() { // 'scene' is an autorelease object auto scene = Scene::create(); // 'layer' is an autorelease object auto layer = HelloWorld::create(); // add layer as a child to scene scene->addChild(layer); // return the scene return scene; } // on "init" you need to initialize your instance bool HelloWorld::init() { ////////////////////////////// // 1. super init first if ( !Layer::init() ) { return false; } Size visibleSize = Director::getInstance()->getVisibleSize(); Point origin = Director::getInstance()->getVisibleOrigin(); ///////////////////////////// // 2. add a menu item with "X" image, which is clicked to quit the program // you may modify it. // add a "close" icon to exit the progress. it's an autorelease object auto closeItem = MenuItemImage::create( "CloseNormal.png", "CloseSelected.png", CC_CALLBACK_1(HelloWorld::menuCloseCallback, this)); closeItem->setPosition(Point(origin.x + visibleSize.width - closeItem->getContentSize().width/ , origin.y + closeItem->getContentSize().height/)); // create menu, it's an autorelease object auto menu = Menu::create(closeItem, NULL); menu->setPosition(Point::ZERO); ); ///////////////////////////// // 3. add your codes below... Sprite* spbkground = Sprite::create("Demo1/Background480x800.png"); // position the sprite on the center of the screen spbkground->setPosition(Point(visibleSize.width / + origin.x, visibleSize.height / + origin.y)); // add the sprite as a child to this layer ); /////////////////////// auto label_1 = Label::createWithBMFont("Demo1/fonts/fnt2.fnt", "01 label"); auto label_2 = Label::createWithBMFont("Demo1/fonts/fnt2.fnt", "02 label"); auto label_3 = Label::createWithBMFont("Demo1/fonts/fnt2.fnt", "03 label"); auto label_4 = Label::createWithBMFont("Demo1/fonts/fnt2.fnt", "04 label"); auto label_5 = Label::createWithBMFont("Demo1/fonts/fnt2.fnt", "05 label"); auto label_6 = Label::createWithBMFont("Demo1/fonts/fnt2.fnt", "06 label"); MenuItemLabel* muLab1 = MenuItemLabel::create(label_1, CC_CALLBACK_1(HelloWorld::menuItemCallback_01, this)); MenuItemLabel* muLab2 = MenuItemLabel::create(label_2, CC_CALLBACK_1(HelloWorld::menuItemCallback_02, this)); MenuItemLabel* muLab3 = MenuItemLabel::create(label_3, CC_CALLBACK_1(HelloWorld::menuItemCallback_03, this)); MenuItemLabel* muLab4 = MenuItemLabel::create(label_4, CC_CALLBACK_1(HelloWorld::menuItemCallback_04, this)); MenuItemLabel* muLab5 = MenuItemLabel::create(label_5, CC_CALLBACK_1(HelloWorld::menuItemCallback_05, this)); MenuItemLabel* muLab6 = MenuItemLabel::create(label_6, CC_CALLBACK_1(HelloWorld::menuItemCallback_06, this)); muLab1->setTag(PLACE_TAG); muLab2->setTag(FLIPX_TAG); muLab3->setTag(FLIPY_TAG); muLab4->setTag(HIDE_SHOW_TAG); muLab5->setTag(TOGGLE_TAG); muLab6->setTag(OTHER_ACTION); Menu* mu = Menu::create(muLab1, muLab2, muLab3, muLab4, muLab5, muLab6,NULL); mu->alignItemsVertically(); mu->setPosition(Point(origin.x + visibleSize.width / , origin.y + visibleSize.height/)); this->addChild(mu); return true; } void HelloWorld::menuCloseCallback(Ref* pSender) { #if (CC_TARGET_PLATFORM == CC_PLATFORM_WP8) || (CC_TARGET_PLATFORM == CC_PLATFORM_WINRT) MessageBox("You pressed the close button. Windows Store Apps do not implement a close button.","Alert"); return; #endif Director::getInstance()->end(); #if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS) exit(); #endif } void HelloWorld::menuItemCallback_01(cocos2d::Ref* pSender) { MenuItem* muItem = (MenuItem*)pSender; auto sc = Scene::create(); auto SecondLayer = CActionTest::create(); SecondLayer->setTag(muItem->getTag()); sc->addChild(SecondLayer); auto reScene = TransitionSlideInL::create(1.0f, sc); Director::getInstance()->replaceScene(reScene); log("function:%s, line:%d", __FUNCTION__, __LINE__); } void HelloWorld::menuItemCallback_02(cocos2d::Ref* pSender) { MenuItem* muItem = (MenuItem*)pSender; auto sc = Scene::create(); auto SecondLayer = CActionTest::create(); SecondLayer->setTag(muItem->getTag()); sc->addChild(SecondLayer); auto reScene = TransitionSlideInR::create(1.0f, sc); Director::getInstance()->replaceScene(reScene); log("function:%s, line:%d", __FUNCTION__, __LINE__); } void HelloWorld::menuItemCallback_03(cocos2d::Ref* pSender) { MenuItem* muItem = (MenuItem*)pSender; auto sc = Scene::create(); auto SecondLayer = CActionTest::create(); SecondLayer->setTag(muItem->getTag()); sc->addChild(SecondLayer); auto reScene = TransitionSlideInB::create(1.0f, sc); Director::getInstance()->replaceScene(reScene); log("function:%s, line:%d", __FUNCTION__, __LINE__); } void HelloWorld::menuItemCallback_04(cocos2d::Ref* pSender) { MenuItem* muItem = (MenuItem*)pSender; auto sc = Scene::create(); auto SecondLayer = CActionTest::create(); SecondLayer->setTag(muItem->getTag()); sc->addChild(SecondLayer); auto reScene = TransitionSlideInT::create(1.0f, sc); Director::getInstance()->replaceScene(reScene); log("function:%s, line:%d", __FUNCTION__, __LINE__); } void HelloWorld::menuItemCallback_05(cocos2d::Ref* pSender) { MenuItem* muItem = (MenuItem*)pSender; auto sc = Scene::create(); auto SecondLayer = CActionTest::create(); SecondLayer->setTag(muItem->getTag()); sc->addChild(SecondLayer); auto reScene = TransitionPageTurn::create(1.0f, sc, true); Director::getInstance()->replaceScene(reScene); log("function:%s, line:%d", __FUNCTION__, __LINE__); } void HelloWorld::menuItemCallback_06(cocos2d::Ref* pSender) { MenuItem* muItem = (MenuItem*)pSender; auto sc = Scene::create(); auto SecondLayer = CActionTest::create(); SecondLayer->setTag(muItem->getTag()); sc->addChild(SecondLayer); auto reScene = TransitionPageTurn::create(1.0f, sc, true); Director::getInstance()->replaceScene(reScene); log("function:%s, line:%d", __FUNCTION__, __LINE__); }
HelloWorldScene.cpp
#ifndef __ACTION_SCENE_H__ #define __ACTION_SCENE_H__ #include "cocos2d.h" #include "HelloWorldScene.h" class CActionTest : public cocos2d::Layer { public: CActionTest(); ~CActionTest(); static cocos2d::Scene* createScene(); CREATE_FUNC(CActionTest); /// 初始化层 调用 virtual bool init(); /// 进入层时调用 virtual void onEnter(); /// 进入层而且过渡动画结束时调用 virtual void onEnterTransitionDidFinish(); /// 退出层时 调用 virtual void onExit(); /// 退出层 而且开始过渡动画时调用 virtual void onExitTransitionDidStart(); /// 层对象被清除时调用 virtual void cleanup(); void menuItemCallback_back(cocos2d::Ref* pSender); void menuItemCallback_Action(cocos2d::Ref* pSender); protected: cocos2d::Sprite* spPlane; // 飞机 精灵 bool bShow; // 隐藏标识 }; #endif // __ACTION_SCENE_H__
Action.h
#include "Action.h" USING_NS_CC; CActionTest::CActionTest() { spPlane = NULL; bShow = TRUE; log("function:%s, line:%d", __FUNCTION__, __LINE__); } CActionTest::~CActionTest() { log("function:%s, line:%d", __FUNCTION__, __LINE__); } Scene* CActionTest::createScene() { Scene* sc = Scene::create(); auto myLayer = CActionTest::create(); sc->addChild(myLayer); return sc; } bool CActionTest::init() { if (!Layer::init()) { return false; } //// 层的初始化 Size sz = Director::getInstance()->getVisibleSize(); Point origion = Director::getInstance()->getVisibleOrigin(); Sprite* spBkground = Sprite::create("Demo1/Background480x800.png"); spBkground->setPosition(Point(origion.x + sz.width / , origion.y + sz.height / )); this->addChild(spBkground); MenuItemImage* muBack = MenuItemImage::create("Demo1/Back-up.png", "Demo1/Back-down.png", CC_CALLBACK_1(CActionTest::menuItemCallback_back, this)); muBack->setPosition(Point(origion.x+, origion.y+sz.height-)); MenuItemImage* muGo = MenuItemImage::create("Demo1/Go-up.png", "Demo1/Go-down.png", CC_CALLBACK_1(CActionTest::menuItemCallback_Action, this)); muGo->setPosition(Point(origion.x + , origion.y + )); Menu* mu = Menu::create(muBack, muGo, NULL); mu->setPosition(Point::ZERO); this->addChild(mu); spPlane = Sprite::create("Demo1/Plane.png"); spPlane->setPosition(Point(origion.x + sz.width / , origion.y + sz.height / )); ); log("function:%s, line:%d", __FUNCTION__, __LINE__); return true; } /// 进入层时调用 void CActionTest::onEnter() { Layer::onEnter(); log("function:%s, line:%d", __FUNCTION__, __LINE__); } /// 进入层而且过渡动画结束时调用 void CActionTest::onEnterTransitionDidFinish() { Layer::onEnterTransitionDidFinish(); log("function:%s, line:%d", __FUNCTION__, __LINE__); } /// 退出层时 调用 void CActionTest::onExit() { Layer::onExit(); log("function:%s, line:%d", __FUNCTION__, __LINE__); } /// 退出层 而且开始过渡动画时调用 void CActionTest::onExitTransitionDidStart() { Layer::onExitTransitionDidStart(); log("function:%s, line:%d", __FUNCTION__, __LINE__); } /// 层对象被清除时调用 void CActionTest::cleanup() { Layer::cleanup(); log("function:%s, line:%d", __FUNCTION__, __LINE__); } void CActionTest::menuItemCallback_back(cocos2d::Ref* pSender) { auto sc = HelloWorld::createScene(); auto reScene = TransitionShrinkGrow::create(1.0f, sc); Director::getInstance()->replaceScene(reScene); log("function:%s, line:%d", __FUNCTION__, __LINE__); } void CActionTest::menuItemCallback_Action(cocos2d::Ref* pSender) { log("function:%s, line:%d, Tag=%d", __FUNCTION__, __LINE__, this->getTag()); Size sz = Director::getInstance()->getVisibleSize(); Point pt = Point(CCRANDOM_0_1() * sz.width, CCRANDOM_0_1() * sz.height); ccBezierConfig bezier; switch (this->getTag()) { case PLACE_TAG: spPlane->runAction(Place::create(pt)); log("PLACE_TAG,Position. x=%f, y=%f", pt.x, pt.y); break; case FLIPX_TAG: spPlane->runAction(FlipX::create(true)); break; case FLIPY_TAG: spPlane->runAction(FlipY::create(true)); break; case HIDE_SHOW_TAG: if (bShow) { spPlane->runAction(Hide::create()); bShow = false; } else { spPlane->runAction(Show::create()); bShow = true; } break; case TOGGLE_TAG: spPlane->runAction(ToggleVisibility::create()); break; case OTHER_ACTION: // spPlane->runAction(MoveTo::create(3.0f, Point(0, 0))); // spPlane->runAction(MoveBy::create(1.0f, Point(200, 200))); // spPlane->runAction(JumpTo::create(3.0f, Point(100, 300),100, 10)); // spPlane->runAction(JumpBy::create(3.0f, Point(100, 300), 400, 8)); //bezier.controlPoint_1 = Point(100, sz.height); //bezier.controlPoint_2 = Point(100, -sz.height / 2); //bezier.endPosition = Point(300, 600); //spPlane->runAction(BezierTo::create(3.0f, bezier)); // spPlane->runAction(ScaleTo::create(2.0f, 1.3)); // spPlane->runAction(ScaleBy::create(2.0f, 0.5)); // spPlane->runAction(RotateTo::create(3.0f, 181)); ///旋转角度超过180度,旋转方向会变 // spPlane->runAction(RotateTo::create(3.0f, 81)); ///旋转角度超过180度,旋转方向会变 // spPlane->runAction(RotateBy::create(3.0f, -100)); // spPlane->runAction(Blink::create(3.0f, 5)); // 闪烁 // spPlane->runAction(TintTo::create(2.0f, 255, 0, 0)); // spPlane->runAction(TintBy::create(2.0f, 255, 0, 0)); /// 这个 渲染,好像 颜色不正确 // spPlane->runAction(FadeTo::create(2.0f, 90)); //spPlane->setOpacity(50); //spPlane->runAction(FadeIn::create(2.0f)); spPlane->runAction(FadeOut::create(3.0f)); break; default: break; } log("function:%s, line:%d", __FUNCTION__, __LINE__); }
Action.cpp
关键代码分析1:
auto sc = Scene::create(); /// 生成新场景 auto SecondLayer = CActionTest::create(); SecondLayer->setTag(muItem->getTag()); sc->addChild(SecondLayer); ///将 CActionTest 层添加到 新场景 auto reScene = TransitionSlideInR::create(1.0f, sc); /// 生成 过渡场景(过渡动画) 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类图如下:
上面的源码示例中,有用到 间隔动作。
关键代码分析:
// spPlane->runAction(MoveTo::create(3.0f, Point(0, 0))); // spPlane->runAction(MoveBy::create(1.0f, Point(200, 200))); // spPlane->runAction(JumpTo::create(3.0f, Point(100, 300),100, 10)); // spPlane->runAction(JumpBy::create(3.0f, Point(100, 300), 400, 8)); //bezier.controlPoint_1 = Point(100, sz.height); //bezier.controlPoint_2 = Point(100, -sz.height / 2); //bezier.endPosition = Point(300, 600); //spPlane->runAction(BezierTo::create(3.0f, bezier)); // spPlane->runAction(ScaleTo::create(2.0f, 1.3)); // spPlane->runAction(ScaleBy::create(2.0f, 0.5)); // spPlane->runAction(RotateTo::create(3.0f, 181)); ///旋转角度超过180度,旋转方向会变 // spPlane->runAction(RotateTo::create(3.0f, 81)); ///旋转角度超过180度,旋转方向会变 // spPlane->runAction(RotateBy::create(3.0f, -100)); // spPlane->runAction(Blink::create(3.0f, 5)); // 闪烁 // spPlane->runAction(TintTo::create(2.0f, 255, 0, 0)); // spPlane->runAction(TintBy::create(2.0f, 255, 0, 0)); /// 这个 渲染,好像 颜色不正确 // spPlane->runAction(FadeTo::create(2.0f, 90)); //spPlane->setOpacity(50); //spPlane->runAction(FadeIn::create(2.0f)); spPlane->runAction(FadeOut::create(3.0f));
间隔动作中很多类是 XxxTo 和 XxxBy 的命名。
XxxTo是指运动到指定的位置,这个位置是 绝对的。
XxxBy是指运动到相对于本身的位置,这个位置是相对的位置。
cocos2d-x实战 C++卷 学习笔记--第7章 动作、特效(一)的更多相关文章
- cocos2d-x实战 C++卷 学习笔记--第4章 字符串 __String类
前言: <cocos2d-x实战C++卷>学习笔记.(cocos2d-x 是3.0版本) 介绍 cocos2d-x 通用的字符串类 __String . 使用cocos2d::__Str ...
- cocos2d-x实战 C++卷 学习笔记--第6章 场景与层
前言: 一个场景(Scene)是由多个层(Layer)组成,而且层的个数要至少是1,不能为0. 场景切换 场景切换相关函数 1)void runWithScene(Scene* scene) 该函 ...
- cocos2d-x实战 C++卷 学习笔记--第4章 使用菜单
前言: 菜单中包含菜单项,菜单项类是 MenuItem ,每个菜单项都有三个基本状态:正常.选中和禁止. (MenuItem)菜单分类: (文本菜单)MenuItemLabel : MenuItemA ...
- cocos2d-x实战 C++卷 学习笔记--第4章 win32平台下中文乱码问题
前言: 将GBK编码的字符串转为UTF-8编码.(通俗点说就是解决中文乱码问题) 简要介绍: 在Win32平台下通过 log 输出中文字符时,会出现中文乱码问题.同样的代码在 ios 和 Androi ...
- cocos2d-x实战 C++卷 学习笔记--第5章 精灵
前言: 精灵类是Sprite类.它的子类有PhysicsSprite 和 Skin. PhysicsSprite 是物理引擎精灵类,而Skin是皮肤精灵类,用于骨骼动画. 创建Sprite精灵对象 创 ...
- cocos2d-x实战 C++卷 学习笔记--第4章 使用标签
前言: 介绍cocos2d-x中 标签类. cocos2d-x中 标签类 主要有三种:LabelTTF, LabelAtlas, 和 LabelBMFont.此外,在Cocos2d-x 3.x之后推出 ...
- Docker技术入门与实战 第二版-学习笔记-10-Docker Machine 项目-2-driver
1>使用的driver 1〉generic 使用带有SSH的现有VM/主机创建机器. 如果你使用的是机器不直接支持的provider,或者希望导入现有主机以允许Docker Machine进行管 ...
- Docker技术入门与实战 第二版-学习笔记-8-网络功能network-3-容器访问控制和自定义网桥
1)容器访问控制 容器的访问控制,主要通过 Linux 上的 iptables防火墙来进行管理和实现. iptables是 Linux 上默认的防火墙软件,在大部分发行版中都自带. 容器访问外部网络 ...
- Spring实战第八章学习笔记————使用Spring Web Flow
Spring实战第八章学习笔记----使用Spring Web Flow Spring Web Flow是一个Web框架,它适用于元素按规定流程运行的程序. 其实我们可以使用任何WEB框架写流程化的应 ...
随机推荐
- hdoj 2151 Worm【动态规划】
Worm Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submis ...
- 如何获得网页上的swf视频教程文件?
网上有很多免费的视频教程,但有的视频教程这能在线观看,无法离线下在,如何获得网页上的swf视频教程文件呢? 我问以"我要自学网"的视频教程为例进行讲解.这是一个我要自学网的PS视频 ...
- linux教程:[4]配置Tomcat开机启动
http://jingyan.baidu.com/article/6525d4b1382f0aac7d2e9421.html 方法/步骤 1 请自行下载安装配置tomcat的服务器环境 本经验仅仅介绍 ...
- 安装好Windows 8后必做的几件事情,让你的Win8跑的更快更流畅。
1.关闭家庭组,因为这功能会导致硬盘和CPU处于高负荷状态. 关闭方法:Win+C-设置-更改电脑设置-家庭组-离开 如果用不到家庭组可以直接把家庭组服务也给关闭了:控制面板-管理工具-服务-Home ...
- There is no Action mapped for namespace [/pages/action/student] and action name [findStudent]
1.错误描写叙述 2014-7-13 2:38:54 org.apache.jasper.compiler.TldLocationsCache tldScanJar 信息: At least one ...
- SVN安装笔记
1.先去以下网址去下载服务器端与客户端的SVN 2.服务端SVN的安装 点击next 点击next 再点击next 点击next 点击install 点击Finish,这样服务器端的SVN就安装好了, ...
- iOS开发——屏幕适配篇&Masonry详解
Masonry详解 前言 MagicNumber -> autoresizingMask -> autolayout 以上是纯手写代码所经历的关于页面布局的三个时期 在iphone1-ip ...
- JavaScript网站设计实践(五)编写photos.html页面,实现点击缩略图显示大图的效果
一.photos.html页面,点击每一张缩略图,就在占位符的位置那里,显示对应的大图. 看到的页面效果是这样的: 1.实现思路 这个功能在之前的JavaScript美术馆那里已经实现了. 首先在页面 ...
- JavaScript网站设计实践(三)设计有特色的主页,给主页链接添加JavaScript动画脚本
一.主页一般都会比较有特色,现在在网站设计(二)实现的基础上,来给主页添加一点动画效果. 1.这里实现的动画效果是:当鼠标悬停在其中某个超链接时,会显示出属于该页面的背景缩略图,让用户知道这个链接的页 ...
- 生产者/消费者问题的多种Java实现方式--转
实质上,很多后台服务程序并发控制的基本原理都可以归纳为生产者/消费者模式,而这是恰恰是在本科操作系统课堂上老师反复讲解,而我们却视而不见不以为然的.在博文<一种面向作业流(工作流)的轻量级可复用 ...