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框架写流程化的应 ...
随机推荐
- [iOS基础控件 - 1] UI概念
A. UIView 1.概念 属于UIKit框架 屏幕上能看得见摸得着的东西就是UIView,比如屏幕上的按钮.文字.图片 翻译为:视图/控件/组件 UIBut ...
- iOS中几种定时器 - 控制了时间,就控制了一切
在软件开发过程中,我们常常需要在某个时间后执行某个方法,或者是按照某个周期一直执行某个方法.在这个时候,我们就需要用到定时器. 然而,在iOS中有很多方法完成以上的任务,到底有多少种方法呢?经过查阅资 ...
- CMD-NET命令详解(转载)
本文转自http://www.cnblogs.com/chenjq0717/archive/2010/05/09/1730934.html net命令大全,net命令用法,net网络命令,net命令使 ...
- SVG 矢量图形格式
SVG(Scalable Vector Graphics)是基于 XML 的一种矢量图形格式,它即可以作为单独的图形文件使用也可以嵌入到网页中并由 JavaScript 来操作,非常方便和灵活.SVG ...
- ExtJs5.1.1使用中问题集锦
1.获取grid filter对象: grid.getStore().getFilters().items 2.获取grid filter后把filter对象转换成json格式字符串:grid.ge ...
- 未定义标识符_ConnectionPtr
我的编译环境 vs2010 你会明白的图片,那么多 无用!
- android---APN切换
android手机客户端在上传文件时,有时候会一直失败,其可能的原因是APN的设置.wap下的成功率极低,所以在进行文件上传时最好设置下 apn为net形式.下面是我在网上找的一些代码,是由wap转n ...
- Spring – ${} is not working in @Value--转载
原文:http://www.mkyong.com/spring/spring-is-not-working-in-value/ By mkyong | February 4, 2015 | Last ...
- 分享原创可复用且非侵入性代码生成工具(for .net)
入行IT十年了,这是本人第一次网上’献丑‘.迫于工作压力,花了大半年时间写了这个生成器以辅助开发.如有价值请多多给予建议,谢谢 好了,废话少说,开动! QA. 1.为什么要用代码生成器? 当然是为了快 ...
- 【转】使用BBB的device tree和cape(重新整理版)
只要你想用BBB做哪怕一丁点涉及到硬件的东西,你就不可避免地要用到cape和device tree的知识.所以尽管它们看起来很陌生而且有点复杂,但还是得学.其实用起来不难的.下面我只讲使用时必须会的内 ...