Flutter - Flame动效

文章目录[x]
  1. 1:简介
  2. 2:内置动效
  3. 2.1:动效
  4. 2.2:MoveByEffect
  5. 2.3:MoveToEffect
  6. 2.4:MoveAlongPathEffect
  7. 2.5:RotateAroundEffect
  8. 2.6:RotateEffect.by
  9. 2.7:RotateEffect.to
  10. 2.8:ScaleEffect.by
  11. 2.9:ScaleEffect.to
  12. 2.10:SizeEffect.by
  13. 2.11:SizeEffect.to
  14. 2.12:AnchorByEffect
  15. 2.13:AnchorToEffect
  16. 2.14:OpacityToEffect
  17. 2.15:OpacityByEffect
  18. 2.16:GlowEffect
  19. 2.17:SequenceEffect
  20. 2.18:RemoveEffect
  21. 2.19:ColorEffect
  22. 2.20:FunctionEffect

动效是一种特殊的组件,可以附加到其他组件上,以修改其属性或外观。

例如,假设正在制作一款包含可收集强化道具的游戏。希望这些强化道具在地图上随机生成,并在一段时间后消失。显然,可以为强化道具制作一个精灵组件,然后将该组件放置在地图上。

简介

效果器的功能是使某个组件的属性随时间发生变化。为了实现这一点,效果器必须知道该属性的初始值、最终值以及它如何随时间变化。初始值通常由效果器自动确定,最终值由用户明确提供,而随时间变化则由 EffectControllers 处理。

Flame 提供了多种效果器,也可以创建自己的效果器。包含以下效果:

  • MoveByEffect
  • MoveToEffect
  • MoveAlongPathEffect
  • RotateAroundEffect
  • RotateEffect.by
  • RotateEffect.to
  • ScaleEffect.by
  • ScaleEffect.to
  • SizeEffect.by
  • SizeEffect.to
  • AnchorByEffect
  • AnchorToEffect
  • OpacityToEffect
  • OpacityByEffect
  • ColorEffect
  • SequenceEffect
  • RemoveEffect
  • FunctionEffect

EffectController 是一个描述效果如何随时间演变的对象。如果将效果的初始值视为 0% 进度,将最终值视为 100% 进度,那么效果控制器的作用就是将以秒为单位的“物理”时间映射到从 0 到 1 变化的“逻辑”时间。

Flame 框架还提供了多种效果控制器:

  • EffectController 动效控制器
  • LinearEffecController 线性效果控制器
  • ReverseLinearEffectController 反向线性效果控制器
  • CurvedEffectController 曲线效果控制器
  • ReverseCurvedEffectController 反向曲线效果控制器
  • PauseEffectController 暂停效果控制器
  • RepeatedEffectController 重复效果控制器
  • InfiniteEffectController 无限效果控制器
  • SequenceEffectController 顺序效果控制器
  • SpeedEffectController 速度效果控制器
  • DelayedEffectController 延迟效果控制器
  • NoiseEffectController 噪声效果控制器
  • RandomEffectController 随机效果控制器
  • SineEffectController 正弦效果控制器
  • ZigzagEffectController 锯齿效果控制器

内置动效

动效

基础 Effect 类本身不可使用(它是抽象的),但它提供了一些其他效果继承的通用功能。这些功能包括:

  • 使用 effect.pause() 和 effect.resume() 暂停/恢复效果的功能。您可以使用 effect.isPaused 检查效果当前是否处于暂停。
  • removeOnFinish 属性(默认为 true)将导致效果组件在效果完成后从游戏树中移除并被垃圾回收。如果您计划在效果完成后重复使用,请将其设置为 false。
  • 可选的用户提供的 onComplete 函数,将在效果执行完毕但尚未从游戏中移除时调用。
  • Completed Future,在效果完成后完成。
  • reset() 方法将效果恢复到原始状态,使其再次运行。

MoveByEffect

此动效应用于 PositionComponent,并将其按指定的偏移量移动。此偏移量相对于目标的当前位置:

