持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第 18 天,点击查看活动详情
前言
这是一套 张风捷特烈 出品的 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. Effect 是什么
比如马里奥吃到蘑菇变大动画;僵尸被寒冰射手击中,整体颜色变成偏蓝色;当主角被击中时闪烁几下,或怪物被消灭时透明渐变消失。这些视觉上的效果处理,会增加游戏的动感,刚好地和用户交互。当你对一个构件进行移动、缩放、旋转、透明度、尺寸、颜色进行换行时,就可以考虑添加 Effect
。
本质上来说 Effect
是一个 Component
,它往往是被附加在其他构件上,实现功能。也就是说,一般并不单独展示 Effect
构件。另外,Effect
是一个抽象类,不能直接使用,Flame
中提供的 Effect
实现类在 effects
包下,如下所示:
Flame
提供的 Effect
有如下几个,主要分为两类:第一种是进行基本变换操作,及:移动
、旋转
、缩放
等;另一种是 ComponentEffect
,为构件添加颜色、透明度、尺寸等变换特效。下面来结合粒子介绍一下。
2. 移动特效:MoveEffect
由 MoveEffect
支持移动特效,不过它是一个抽象类,不能作为运行时使用。它有两个子类:MoveByEffect
和 MoveToEffect
,分别应用 移动了
和 移动到
某位移。之前点击屏幕,让角色移动到指定位置,用的就是 MoveToEffect
。 下面通过两个一个小例子来介绍它们的使用方式和区别:本文代码均在 【18/01】
https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/ee834b987974406cbe10f588b8faa8f1~tplv-k3u1fbpfcp-zoom-in-crop-mark:1304:0:0:0.awebp?
当按下数字 1
键时让角色 0.5
秒位移 Vector2(10, -10)
。实现创建 MoveByEffect
对象,设置偏移量和控制器,然后附加在角色构建上面即可。代码如下:
void addMoveByEffect(){
Effect effect = MoveByEffect(
Vector2(10, -10),
EffectController(duration: 0.5),
);
player.add(effect);
}
复制代码
当按下数字 2
键时让角色 0.5
秒移动到
屏幕中心。实现创建 MoveToEffect
对象,设置目标点和控制器,然后附加在角色构建上面即可。代码如下:
void addMoveToEffect(){
Effect effect = MoveToEffect(
size / 2,
EffectController(duration: 0.5),
);
player.add(effect);
}
复制代码
另外注意一个小细节,MoveEffect
虽然是抽象类,但定义了 by
和 to
的工厂构造方法,来创建子类对象。本质上和直接使用 MoveByEffect
和 MoveToEffect
没有区别,可以根据自己的喜好来用。我更倾向于用 MoveEffect
的命名构造,感觉语义上好一些。
3. 旋转特效 :RotateEffect
从源码中来看 RotateEffect
也有 by
和 to
两个构造,含义上和移动类似。 by
表示旋转了多少度,to
表示旋转到多少度。
下面通过按下数字键 3
让角色旋转 15°
,通过下面的 addRotateEffectBy
实现;按下数字键 4
让角色旋转到 0°
, 通过下面的 addRotateEffectTo
实现。如下所示:
https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/f8547758b4014d01a6531368a01f35a2~tplv-k3u1fbpfcp-zoom-in-crop-mark:1304:0:0:0.awebp?
代码语言:javascript复制void addRotateEffectBy(){
Effect effect = RotateEffect.by(
15/180*pi,
EffectController(duration: 0.5),
);
player.add(effect);
}
void addRotateEffectTo(){
Effect effect = RotateEffect.to(
0,
EffectController(duration: 0.5),
);
player.add(effect);
}
复制代码
4. 缩放特效:ScaleEffect
同样 ScaleEffect
也有 by
和 to
两个构造,和前面的也类似。 by
表示缩放了多少,to
表示缩放到多少。
下面通过按下数字键 5
让角色缩放 Vector2(1.2,1.2)
,通过下面的 addScaleEffectBy
实现;按下数字键 6
让角色旋转到 0°
, 通过下面的 addScaleEffectTo
实现。如下所示:
https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/e8c903a98eec4d5d985c974fb591f9eb~tplv-k3u1fbpfcp-zoom-in-crop-mark:1304:0:0:0.awebp?
代码语言:javascript复制void addScaleEffectBy(){
Effect effect = ScaleEffect.by(
Vector2(1.2,1.2),
EffectController(duration: 0.5),
);
player.add(effect);
}
void addScaleEffectTo(){
Effect effect = ScaleEffect.to(
Vector2(1,1),
EffectController(duration: 0.5),
);
player.add(effect);
}
复制代码
5. 移除特效: 移除特效
从 RemoveEffect
的源码中可以看出,这个特效非常简单,甚至连控制器都不需要指定。RemoveEffect
的作用是在 delay
秒后,移除附加的构件。如果时长为 0
,那这和构件直接触发 removeFromParent
没有什么太大的区别。
如下测试中,点击数字键 7
,显示边框信息示意,然后在 3
秒后消失。代码如下:
https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/b836878726f04ccf9bf5d1bdfb91968f~tplv-k3u1fbpfcp-zoom-in-crop-mark:1304:0:0:0.awebp?
代码语言:javascript复制void addRemoveEffect(){
Effect effect = RemoveEffect(
delay:3
);
player.add(effect);
}
复制代码
6. Effect 的结束回调事件
在 【第七篇】 人随指动的一文中,使用到了 MoveEffect
,那时有朋友问了一下 Effect
是否有执行完成的回调。这里来解答一下:
其实瞄一眼 Effect
的源码就很容易看到,有个 onFinishCallback
的方法可以监听结束回调:
使用方式也非常简单,直接设置 onFinishCallback
回调即可:
void addMoveByEffect(){
Effect effect = MoveByEffect(
Vector2(10, -10),
EffectController(duration: 0.5),
);
effect.onFinishCallback =(){
print('=====onFinishCallback========');
};
player.add(effect);
}
复制代码
另外,注意一点:Effect
中有一个 removeOnFinish
方法,默认为 true
,就表示在特效完成时,会主动从宿主身上移除。如果不想移除可以把该属性设为 false
,可以触发 Effect#reset
方法来让特效在此执行。
本文介绍了 Effect
的体系和基本的用法,写了几个小例子认识变换相关的特效。下一篇我们将继续认识一下 ComponentEffect
系列的特效,特效好有个非常重要的 EffectController
概念,在后面也会逐步介绍。那本文就到这里,明天见 ~
@张风捷特烈 2022.06.12 未允禁转
我的 掘金主页
: 张风捷特烈我的 B站主页
: 张风捷特烈我的 github 主页
: toly1994328