19、Cocos2dx 3.0游戏开发找小三之Action:流动的水没有形状,漂
发布时间:2020-12-14 21:22:09 所属栏目:百科 来源:网络整理
导读:重开发者的劳动成果,转载的时候请务必注明出处 :http://www.jb51.cc/article/p-wotesauw-xv.html 流动的水没有形状,漂流的风找不到踪迹、、、 直睡的陵迁谷变,石烂松枯,斗转星移, 整个宇宙在不停的运动着、、、 前面详细介绍了游戏的基本组成元素--场
重开发者的劳动成果,转载的时候请务必注明出处:http://www.52php.cn/article/p-wotesauw-xv.html
流动的水没有形状,漂流的风找不到踪迹、、、
直睡的陵迁谷变,石烂松枯,斗转星移,整个宇宙在不停的运动着、、、
前面详细介绍了游戏的基本组成元素--场景、 层、 精灵和渲染树等, 也详细介绍了 Node 提供的定时器。
为了让整个世界运动起来,让每一个精灵运动,可以利用定时器,不断修改节点的属性,实现简单的动态效果。
然而,这种方法会导致为了实现简单的动态效果,十分烦 琐地维护一批定时器。
Cocos2d-x 为了解决这个问题,引入了动作机制。
Action是动作类的基类
所有的动作都派生自这个类,它创建的一个对象代表了一个动作。
动作作用于Node,因此, 任何一个动作都需要由 Node 对象来执行。
以下代码实现了一个精灵用 10秒钟的时间移动到了点(100,100):
需要注意的是,一个 Action 只能使用一次,
这是因为动作对象不仅描述了动作,还保存了这个动作持续过程中不断改变
的一些中间参数。
对于需要反复使用的动作对象,可以通过 copy 方法复制使用。
Action 作为一个基类,其实质是一个接口(即抽象类),
由它派生的实现类(如运动和转动等)才是我们实际使用的动
作。
Action 的绝大多数实现类都派生自 FiniteTimeAction,这个类定义了在有限时间内可以完成的动作。
FiniteTimeAction定义了 reverse 方法,通过这个方法可以获得一个与原动作相反的动作(称作逆动作),例如隐藏一
个精灵后,用逆转动作再显示出来。
当然,并非所有的动作都有对应的逆动作,
例如类似"放大到"等设置属性为常量的动
作不存在逆动作,而设置属性为相对值的动作则往往存在相应的逆动作。
由 FiniteTimeAction 派生出的两个主要类分别是瞬时动作(ActionInstant)和持续性动作(ActionInterval),
这两类动作与复合动作配合使用,能得到复杂生动的动作效果。
瞬时动作
瞬时动作是指能立刻完成的动作,是 FiniteTimeAction 中动作持续时间为 0 的特例。
更准确地说,这类动作是在下一帧会立刻执行并完成的动作,如设定位置、设定缩放等。
这些动作原本可以通过简单地对 Node 赋值完成,但是把它们包装
为动作后,可以方便地与其他动作类组合为复杂动作。
一些常用的瞬时动作:
Place
该动作用于将节点放置到某个指定位置,其作用与修改节点的 Position 属性相同。
例如,将精灵放置到屏幕坐标(100,100)处,再执行曲线运动 curveMove 的代码如下:
其中 Sequence 又称为动作序列,是一种复合动作,它在初始化时,会接受多个动作,当它被执行时,这些动作会按顺序
逐个执行,形成有序的一列动作。
FlipX 和 和 FlipY
这两个动作分别用于将精灵沿 X 和 Y 轴反向显示,其作用与设置精灵的 FlipX 和 FlipY 属性相同。
将其包装为动作类也是
为了便于与其他动作进行组合。
例如,我们想使精灵从屏幕的一端游动到另一端,然后按原路返回。
为了更自然一点
,
我们设置一个序列,精灵先执行移动的动作,在精灵到达另一端时反向显示,然后再执行移动回起点的动
作,相关代码如下:
其中,duration 参数表示动作持续的时间,position参数表示移动的终点或距离。
对于 MoveTo,节点会被移动到对应的位置;
对于 MoveBy,节点会相对之前的位置移动的距离。
JumpTo 和 JumpBy:使节点以一定的轨迹跳跃到指定位置。它们的初始化方法如下:
其中表示跳跃的终点或距离,height 表示最大高度,jumps 表示跳跃次数。
BezierTo 和 BezierBy: 使节点进行曲线运动, 运动的轨迹由贝塞尔曲线描述。
贝塞尔曲线是描述任意曲线的有力工具,
在许多软件(如 Adobe Photoshop)中,钢笔工具就是贝塞尔曲线的应用。
每一条贝塞尔曲线都包含一个起点和一个终点。
在一条曲线中,起点和终点都各自包含一个控制点,而控制点到端点的连
线称作控制线。
控制线决定了从端点发出的曲线的形状,包含角度和长度两个参数:角度决定了它所控制的曲线的方向,
即这段曲线在这一控制点的切线方向;长度控制曲线的曲率。控制线越长,它所控制的曲线离控制线越近。
使用时我们要先创建 ccBezierConfig 结构体, 设置好终点 endPosition 以及两个控制点controlPoint_1 和controlPoint_2
后,再把结构体传入 BezierTo 或 BezierBy 的初始化方法中:
属性变化动作
属性变化动作的特点是通过属性值的逐渐变化来实现动画效果。
例如, 下面要介绍的第一个动作 ScaleTo,它会在一段时间内不断地改变游戏元素的 scale 属性,
使属性值平滑地变化到一个新值,从而使游戏元素产生缩放的动画效果。
ScaleTo 和 ScaleBy:产生缩放效果,使节点的缩放系数随时间线性变化。对应的初始化方法为:
其中,s 为缩放系数的最终值或变化量。
RotateTo 和 RotateBy:产生旋转效果。对应的初始化方法为:
deltaAngle的单位是角度,正方向为顺时针方向。
FadeIn 和 FadeOut:产生淡入淡出效果,其中前者实现了淡入效果,后者实现了淡出效果。对应的初始化方法为:
以下介绍的几个类似的动作。
FadeTo:用于设置一段时间内透明度的变化效果。其初始化方法为:
与透明度相关的动作只能应用在精灵
(Sprite)上,且子节点不会受到父节点的影响。
TintTo 和 TintBy:设置色调变化。这个动作较为少用,其初始化方法为:
视觉特效动作
用于实现一些特殊的视觉效果
Blink:使目标节点闪烁。其初始化方法为:
其中,blinks是闪烁次数。
Animation:播放帧动画,用帧动画的形式实现动画效果。
控制动作
控制动作是一类特殊的动作,用于对一些列动作进行精细控制。
利用这一类动作可以实现一些实用的功能,因此它们是十
分常用的。
这类动作包括 DelayTime、 Repeat 和RepeatForever 等。
DelayTime可以将动作延时一定的时间,
Repeat
可以把现有的动作重复一定次数,
RepeateForever
可以使一个动作不断重复下去。
事实上,控制动作与复合动作息息相关。
复合动作
简单动作显然不足以满足游戏开发的要求, 在这些动作的基础上,
Cocos2d-x 为我们提供了一套动作的复合机制,
允许我们组合各种基本动作,产生更为复杂和生动的动作效果。
复合动作是一类特殊的动作,因此它也需要使用 Node 的
runAction 方法执行。
而它的特殊之处在于,作为动作容器,复合动作可以把许多动作组合成一个复杂的动作。
因此,我们
通常会使用一个或多个动作来创建复合动作,再把动作交给节点执行。
复合动作十分灵活,这是由于复合动作本身也是动作,因此也可以作为一个普通的动作嵌套在其他复合动作中。
重复( Repeat/RepeatForever )
有的情况下,动作只需要执行一次即可,但我们还常常遇到一个动作反复执行的情况。
对于一些重复的动作,
我们可以通过 Repeat 与 RepeatForever 这两个方式重复执行:
action参数表示需要重复的动作,第一个方法允许指定动作的重复次数,第二个方法使节点一直重复该动
作直到动作被停止。
并列( Spawn )
指的是使一批动作同时执行。Spawn 从 ActionInterval 派生而来的,它提供了两个工厂方法:
其中第一个静态方法可以将多个动作同时并列执行,参数表中最后一个动作后需要紧跟 NULL 表示结束。第二个则只能指定
两个动作复合, 不需要在最后一个动作后紧跟 NULL。
此外, 执行的动作必须是能够同时执行的、 继承自 FiniteTimeAction
的动作。
组合后,Spawn 动作的最终完成时间由其成员中最大执行时间的动作来决定。
序列( Sequence )
除了让动作同时并列执行,我们更常遇到的情况是顺序执行一系列动作。
Sequence 提供了一个动作队列,它会顺序执行
一系列动作。
Sequence 同样派生自 ActionInterval。
与 Spawn 一样,Squence 也提供了两个工厂方法:
它们的作用分别是建立多个和两个动作的顺序执行的动作序列。
同样要注意复合动作的使用条件,部分的非延时动作(如
RepeatForever)并不被支持。
在实现 Sequence 和 Spawn 两个组合动作类时,有一个非常有趣的细节:
成员变量中并没有定义一个可变长的容器来容
纳每一个动作系列, 而是定义了m_pOne和m_pTwo两个动作成员变量。 如果我们创建了两个动作的组合,
那么m_pOne与m_pTwo
就分别是这两个动作本身;
当我们创建更多动作的组合时,引擎会把动作分解为两部分来看待,
其中后一部分只包含最后
一个动作,而前一部分包含它之前的所有动作,
引擎把 m_pTwo 设置为后一部分的动作,把 m_pOne 设置为其余所有动作的
组合。
例如,
语句
就等价于:
Spawn 与 Sequence 所采用的机制类似,在此就不再赘述了。
采用这种递归的方式,而不是直接使用容器来定义组合动
作,实际上为编程带来了极大的便利。
维护多个动作的组合是一个复杂的问题,现在我们只需要考虑两个动作组合的情况
就可以了。
下面是 Spawn 的一个初始化方法,就是利用
递归的思想
简化了编程的复杂度:
众所周知,递归往往会牺牲一些效率,但能换来代码的简洁。
在这两个复合动作中,细节处理得十分优雅,
所有的操作都
只需要针对两个动作实施,多个动作的组合会被自动变换为递归
延时( DelayTime )
DelayTime 是一个"什么都不做"的动作,类似于音乐中的休止符,
用来表示动作序列里一段空白期,通过占位的方式将不
同的动作段串接在一起。
实际上,这与一个定时期实现的延迟没有区别,
但相比之下,使用 DelayTime 动作来延时就可
以方便地利用动作序列把一套动作连接在一起。
DelayTime 只提供了一个工程方法,如下所示:
其中仅包含一个实型参数d,表示动作占用的时间。
变速动作
大部分动作的变化过程是与时间成线性关系的,即一个动作经过相同时间产生的变化相同,
例如,MoveBy 会使节点在同
样长的时间内经过同样的位移。
这是因为 Cocos2d-x 把动作的速度变化控制抽离了出来,形成一个独立的机制。
普通动作配合
变速动作,可以构造出很有趣的动作效果。
与复合动作类似,变速动作也是一种特殊的动作,它可以把任何一种动作按照改变后的速度执行。
因此,在初始化变速动
作时,需要传入一个动作。
变速动作包括 Speed 动作与 Ease 系列动作,下面来详细介绍这些动作。
Speed
Speed 用于线性地改变某个动作的速度,因此,可以实现成倍地快放或慢放功能。
为了改变一个动作的速度,首先需要将
目标动作包装到 Speed 动作中:
在上面的代码中, 我们创建了一个 animation 动作的 CCRepeatForever 复合动作 repeat, 使动画被不断地重复执行。 然后,
我们又使用 repeat 动作创建了一个 CCSpeed 变速动作。
create 初始化方法中的两个参数分别为目标动作与变速比率。
设置
变速比率为 1,目标动作的速度将不会改变。
最后,我们为 speed 动作设置了一个 tag 属性,并把动作交给精灵,让
精灵执行变速动作。
此处设置的 tag 属性与 Node 的 tag 属性类似,用于从节点中方便地查找动作。
接下来,在需要改变速度的地方,我们通过修改变速动作的 speed 属性来改变动作速度。
下面的代码将会把上面设置的动
画速度变为原来的两倍:
ActionEase
虽然使用 Speed 能够改变动作的速度,然而它只能按比例改变目标动作的速度。
如果我们要实现动作由快到慢、速度随
时间改变的变速运动,
需要不停地修改它的speed属性才能实现, 显然这是一个很烦琐的方法。
下面将要介绍的ActionEase系列动作通过使用内置的多种自动速度变化来解决这一问题。
ActionEase 系列包含 15 个动作,
它们可以被概括为 5 类动作:指数缓冲、Sine 缓冲、弹性缓冲、跳跃缓冲和回震缓冲。
每一类动作都有 3 个不同时期的变换:In、Out 和 InOut。
下面使用时间变换图像表示每组 ActionEase 动作的作用效果,
其中横坐标表示实际动画时间,纵坐标表示变换后的动画时间。
因此,线性动作的图像应该是一条自左下角到右上角的直
线。
ActionEase 的使用方法与 Speed 类似。以 Sine 缓冲为例,以下代码实现了 InSine 变速运动:
创建自定义动作
为了抽象出独立的旋转跟踪动作,根据精灵的移动路径设置合适的旋转角度。
Action 包含两个重要的方法:step 与 update。
step 方法会在每一帧动作更新时触发,该方法接受一个表示调用时间间
隔的参数 dt,dt 的积累即为动作运行的总时间。
引擎利用积累时间来计算动作运行的进度(一个从 0 到 1 的实数),并调
用 update 方法更新动作。
update 方法是 Action 的核心,它由 step 方法调用,接受一个表示动作进度的参数,
每一个动
作都需要利用进度值改变目标节点的属性或执行其他指令。
自定义动作只需要从这两个方法入手即可,我们通常只需要修
改 update 方法就可以实现简单的动作。
Action的step和update方法定义:
让动作更平滑流畅
如何让动作看起来更加自然并优雅,
实际上,这是一个涉及玩家注意力的问题。
对于新出现的变化效果,玩家需要时间转移注意力适应这个变化,
而后如果效
果持续稳定、变化不明显,则会降低玩家的注意力,使玩家感觉疲惫。
在这种情况下,一个冗长的匀速动作效果就会造成
游戏不自然不优雅。
不妨为动作添加一些变速效果,将玩家有限的注意力集中到我们希望玩家关注的效果上。
进场动作:由快到慢,快速进入后缓慢停下,在停止前给玩家足够的视觉时间分辨清楚进入的图像。
出场动作:先慢后快,展示了出场趋势和方向后快速移出屏幕,不拖泥带水。
这个变速效果就很自然地交给前面提到的 Ease 系列动作实现了。
针对具体的需求,我们选择了 EaseExponential 动作
来实现变速效果。
以暂停游戏时弹出的菜单为例:
点击暂停游戏后,菜单从屏幕顶端向下滑出;
点击恢复游戏后,菜单向上收起。
弹出菜单的代码如下:
收起菜单的代码如下:
郝萌主友情提示:
优雅自然的动作,能加强游戏的表现性,能吸引更多的玩家、、、
原文地址:http://www.52php.cn/article/p-wotesauw-xv.html
(编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |