持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第 20 天,点击查看活动详情
前言
这是一套 张风捷特烈 出品的 Flutter&Flame
系列教程,发布于掘金社区。如果你在其他平台看到本文,可以根据对于链接移步到掘金中查看。因为文章可能会更新、修正,一切以掘金文章版本为准。本系列源码于 【toly_game】 ,如果本系列对你有所帮助,希望点赞支持,本系列文章一览:
- 【Flutter&Flame 游戏 - 壹】开启新世界的大门
- 【Flutter&Flame 游戏 - 贰】操纵杆与角色移动
- 【Flutter&Flame 游戏 - 叁】键盘事件与手势操作
- 【Flutter&Flame 游戏 - 肆】精灵图片加载方式
- 【Flutter&Flame 游戏 - 伍】Canvas 参上 | 角色的血条
- 【Flutter&Flame 游戏 - 陆】暴击 Dash | 文字构件的使用
- 【Flutter&Flame 游戏 - 柒】人随指动 | 动画点触与移动
- 【Flutter&Flame 游戏 - 捌】装弹完毕 | 角色武器发射
- 【Flutter&Flame 游戏 - 玖】探索构件 | Component 是什么
- 【Flutter&Flame 游戏 - 拾】探索构件 | Component 生命周期回调
- 【Flutter&Flame 游戏 - 拾壹】探索构件 | Component 使用细节
- 【Flutter&Flame 游戏 - 拾贰】探索构件 | 角色管理
- 【Flutter&Flame 游戏 - 拾叁】碰撞检测 | CollisionCallbacks
- 【Flutter&Flame 游戏 - 拾肆】碰撞检测 | 之前代码优化
- 【Flutter&Flame 游戏 - 拾伍】粒子系统 | ParticleSystemComponent
- 【Flutter&Flame 游戏 - 拾陆】粒子系统 | 粒子的种类
- 【Flutter&Flame 游戏 - 拾柒】构件特效 | 了解 Effect 体系
- 【Flutter&Flame 游戏 - 拾捌】构件特效 | ComponentEffect 一族
- 【Flutter&Flame 游戏 - 拾玖】构件特效 | 了解 EffectController 体系
- 【Flutter&Flame 游戏 - 贰拾】构件特效 | 其他 EffectControler
- 【Flutter&Flame 游戏 - 贰壹】视差组件 | ParallaxComponent
- 【Flutter&Flame 游戏 - 贰贰】菜单、字体和浮层
未完待续
~
1. EffectController 及其衍生类
在 Effect
类中,持有一个 EffectController
对象,并在构造方法中被初始化。也就是说,任何 Effect
在构造时,都必须指定 EffectController
对象。
如下是 EffectController
类的定义,首先它是一个抽象类,其中维护了一些动画相关的 get
属性,包括动画时长 duration
、进度 progress
、动画是否已开启 started
、 动画是否已结束 completed
等。以及四个应用控制动画的抽象方法:
它作为抽象类,是无法直接作为运行时对象被实例化的,必定有其实现类对功能进行具体实现。在 effects/controllers
包中,有着很多不同功能的 EffectController
。
EffectController
衍生类目前有如下 14
个,主要分为两种:DurationEffectController
一族和直接继承自 EffectController
的子类。这些控制器本质上和 Flutter
原生的 AnimationController
是类似的,都是对数值的进行变换处理,从而让动画的变化效果。因为 Flame
在一个持续运转的 Ticker
中,所以 EffectController
相比于原生而言是更加简单的,不需要考虑 Ticker
的创建、销毁等处理。
根据名称也基本上能猜个大概功能。比如 DelayedEffectController
可以让动画延时播放、InfiniteEffectController
可以让动画无限时长、RepeatedEffectController
可以让动画重复播放、CurvedEffectController
可以支持变化曲线等。
2、线性效果控制器: LinearEffectController
如果看过 《Flutter 动画探索 - 流光幻影》,那么你对动画控制器的插值一定不会陌生。我们都知道 Ticker
每次触发回调的时间间隔基本恒定,其中每次触发被称为 1 帧
。如果某个量的属性在每一帧中都增加固定的值,在连续变化的过程中,该属性就会呈现一个 线性的
变化效果:
https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/bdd29f15dabd41959fb113649f28062d~tplv-k3u1fbpfcp-zoom-in-crop-mark:1304:0:0:0.awebp
比如 LinearEffectController
中,每帧的 progress
属性是 运行时长
除以 总时长
,也就是说该进度值的变化是线性的。
如下,使用 LinearEffectController
让角色在 2s
内向上平移 100
,可见运动的位移变化是均匀的。
https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/40711f07d8024f2eaf0a414c4b8a278c~tplv-k3u1fbpfcp-zoom-in-crop-mark:1304:0:0:0.awebp?
代码语言:javascript复制void linearEffectController(){
EffectController ctrl = LinearEffectController(2);
Effect effect = MoveByEffect(
Vector2(0, -100),
ctrl,
);
player.add(effect);
}
复制代码
3. 曲线效果控制器:CurvedEffectController
曲线指的是在每次更新时,对属性值的变化量附加的变换效果。比如下面是附件 Curves.ease
的曲线变换,如果把属性值对应到小球的高度只,就可以通过该曲线变换实现开始运动快,后面逐渐减慢的效果。
https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/1debbb6112ea4c77955ff1024e1e8267~tplv-k3u1fbpfcp-zoom-in-crop-mark:1304:0:0:0.awebp
如下, CurvedEffectController
中可以指定一个 Curve
对象,用于转换。这样角色在进行位移动画时就可以有速度变换的效果:
https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/610dfb97ef054bd2a6cc181841161841~tplv-k3u1fbpfcp-zoom-in-crop-mark:1304:0:0:0.awebp?
代码语言:javascript复制void curvedEffectController(){
EffectController ctrl = CurvedEffectController(2,Curves.ease);
Effect effect = MoveByEffect(
Vector2(0, -100),
ctrl,
);
player.add(effect);
}
复制代码
简单瞄一下源码,可以看出 CurvedEffectController
中做的事,就是通过 Curve
对象的 transform
方法,对进度进行变换而已:
而 Curves.ease
是一个静态的 Cubic
对象,它的 transform
方法,就是按照三次贝塞尔曲线方程,对入参进行变换。也就是说,你可以通过 Cubic
对象,自定义任何的三次贝塞尔曲线,让速度按照该曲线进行。其中四个入参分别代表三次贝塞尔曲线的两个控制点坐标,另外起始坐标为 (0,0)
,终止坐标为 (1,1)
。
static const Cubic ease = Cubic(0.25, 0.1, 0.25, 1.0);
复制代码
4. 反向控制器:ReverseLinearEffectController、ReverseCurvedEffectController
这两个看着名字老长的,本质上就是进度值被 1
减下而已,也就是说,默认一开始是 100%
,然后逐渐变为 0
,即反方动画。如下图所示,如果是 ReverseLinearEffectController
,动画开启时,角色将从 (0,-100)
点向下匀速运动:
https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/f91230e66c4a45c1af6e462293923747~tplv-k3u1fbpfcp-zoom-in-crop-mark:1304:0:0:0.awebp?
代码语言:javascript复制EffectController ctrl = ReverseLinearEffectController(2);
复制代码
对于 ReverseCurvedEffectController
来说也一样, Curve
对象的 transform
方法转换的对象,也是被 1
减的进度。对应于图像来上,相当于反走曲线,所以对于 Curves.ease
来说,会产生先慢后快的效果。
https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/e3034a22ce3345caa1ddec008d3204cc~tplv-k3u1fbpfcp-zoom-in-crop-mark:1304:0:0:0.awebp?
代码语言:javascript复制EffectController ctrl = ReverseCurvedEffectController(2,Curves.ease);
复制代码
5. 正弦曲线控制器: SineEffectController
这个也非常好理解, Cubic
是通过三次贝塞尔曲线,对数值进行变换;那这里就是通过正弦函数对数值进行变换。这点在源码中很容易被证实,可以看出在 period
时长下,属性值会完成 0~2pi
的正弦函数变换,效果如下图:
https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/13b4168917fc4850860e9f7ac209e5c7~tplv-k3u1fbpfcp-zoom-in-crop-mark:1304:0:0:0.awebp?
代码语言:javascript复制EffectController ctrl = SineEffectController(period: 2);
复制代码
这有个不错的应用场景,可以结合 RepeatedEffectController
重复震荡,来达到抖动的效果,这在下一篇介绍 RepeatedEffectController
时再细说,效果如下所示:
https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/ae43ef0ea7f447c4982963dc02970984~tplv-k3u1fbpfcp-zoom-in-crop-mark:1304:0:0:0.awebp?
6.噪音曲线控制器: NoiseEffectController
这里噪音曲线指的是在 0
附近随机震荡的的点,源码中通过 SimplexNoise
对象进行转换。这个比较适合做一些随机震动的场景,比如抖动:
https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/3043e7b1e0eb45a5acc308f27c12d42e~tplv-k3u1fbpfcp-zoom-in-crop-mark:1304:0:0:0.awebp?
代码语言:javascript复制EffectController ctrl = NoiseEffectController(frequency: 30,duration: 1);
复制代码
7.锯齿形曲线控制器:ZigzagEffectController
这个控制器的变化是 0->1->0->-1->0
,数值随时间的变化呈 锯齿形
,如下图所示:
对应到角色的位移上,就是均匀的震荡,如下图所示:
https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/274fda81d9d640dba6854d6a679f0728~tplv-k3u1fbpfcp-zoom-in-crop-mark:1304:0:0:0.awebp?
代码语言:javascript复制EffectController ctrl = ZigzagEffectController(period: 2);
复制代码
最后 PauseEffectController
的进度数值不会随时间进行任何变换,也就是说这个动画效果是不会动的效果。感觉使用场景非常优先,本身也非常简单,了解一下即可:
通过本文,我们认识了 8
个 DurationEffectController
一族的效果控制器。总的来看,这一族非常简单,就是利用不同的函数对进度数值进行转换而已,本身没有什么难点。通过这些控制器,就可以让动画不那么 “死板”
,可以让运动的速度产生变化,以及进行周期性的震荡。下一篇将继续通过小案例介绍其他的控制器,那本文就到这里,明天见 ~
@张风捷特烈 2022.06.14 未允禁转
我的 掘金主页
: 张风捷特烈我的 B站主页
: 张风捷特烈我的 github 主页
: toly1994328