【Flutter&Flame 游戏 - 柒】人随指动 | 动画点触与移动


theme: cyanosis

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第 8 天,点击查看活动详情


前言

这是一套 张风捷特烈 出品的 Flutter&Flame 系列教程,发布于掘金社区。如果你在其他平台看到本文,可以根据对于链接移步到掘金中查看。因为文章可能会更新、修正,一切以掘金文章版本为准。本系列文章一览:

第一季完结,谢谢支持 ~


1. 本文目标

之前的主角是通过键盘来控制移动,但移动设备中一般不通过键盘操作,而是点击操作。比如下面的人物在点击时,会动画移动到点击的位置,这就涉及到构件的动画移动。
另外还有个小细节,就是点击时触点的动画,其特点是在点击后显示,一会便自动消失。本文的目标就是实现这两个小功能。


2. 点触动画

这里点击时一闪的小星星,本质上是一个序列动画,如下是序列图片:

我们在 【第一篇】 就介绍了通过 SpriteAnimationComponent 构件对序列帧进行动画播放,但当时并没有细说。 类型维护的 SpriteAnimation 对象是由 Sprite 列表构成的列表,本质上就是在 update 方法中,根据时长来不断更新显示的帧索引而已。
这里把触点指示器封装成一个构件 TouchIndicator ,由外界提供 position 确定位置。在 onLoad 回调中,加载序列帧图片形成 SpriteAnimation 。注意一点,默认情况下序列帧动画是在不断运行的,可以指定 loop: false 设置播放一次。

```dart class TouchIndicator extends SpriteAnimationComponent { TouchIndicator({required Vector2 position}) : super( size: Vector2(30, 30), anchor: Anchor.center, position: position, );

@override Future onLoad() async { List sprites = []; for(int i=1;i<=10;i++){ sprites.add(await Sprite.load('touch/star_${'$i'.padLeft(2,'0')}.png')); } removeOnFinish = true; animation = SpriteAnimation.spriteList(sprites, stepTime: 1/15,loop: false); } } ```

另外 SpriteAnimationComponent 内部维护了 removeOnFinish 成员,用于表示是否在序列帧播放完毕时移除当前构件,这里设置为 true 即可实现如下效果:代码见 【07/01】

TolyGame 中,只需要监听 onPanDown 事件,添加 TouchIndicator 构件即可。

dart class TolyGame extends FlameGame with TapDetector, PanDetector { @override void onPanDown(DragDownInfo info) { add(TouchIndicator(position: info.eventPosition.global)); } }


3. 移动点触

点击显示 TouchIndicator 完成了,其实移动也就非常简单,覆写 onPanUpdate 方法,在其中添加 TouchIndicator 即可。但这里有个问题,onPanUpdate 更新的频率是非常快的,直接添加就会是如下效果,密密麻麻的一坨。这显然并非我们期望的:

dart @override void onPanUpdate(DragUpdateInfo info) { add(TouchIndicator(position: info.eventPosition.global)); }


这个问题的解决方式其实很简单:只要在更新期间,校验一下偏移量是否大于某个值,再添加即可。效果如下,当间隔的位移长度大于 10 时,才添加 TouchIndicator

```dart double ds = 0;

@override void onPanUpdate(DragUpdateInfo info) { ds += info.delta.global.length; if (ds > 10) { add(TouchIndicator(position: info.eventPosition.global)); ds = 0; } } ```


4.构建的的移动效果: MoveEffect

需要让角色动画移动到某个点,可以添加 MoveEffect 构件。如下,在 Adventurer 类中定义toTarget 方法,使用 MoveEffect.to 创建效果对象并进行添加。代码详见:【07/02】

其中 EffectController 可以指定很多动画的参数,比如重复次数、动画曲线、动画时长等。后面会就各种 Effect 进行专文介绍,这里暂时不深入,简单使用以下即可:

```dart ---->[07/02/Adventurer]---- final double _speed = 100;

void toTarget(Vector2 target) { double timeMs = (target-position).length/_speed; add( MoveEffect.to( target, EffectController( duration: timeMs, ), ), ); } ```


然后在 TolyGame 中,点击屏幕时,执行 player.toTarget 方法。角色就会从当前位置,动画移动到指定的 target 位置。

dart @override void onPanDown(DragDownInfo info) { Vector2 target = info.eventPosition.global; add(TouchIndicator(position: target)); player.toTarget(target); }


4. Effect 效果的移除

上面的处理会出现一个问题,如下图所示:当前一次移动动画没有结束前,点一下其他位置,由于两个动画效果同时作用在构建上,所以无法正常完成移动到某点的任务。


解决的思路是:当点击时,应该要移除之前的 MoveEffect ,避免对接下来的移动效果产生影响。每个 Component 中都有 children 成员,表示子构件列表;通过 whereType 可以获取指定类型的子构件列表;然后使用 removeAll 将其移除即可。这样点哪里,角色就是动画运动到哪里。

dart void toTarget(Vector2 target) { removeAll(children.whereType<MoveEffect>()); double timeMs = (target-position).length/_speed; add( MoveEffect.to( target, EffectController( duration: timeMs, ), ), ); }


本文主要介绍了如何让帧动画在播放完后自动移除,以此实现点触时和移动时的闪光动画。接着介绍了使用 MoveEffect 构件完成动画移动的效果。这两者结合起来,就完成了对角色通过触点来控制移动的需求。那本文就到这里,明天见 ~

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值