相比之前的速度正弦变化动作(这个东西叫什么更好一些?渐变动画?)与速度指数级变化动作,CCEaseIn/CCEaseOut/CCEaseInOut更具灵活性。你可以设置运动的速率,甚至是在运动的过程中改变速率。它们拥有共同的基类——CCEaseRateAction。不要直接使用CCEaseRateAction,因为它没有实现任何变化效果。

7)CCEaseIn

按照惯例贴出update函数的源代码,以免版本更新导致文不对题。

1 void CCEaseIn::update(ccTime time)
2 {
3 m_pOther->update(powf(time, m_fRate));
4 }

根据此函数的实现推导出以下三个公式:

s(t)=t^r t∈[0,1]
v(t)=s'(t)=r*t^(r-1) t∈[0,1]
a(t)=v'(t)=r*(r-1)*t^(r-2) t∈[0,1]

s:路程 v:速度 a:加速度 t:时间 r:速率参数m_fRate
都是很基本的导函数推导,如果有不清楚的地方,建议先复习下导数。

下面我们着重分析下速率参数,也就是r的取值范围。因为是讨论二元函数,图像是三维的,画出后重叠在一起反而不利于理解,这里就没有作图。

1.r<0

当r<0时,v(t)将始终保持为负数,也就是说速度的方向与设定的方向正好相反。
又因为s(1)=1,这说明精灵最后移动到了目标点坐标,但它是从预设轨迹的延长线上反向移动到这一坐标点的。
这是一个很奇怪的动作行为,跟我们预想的设计不符,所以r的取值不应小于零。

2.r=0

当r=0时,s(t)恒等于1,也就说动作在开始之前就已经达到了完成的状态。我们这里说的是动作的表现,动作原本的执行时间是不受此影响的。
很明显,这与我们的设计不符,所以零也不是r的一个取值。

3.0<r<1

当r的取值范围在(0,1)时,a(t)恒为负数,加速度为负说明速度是越来越慢的,这与CCEaseXxxxIn动作应该由慢至快的设定不符,所以这也不是r应有的取值范围。

4.r=1

当r=1时,a(t)恒等于零,v(t)恒等于一,这说明此时的动作是速度为1的匀速运动。这貌似与设定的有慢至快也不相符。

5.1<r<2

当r的取值范围在(1,2)时,加速度a(t)恒大于零,但呈下降趋势。

6.r=2

当r=2是,a(t)恒等于2,也就是此时为匀加速运动。

7.r>2

当r>2时,加速度a(t)恒大于零,且呈上升趋势。

综上所述,当你使用CCEaseIn时,传入的速率参数应大于1.0f,并且根据取值范围的不同,会呈现出3种不太一样的加速运动。

8)CCEaseOut

我们再来看一下CCEaseOut的update函数。

1 void CCEaseOut::update(ccTime time)
2 {
3 m_pOther->update(powf(time, 1 / m_fRate));
4 }

第一步还是需要推导出路程、速度、加速度的公式:

s(t)=t^(1/r) t∈[0,1]
v(t)=s'(t)=1/r*(t^(1/r-1)) t∈[0,1]
a(t)=v'(t)=1/r*(1/r-1)*(t^(1/r-2)) t∈[0,1]

第二步分析r的取值范围:

1.r<0

当r<0时,CCEaseOut的情况与CCEaseIn一样,运动不在预设轨迹上,排除。

2.r=0

除数不能为零,排除。

3.0<r<1

当r的取值范围在(0,1)时,a(t)恒大于零,这说明速度是越来越快的,这与CCEaseXxxxOut由快至慢的设定不符,排除。

4.r=1

当r=1时,a(t)恒等于零,这说明是匀速运动,不符合设定,排除。

5.r>1

当r>1时,加速度a(t)恒小于零,但呈上升趋势。

综上所述,当你使用CCEaseOut时,传入的速率参数应大于1.0f,与CCEaseIn不同的是,CCEaseOut只有一类加速度变化趋势。

在继续后面的研究之前,我们来做一些额外的思考。CCEaseOut中r的取值为什么与CCEaseIn的有些不一样呢?是不是它的设计存在什么不合理的地方?

假设我们将r设定为3,同时画出CCEaseIn和CCEaseOut的图像:

颜色有点儿乱,不过没办法,里面包含3套对比数据,我直接说颜色,希望大家别迷糊。

那条红色曲线是CCEaseIn的v(t)函数,那条分数的是CCEaseOut的v(t)函数。
大家都知道CCEaseXxxxIn与CCEaseXxxxOut动作的区别是,前者由慢到快,后者由快到慢。如果说得更精确些,它们的表现应该是对称的——速度函数v(t)按照x=0.5直线轴对称。
但是显而易见的,红色曲线和粉色曲线根本不对称。

