第一次去学习Action,总会找到一篇入门的帖子(官网:http://cn.cocos2d-x.org/article/index?type=cocos2d-x&url=/doc/cocos-docs-master/manual/framework/native/v3/action/zh.md)。也会初步了解Action是怎么用的?

  *创建动作对象,eg:移动、旋转等

  *调用Node的runAction函数,这个动作就表现出来了

  auto actionTo = MoveTo::create(, Vec2(s.width-, s.height-));
auto actionBy = MoveBy::create(, Vec2(,));
auto actionByBack = actionBy->reverse(); _tamara->runAction( actionTo);
_grossini->runAction( Sequence::create(actionBy, actionByBack, nullptr));
_kathia->runAction(MoveTo::create(, Vec2(,)));

  So Easy!但是,但是,看完之后你会有一溜的问题!

(1)类结构中即时动作和持续动作在原理上有什么不同?

(2)FiniteTimeAction、Follow和Speed这两个是干嘛的?尤其是后面两个。

(3)Action工作的一个原理是什么?

  然而,还有一个一开始容易被忽视的问题,但是你去看了之后才发现有很多技术或者知识细节需要去弄明白,再加一个问题:

(4)不管是即时动作(ActionInstant)还是ActionInterval(持续动作)里面包含了许多动作类,他们表现上的差异在原理上有什么不同?如何实现的?

*友情提示*上面的问题记得看一篇入门文章,后面的内容并不一定按照上面问题的顺序和分节去讲,只是按照自己学习的思路记录一下,增强自己的记忆和梳理一些遗漏的知识点,如果能帮助一些和我一样的菜鸟朋友,权当无心插柳!^_^

----------------------------------------------------------------------------------------------------------------------------------------------------------

--下面进入高能阶段--

----------------------------------------------------------------------------------------------------------------------------------------------------------

一、Action的原理

  看cocos提供的例子,很容易理解一些基本的动作,比如move、rotate、jump等,但是当你看源码的时候,你是想知道,这个整体的逻辑是怎么设计和实现的,先上Action的流程图,如下所示:

  

1.流程图解析

(1)没有方框的名字是类名,eg:Director, Scheduler,ActionManager,Action,Timer等

(2)没有方框但是带有‘*’开头的是旁白,为了帮助自己记忆和更容易看明白

(3)有颜色的的都是自己觉得比较重要的关键点,当然其他细节也需要弄明白,一些表示状态的标记等

* 两条蓝色的箭头是Scheduler(看调度器时候重要)调用update函数的地方,所以不管是动作的ActionManager还是定时器的Timer,主要逻辑都还是在update中完成的

* 紫色的step函数是Action的逻辑主要完成地方,但是由于Action是基类。最后各个动作都是继承的Action,但是没有重载step函数,所以基类Action中的step是调用了update函数的,因此你可以看到多数动作的逻辑是自己重载update函数完成的,而为什么要有step呢?那是因为有些类是需要重载step的,他不需要update,可以看Follow和Speed的源码。

void Follow::step(float dt)
{
CC_UNUSED_PARAM(dt); if(_boundarySet)
{
// whole map fits inside a single screen, no need to modify the position - unless map boundaries are increased
if(_boundaryFullyCovered)
return; Vec2 tempPos = _halfScreenSize - _followedNode->getPosition(); _target->setPosition(Vec2(clampf(tempPos.x, _leftBoundary, _rightBoundary),
clampf(tempPos.y, _bottomBoundary, _topBoundary)));
}
else
{
_target->setPosition(_halfScreenSize - _followedNode->getPosition());
}
}

  当然,也可以这么理解:由于连续性动作需要时间上有个计时器的概念,所以他需要每隔一段时间update,而其他类不需要,只要把逻辑写在step里面就可以了,所以需要一个step和update的层次概念,这样是不是很好理解了呢?(clever!^_^)

* 各个真正使用的动作类(如Move、Jump等)都是重载了update函数的,那么update干嘛了呢?只有update函数这里有差异,所以update是区分各个动作的关键所在!来看一个简单的动作代码(MoveBy):

void MoveBy::update(float t)
{
if (_target)
{
#if CC_ENABLE_STACKABLE_ACTIONS
Vec2 currentPos = _target->getPosition();
Vec2 diff = currentPos - _previousPosition;
_startPosition = _startPosition + diff;
Vec2 newPos = _startPosition + (_positionDelta * t);
_target->setPosition(newPos);
_previousPosition = newPos;
#else
_target->setPosition(_startPosition + _positionDelta * t);
#endif // CC_ENABLE_STACKABLE_ACTIONS
}
}

  稍微看一下就明白了,他只做了一件事情,就是设置节点(_target是node对象,例如一个精灵Sprite)的位置。有点乱~,往前看,这里看下连续性动作ActionInternal的代码,再联系上这里的update

void ActionInterval::step(float dt)
{
if (_firstTick)
{
_firstTick = false;
_elapsed = ;
}
else
{
_elapsed += dt;
} this->update(MAX (, // needed for rewind. elapsed could be negative
MIN(, _elapsed /
MAX(_duration, FLT_EPSILON) // division by 0
)
)
);
}

  看到了没?每一帧都会调用update函数,而update函数的参数是一个比例值_elapsed/MAX(_duration, FLT_EPSILOW)。去掉一些MIN、MAX等宏(防止除数为0等的情况),很容易看明白这个比例表示了当前时间点在整个持续动作过程的某个位置(注:这里的update参数和scheduler中的update参数意义不一样,step的参数和scheduler中的update参数是一个意义)!

  那么一个宏观的逻辑就算是比较清晰了,那么发散思维一下:如果是Jump呢?他的update做了什么呢?同样的也是setPosition,只不过不近要处理水平坐标,还要处理纵坐标;Scale呢?就是直接设置Node(eg:精灵Sprite)的scale,(eg:setScaleX,setScaleY)...

(4)Timer中红色方框边缘的节点表示的是关键函数,这里面执行的就是定时器传进来的函数参数。

(5)深绿色方框边缘的判断语句“时间到”只是表示他们都是一样的:_elapsed >= _interval,看源代码也很好理解。命名很赞!

2. cocos文件

  cocos中的文件很好找,在工程里面libcocos2d/2d目录下面一开始就可以看到一槽排的CCActionXXX.h和CCActionXXX.cpp文件,具体自己去看吧。(个人版本:cocos2dx-3.2)

3. 问题

4. 总结

(1)整体理解一下,Action是一系列不同的对象,绑定Node。ActionManager维护一个hash表,并且每帧处理!

(2)跳出来看,每一个Action就是让Node做某件事情,也就是设定Node的某项属性。如果是即时动作,这立马执行。如果是持续性动作,就是每帧去处理节点的属性,因为牵涉到时间概念,所以有一个简单的计算过程(比例值的计算)。

---先到这里---后面继续记录>>>

----------------------------------------------------------------------------------------------------------------------------------------------------------

二、各种动作详细解读

【源码分析】cocos2dx的Action的更多相关文章

  1. cocos2dx骨骼动画Armature源码分析(一)

    源码分析一body { font-family: Helvetica, arial, sans-serif; font-size: 14px; line-height: 1.6; padding-to ...

  2. Struts2 源码分析——DefaultActionInvocation类的执行action

    本章简言 上一章讲到关于拦截器的机制的知识点,让我们对拦截器有了一定的认识.我们也清楚的知道在执行用户action类实例之前,struts2会先去执行当前action类对应的拦截器.而关于在哪里执行a ...

  3. Struts2 源码分析——Action代理类的工作

    章节简言 上一章笔者讲到关于如何加载配置文件里面的package元素节点信息.相信读者到这里心里面对struts2在启动的时候加载相关的信息有了一定的了解和认识.而本章将讲到关于struts2启动成功 ...

  4. Struts2 源码分析——调结者(Dispatcher)之执行action

    章节简言 上一章笔者写关于Dispatcher类如何处理接受来的request请求.当然读者们也知道他并非正真的执行action操作.他只是在执行action操作之前的准备工作.那么谁才是正真的执行a ...

  5. 【Cocos2d-x 3.x】 事件处理机制源码分析

    在游戏中,触摸是最基本的,必不可少的.Cocos2d-x 3.x中定义了一系列事件,同时也定义了负责监听这些事件的监听器,另外,cocos定义了事件分发类,用来将事件派发出去以便可以实现相应的事件. ...

  6. Cocos2dx源码赏析(4)之Action动作

    Cocos2dx源码赏析(4)之Action动作 本篇,依然是通过阅读源码的方式来简单赏析下Cocos2dx中Action动画的执行过程.当然,这里也只是通过这种方式来总结下对Cocos2dx引擎的理 ...

  7. [转帖]cocos2D-X源码分析之从cocos2D-X学习OpenGL(3)----BATCH_COMMAND

    原贴: cocos2D-X源码分析之从cocos2D-X学习OpenGL(3)----BATCH_COMMAND 上一篇介绍了QUAD_COMMAND渲染命令,顺带介绍了VAO和VBO,这一篇介绍批处 ...

  8. [转帖]cocos2D-X源码分析之从cocos2D-X学习OpenGL(2)----QUAD_COMMAND

    原文:cocos2D-X源码分析之从cocos2D-X学习OpenGL(2)----QUAD_COMMAND 上一篇文章介绍了cocos2d-x的基本渲染结构,这篇顺着之前的渲染结构介绍渲染命令QUA ...

  9. 5 cocos2dx 3.0源码分析 渲染 render

    渲染,感觉这个挺重要了,这里代入一个简单的例子 Sprite 建立及到最后的画在屏幕上, 我们描述一下这个渲染的流程:   1 sprite 初始化(纹理, 坐标,及当前元素的坐标大小信息) 2 主循 ...

  10. 3 cocos2dx 3.0 源码分析-mainLoop详细

    简述:   我靠上面图是不是太大了, 有点看不清了.  总结一下过程: 之前说过的appController 之后经过了若干初始化, 最后调用了displayLinker 的定时调用, 这里调用了函数 ...

随机推荐

  1. apache2 + django 路径问题

    问题: 在代码中使用sys.path.append(), 添加模块路径后,仍然报错找不到包. 虽然在LD_LIBRARY_PATH中配置了.so文件打路径,仍然报错找不到. 原因: 检查apahce2 ...

  2. PyCharm+cmd中使用Anaconda 与 新建Python环境(Windows)

    PyCharm配置Anaconda Anaconda的安装在网上已经有了,这里主要讲之前已经安装了已经配置好Python环境变量以及PyCharm的情况下,使用Anaconda. 即在PyCharm中 ...

  3. Robot Framework_Ride(Edit标签)

    前言 RIDE 作为 Robot Framework 的“脸面”,虽然我们已经可以拿它来创建和运行测试了,但我们对它的认识并不全面,这一小节我们将了解这个工具的使用 Edit标签 下面我们来看一看测试 ...

  4. Cloudera Manager安装之时间服务器和时间客户端(Ubuntu14.04)(二)

    第二步: Cloudera Manager安装之时间服务器和时间客户端(二) 找一台机器作为时间服务器 我这里,放到ubuntucmbigdata1这台机器! 注意,之前是已经做了集群时间同步了. 在 ...

  5. 使用YUM安装MySQL 5.5(适用于CentOS6.2/5.8及Fedora 17/16平台)

    目前CentOS/Red Hat (RHEL) 6.2官方自带的mysql版本为5.1,mysql5.5已经出来了. 相比mysql5.1,mysql5.5不仅在多个方面进行了改进: 性能上有了很大提 ...

  6. 【idea快捷键】

    IntelliJ Idea 常用快捷键列表 idea也是可以切换到eclipse风格的快捷键方式的  在keymap中切换即可 Ctrl+Shift + Enter,语句完成 “!”,否定完成,输入表 ...

  7. [转]微信小程序填坑之路之使用localhost在本地测试

    本文转自:http://www.wxappclub.com/topic/798

  8. 微信小程序wx:for循环

    最近做微信小程序碰到了一些问题,和wx:for循环相关,wx:for有很多用途,例如可以用于swiper中图片的循环,也就是所谓的轮播图,也可以用于其它的循环,可以大大地减少代码量. 但wx:for. ...

  9. 001.開始使用ASP.NET Web API 2(一)

    原文鏈接:http://www.asp.net/web-api/overview/getting-started-with-aspnet-web-api/tutorial-your-first-web ...

  10. JS的Object类的属性、方法及如何创建对象

    属性 constructor:对创建对象的函数的引用(指针).对于Object类,该指针指向原始的object()函数. prototype:对该对象的对象原型的引用.对于所有的类,它默认返回Obje ...