final effect = MoveByEffect(
 Vector2(0, -10),
 EffectController(duration: 0.5),
);

多个移动效果可以同时应用于一个组件。其结果将是所有单独效果的叠加。

MoveToEffect

此效果将 PositionComponent 从其当前位置沿直线移动到指定的目标点:

final effect = MoveToEffect(
 Vector2(100, 500),
 EffectController(duration: 3),
);

MoveAlongPathEffect

此效果使 PositionComponent 沿指定路径相对于组件当前位置移动。路径可以包含非线性段,但必须单向连接。建议从 Vector2.zero() 开始路径,以避免组件位置突然跳跃。

final effect = MoveAlongPathEffect(
 Path()..quadraticBezierTo(100, 0, 50, -50),
 EffectController(duration: 1.5),
);
  • absolute: true 表示效果中的路径为绝对路径。也就是说,目标会在开始时“跳转”到路径的起​​点,然后沿着该路径移动,就像在画布上绘制曲线一样。
  • oriented: true 表示目标不仅会沿着曲线移动,还会在每个点处沿着曲线的方向旋转。使用此标志,效果将同时具有移动和旋转效果。

RotateAroundEffect

将目标绕指定中心点顺时针旋转指定角度(相对于其当前方向)。该角度以弧度为单位。例如,以下效果将使目标绕 (100, 100) 顺时针旋转 90º(= tau/4 弧度)。

final effect = RotateAroundEffect(
 tau/4,
 center: Vector2(100, 100),
 EffectController(duration: 2),
);

RotateEffect.by

将目标相对于其当前方向顺时针旋转指定角度。该角度以弧度为单位。例如,以下效果将使目标顺时针旋转 90º(= tau/4 弧度):

final effect = RotateEffect.by(
 tau/4,
 EffectController(duration: 2),
);

RotateEffect.to

将目标顺时针旋转至指定角度。例如,以下代码将使目标旋转至朝东(0º 为北,90º=tau/4 为东,180º=tau/2 为南,270º=tau*3/4 为西):

final effect = RotateEffect.to(
 tau/4,
 EffectController(duration: 2),
);

ScaleEffect.by

此效果将按指定量改变目标的比例。例如,这将导致组件增大 50%:

final effect = ScaleEffect.by(
 Vector2.all(1.5),
 EffectController(duration: 0.3),
);

ScaleEffect.to

此效果与 ScaleEffect.by 类似,但设置了目标比例的绝对值。

final effect = ScaleEffect.to(
 Vector2.all(0.5),
 EffectController(duration: 0.5),
);

 

SizeEffect.by

此效果将改变目标组件相对于其当前尺寸的大小。例如,如果目标的尺寸为 Vector2(100, 100),则应用以下效果并运行后,新的尺寸将为 Vector2(120, 50):

final effect = SizeEffect.by(
 Vector2(-15, 30),
 EffectController(duration: 1),
);

PositionComponent 的尺寸不能为负数。如果效果尝试将尺寸设置为负值,尺寸将被限制为零。

请注意,要使此效果生效,目标组件必须实现 SizeProvider 接口,并在渲染时考虑其尺寸。只有少数内置组件实现了此 API,但您始终可以通过在类声明中添加 implements SizeEffect 来使自己的组件支持尺寸效果。SizeEffect 的替代方案是 ScaleEffect,它的作用更广泛,可以同时缩放目标组件及其子组件。

SizeEffect.to

将目标组件的尺寸更改为指定尺寸。目标尺寸不能为负数:

final effect = SizeEffect.to(
 Vector2(90, 80),
 EffectController(duration: 1),
);

AnchorByEffect

根据指定的偏移量更改目标锚点的位置。此效果也可以使用 AnchorEffect.by() 来实现。

final effect = AnchorByEffect(
 Vector2(0.1, 0.1),
 EffectController(speed: 1),
);

AnchorToEffect