如果大家再仔细想想之前正弦变化和指数级变化的图像,这里还存在一处对称。那就是,路程函数s(t)的图像应该是按照点A(0.5,0.5)中心对称的。
那条蓝色曲线是CCEaseIn的s(t)函数,那条兰色的是CCEaseOut的s(t)函数。
可以很明显地看出,它们是按照y=x直线轴对称的,而不是按照点A中心对称。

我们将红色曲线按照x=0.5直线做轴对称镜像,得到那条黑色的抛物线。再对此抛物线求其反导函数图像,得到那条黑色曲线。瞧,它与那条蓝色曲线是不是按照点A中心对称的。
所以,我认为CCEaseOut的update函数应该修改一下。如果你有不同的见解,欢迎在评论区留言。

附上我修改后的代码:

1 void CCEaseOut::update(ccTime time)
2 {
3 m_pOther->update(1.0f - powf((1.0f - time), m_fRate));
4 }

如果按我这样修改,那么速率参数的取值范围与CCEaseIn中是一样的,大于一。

9)CCEaseInOut

好了,继续我们的研究:

 1 void CCEaseInOut::update(ccTime time)
2 {
3 int sign = 1;
4 int r = (int) m_fRate;
5
6 if (r % 2 == 0)
7 {
8 sign = -1;
9 }
10
11 time *= 2;
12 if (time < 1)
13 {
14 m_pOther->update(0.5f * powf(time, m_fRate));
15 }
16 else
17 {
18 m_pOther->update(sign * 0.5f * (powf(time - 2, m_fRate) + sign * 2));
19 }
20 }

必须指出,这个函数的实现是有问题的。

第一,难道引擎的设计者只希望我们传入整数型的速率吗?
问题出在powf函数调用上。
我们知道传入的time参数范围在[0,1],即便中间做了一次乘2的操作,到了后面time-2依然是小于等于零的。所以在某些情况下,powf会出现问题。
比如,当m_fRate设置为3.5f之类的小数时,这里的powf会返回"-1.#IND000"。
于是,当动作执行到后半段时,精灵会消失,直到动作全部完成,精灵才会出现在终点上。

第二,那个sign正负标志是用来解决问题的吗?怎么感觉引入后反而将问题复杂化了。
这里其实只需将前半段的函数按照点(0.5,0.5)做一次中点对称就可以了,用不着这么麻烦。
我修改的代码如下:

 1 void CCEaseInOut::update(ccTime time)
2 {
3 time *= 2;
4 if (time < 1)
5 {
6 m_pOther->update(0.5f * powf(time, m_fRate));
7 }
8 else
9 {
10 m_pOther->update(0.5f * (2.0f - powf((2.0f - time), m_fRate)));
11 }
12 }

因为CCEaseInOut与CCEaseIn使用相同的算法,所以在这里速率参数的取值范围与CCEaseIn的一样,也是大于一。

小结

到目前为止,我们对CCActionEase的学习已经完成了一半。

我们一共学习了3类,9个动作。它们分别是CCEaseSineIn、CCEaseSineOut、CCEaseSineInOut、CCEaseExponentialIn、CCEaseExponentialOut、CCEaseExponentialInOut、CCEaseIn、CCEaseOut、CCEaseInOut。

它们与之后将要学习的动作的最大区别是,在这些动作的执行过程中,精灵会严格地按照内部动作指定的路径移动,绝对不会超出起始点与终点的范围。

在CCEaseIn/CCEaseOut/CCEaseInOut中,速度的变化范围是[0,m_fRate],m_fRate>1。

但是,如果cocos2d-x需要与cocos2d-iphone从原则上保持高度一致,即便是存在缺陷也不能破坏原则的话,那么我推测官方在短时间内是不会修改这个问题的。因为,在大约6个月之前,有朋友提出过此问题,但似乎被无视了。
http://www.cocos2d-iphone.org/forum/topic/20979
http://code.google.com/p/cocos2d-iphone/issues/detail?id=1248

所以,在官方正式修正此问题之前,我建议大家只使用大于1的整数作为速率的参数,以提高兼容性。