改变目标锚点的位置。此效果也可以使用 AnchorEffect.to() 来实现。

final effect = AnchorToEffect(
 Anchor.center,
 EffectController(speed: 1),
);

OpacityToEffect

此效果会将目标的不透明度随时间推移更改为指定的 alpha 值。此效果仅适用于实现了 OpacityProvider 的组件。

final effect = OpacityEffect.to(
 0.2,
 EffectController(duration: 0.75),
);

不透明度值为 0 表示组件完全透明,不透明度值为 1 表示完全不透明。便捷构造函数 OpacityEffect.fadeOut() 和 OpacityEffect.fadeIn() 分别会将目标动画化为完全透明/完全可见。

OpacityByEffect

此效果将根据指定的 Alpha 值改变目标的不透明度。例如,以下效果将使目标的不透明度改变 90%:

final effect = OpacityEffect.by(
 0.9,
 EffectController(duration: 0.75),
);

GlowEffect

此效果将根据指定的发光强度在目标周围应用发光阴影。阴影颜色将为目标的油漆颜色。例如,以下效果将在目标周围应用强度为 10 的发光阴影:

final effect = GlowEffect(
 10.0,
 EffectController(duration: 3),
);

目前,此效果只能应用于具有 HasPaint mixin 的组件。

SequenceEffect

此效果可用于依次运行多个其他效果。组成效果的类型可能不同。

序列效果也可以交替运行(序列先向前运行,然后向后运行);也可以按预定次数或无限次重复。

final effect = SequenceEffect([
 ScaleEffect.by(
 Vector2.all(1.5),
 EffectController(
 duration: 0.2,
 alternate: true,
 ),
 ),
 MoveEffect.by(
 Vector2(30, -50),
 EffectController(
 duration: 0.5,
 ),
 ),
 OpacityEffect.to(
 0,
 EffectController(
 duration: 0.3,
 ),
 ),
 RemoveEffect(),
]);

RemoveEffect

这是一个简单的效果,可以附加到一个组件,使其在指定的延迟时间过去后从游戏树中移除:

final effect = RemoveEffect(delay: 3.0);

ColorEffect

此效果将改变油漆的基色,导致渲染的组件在提供的范围内被提供的颜色着色。

final effect = ColorEffect(
 const Color(0xFF00FF00),
 EffectController(duration: 1.5),
 opacityFrom: 0.2,
 opacityTo: 0.8,
);

opacityFrom 和 opacityTo 参数将决定应用于组件的颜色“量”。在本例中,效果将从 20% 开始,逐渐增加到 80%。

注意:由于此效果的实现方式以及 Flutter 的 ColorFilter 类的工作方式,此效果不能与其他 ColorEffect 混合使用。当向组件添加多个 ColorEffect 时,只有最后一个 ColorEffect 才会生效。

FunctionEffect

FunctionEffect 类是一个非常通用的 Effect 类,它几乎允许执行任何操作,而无需定义新的 Effect。它运行一个函数,该函数接受目标和 Effect 的进度作为参数,然后用户可以决定如何处理该输入。

例如,它可以用于实现游戏状态随时间的变化,但不一定像大多数其他 Effect 那样具有视觉效果。

在下面的示例中,我们有一个 PlayerState 枚举,我们希望它随时间变化。我们希望在进度超过 50% 时将状态更改为“打哈欠”,在进度超过 80% 时将其恢复为“空闲”。

enum PlayerState {
idle,
yawn,
}

final effect = FunctionEffect<SpriteAnimationGroupComponent<PlayerState>>(
(target, progress) {
if (progress > 0.5) {
target.current = PlayerState.yawn;
} else if(progress > 0.8) {
target.current = PlayerState.idle;
}
},
EffectController(
duration: 10,
infinite: true,
),
);
点赞

发表评论

昵称和uid可以选填一个,填邮箱必填(留言回复后将会发邮件给你)
tips:输入uid可以快速获得你的昵称和头像

Title - Artist
0:00