关于Cococs中的CCActionEase(中)的更多相关文章

  1. 记录一次bug解决过程:velocity中获取url中的参数

    一.总结 在Webx的Velocity中获取url中参数:$rundata.getRequest().getParameter('userId') 在Webx项目中,防止CSRF攻击(Cross-si ...

  2. 地图四叉树一般用在GIS中,在游戏寻路中2D游戏中一般用2维数组就够了

    地图四叉树一般用在GIS中,在游戏寻路中2D游戏中一般用2维数组就够了 四叉树对于区域查询,效率比较高. 原理图

  3. android/java 根据当前时间判断股票交易状态(未开盘 交易中 休市中 已收盘)

    /** * @param data yyyy-MM-dd HH:mm:ss 时间 * @return 未开盘 交易中 休市中 已收盘 */ public static String getSotckS ...

  4. Objective-C中把数组中字典中的数据转换成URL

    可能上面的标题有些拗口,学过PHP的小伙伴们都知道,PHP中的数组的下标是允许我们自定义的,PHP中的数组确切的说就是键值对.而在OC我们要用字典(Dictionary)来存储,当然了Java用的是M ...

  5. SSAS中事实表中的数据如果因为一对多或多对多关系复制了多份,在维度上聚合的时候还是只算一份

    SSAS事实表中的数据,有时候会因为一对多或多对多关系发生复制变成多份,如下图所示: 图1 我们可以从上面图片中看到,在这个例子中,有三个事实表Fact_People_Money(此表用字段Money ...

  6. 修改tnsnames.ora文件中配置内容中的连接别名后,连接超时解决办法

    1.tnsnames.ora文件中配置内容中的连接别名:由upaydb修改为IP地址 2.连接超时 定位原因: PLSQL登录界面的数据库列表就是读的tnsname.ora中连接的别名,这个文件中连接 ...

  7. 在SQL SERVER中获取表中的第二条数据

    在SQL SERVER中获取表中的第二条数据, 思路:先根据时间逆排序取出前2条数据作为一个临时表,再按顺时排序在临时表中取出第一条数据 sql语句如下: select top 1 * from(se ...

  8. Java中实现PHP中的urlencode与rawurlencode

    php手册中对urlencode这样说明 在java中 URLEncoder做了这样注释 也就是说java中对星号"*"是不进行编码的 也就是说URLEncoder之后还是&quo ...

  9. 在app中打开appStore中其他app

    var str = "https://itunes.apple.com/cn/app/zhang-jiange-hao-tou-zi-ke/id402382976?mt=8"//这 ...

  10. 【AspNetCore】【WebApi】扩展Webapi中的RouteConstraint中,让DateTime类型,支持时间格式化(DateTimeFormat)

    扩展Webapi中的RouteConstraint中,让DateTime类型,支持时间格式化(DateTimeFormat) 一.背景 大家在使用WebApi时,会用到DateTime为参数,类似于这 ...

随机推荐

  1. SDUT2087 离散事件模拟-银行管理(模拟)

    题目链接. 分析: 模拟. 果然模拟什么的最讨厌了. 用e1,e2分别记录队列1,队列2的结束时间. 每个结点的s记录开始时间,e一开是记录逗留时间,进队列的时候,改成离开的时间.时刻记录总时间就可以 ...

  2. C#中两个时间的比较

    var DateTimedt1 = Convert.ToDateTime(dt);     var DateTimedt2 = Convert.ToDateTime(DateTime.Now);    ...

  3. Java---多线程之死锁

    ★ 死锁的两种情况: 简单的说下单块cpu运行多线程的情况: 大家可能平时玩电脑,可以同时挂QQ啊,玩游戏啊,打开文本啊,等等.这里,我们假设是单块cpu.也就是俗称的单核cpu. 大家可能会觉得这些 ...

  4. HDOJ 1020 Encoding

    Problem Description Given a string containing only 'A' - 'Z', we could encode it using the following ...

  5. UVA196-Spreadsheet(拓扑排序)

    Spreadsheet In 1979, Dan Bricklin and Bob Frankston wrote VisiCalc, the first spreadsheet applicatio ...

  6. 中国四大资产管理公司 ACM

    一,来历和主要业务 国家于1999年成立了四家直属国务院的资产管理公司:中国东方资产管理公司.中国信达资产管理公司.中国华融资产管理公司.中国长城资产管理公司.由于资产公司一般是是为适应体制转轨或防范 ...

  7. php中的后期静态绑定("Late Static Binding")

    在我们以往中,在类中使用self关键字的时候都是指向了被调用方法定义时的类,而非原始的调用类. 例如: class Animal{ static $IQ_lv_avg = 1; public stat ...

  8. javascript对链接进行动态处理化

    // $(function(){// var aLink=$('.nav-content .nav li a'); // 选中所有a// var aText=['在线搭配','星网学院','推客联盟' ...

  9. HDU 5266 pog loves szh III (线段树+在线LCA转RMQ)

    题目地址:HDU 5266 这题用转RMQ求LCA的方法来做的很easy,仅仅须要找到l-r区间内的dfs序最大的和最小的就能够.那么用线段树或者RMQ维护一下区间最值就能够了.然后就是找dfs序最大 ...

  10. Linux安装应用程序对程序文件owner/group和执行程序帐号设置的规范做法

    本文原文链接:http://blog.csdn.net/bluishglc/article/details/24384189 转载请注明出外! 本文面向的是在server环境下对已编译.自解压应用程序 ...