Effect controllers¶
An EffectController
is an object that describes how the effect should evolve over time. If you
think of the initial value of the effect as 0% progress, and the final value as 100% progress, then
the job of the effect controller is to map from the “physical” time, measured in seconds, into the
“logical” time, which changes from 0 to 1.
There are multiple effect controllers provided by the Flame framework:
EffectController
¶
The base EffectController
class provides a factory constructor capable of creating a variety of
common controllers. The syntax of the constructor is the following:
EffectController({
required double duration,
Curve curve = Curves.linear,
double? reverseDuration,
Curve? reverseCurve,
bool alternate = false,
double atMaxDuration = 0.0,
double atMinDuration = 0.0,
int? repeatCount,
bool infinite = false,
double startDelay = 0.0,
VoidCallback? onMax,
VoidCallback? onMin,
});
duration
– the length of the main part of the effect, i.e. how long it should take to go from 0 to 100%. This parameter cannot be negative, but can be zero. If this is the only parameter specified then the effect will grow linearly over theduration
seconds.curve
– if given, creates a non-linear effect that grows from 0 to 100% according to the provided curve.reverseDuration
– if provided, adds an additional step to the controller: after the effect has grown from 0 to 100% over theduration
seconds, it will then go backwards from 100% to 0 over thereverseDuration
seconds. In addition, the effect will complete at progress level of 0 (normally the effect completes at progress 1).reverseCurve
– the curve to be used during the “reverse” step of the effect. If not given, this will default tocurve.flipped
.alternate
– setting this to true is equivalent to specifying thereverseDuration
equal to theduration
. If thereverseDuration
is already set, this flag has no effect.atMaxDuration
– if non-zero, this inserts a pause after the effect reaches its max progress and before the reverse stage. During this time the effect is kept at 100% progress. If there is no reverse stage, then this will simply be a pause before the effect is marked as completed.atMinDuration
– if non-zero, this inserts a pause after the reaches its lowest progress (0) at the end of the reverse stage. During this time, the effect’s progress is at 0%. If there is no reverse stage, then this pause will still be inserted after the “at-max” pause if it’s present, or after the forward stage otherwise. In addition, the effect will now complete at progress level of 0.repeatCount
– if greater than one, it will cause the effect to repeat itself the prescribed number of times. Each iteration will consists of the forward stage, pause at max, reverse stage, then pause at min (skipping those that were not specified).infinite
– if true, the effect will repeat infinitely and never reach completion. This is equivalent to as ifrepeatCount
was set to infinity.startDelay
– an additional wait time inserted before the beginning of the effect. This wait time is executed only once, even if the effect is repeating. During this time the effect’s.started
property returns false. The effect’sonStart()
callback will be executed at the end of this waiting period.Using this parameter is the simplest way to create a chain of effects that execute one after another (or with an overlap).
onMax
– callback function which will be invoked right after reaching its max progress and before the optional pause and reverse stage.onMin
– callback function which will be invoked right after reaching its lowest progress at the end of the reverse stage and before the optional pause and forward stage.
The effect controller returned by this factory constructor will be composited of multiple simpler effect controllers described further below. If this constructor proves to be too limited for your needs, you can always create your own combination from the same building blocks.
In addition to the factory constructor, the EffectController
class defines a number of properties
common for all effect controllers. These properties are:
.started
– true if the effect has already started. For most effect controllers this property is always true. The only exception is theDelayedEffectController
which returns false while the effect is in the waiting stage..completed
– becomes true when the effect controller finishes execution..progress
– current value of the effect controller, a floating-point value from 0 to 1. This variable is the main “output” value of an effect controller..duration
– total duration of the effect, ornull
if the duration cannot be determined (for example if the duration is random or infinite).
LinearEffectController
¶
This is the simplest effect controller that grows linearly from 0 to 1 over the specified
duration
:
final controller = LinearEffectController(3);
ReverseLinearEffectController
¶
Similar to the LinearEffectController
, but it goes in the opposite direction and grows linearly
from 1 to 0 over the specified duration:
final controller = ReverseLinearEffectController(1);
CurvedEffectController
¶
This effect controller grows non-linearly from 0 to 1 over the specified duration
and following
the provided curve
:
final controller = CurvedEffectController(0.5, Curves.easeOut);
ReverseCurvedEffectController
¶
Similar to the CurvedEffectController
, but the controller grows down from 1 to 0 following the
provided curve
:
final controller = ReverseCurvedEffectController(0.5, Curves.bounceInOut);
PauseEffectController
¶
This effect controller keeps the progress at a constant value for the specified time duration.
Typically, the progress
would be either 0 or 1:
final controller = PauseEffectController(1.5, progress: 0);
RepeatedEffectController
¶
This is a composite effect controller. It takes another effect controller as a child, and repeats it multiple times, resetting before the start of each next cycle.
final controller = RepeatedEffectController(LinearEffectController(1), 10);
The child effect controller cannot be infinite. If the child is random, then it will be re-initialized with new random values on each iteration.
InfiniteEffectController
¶
Similar to the RepeatedEffectController
, but repeats its child controller indefinitely.
final controller = InfiniteEffectController(LinearEffectController(1));
SequenceEffectController
¶
Executes a sequence of effect controllers, one after another. The list of controllers cannot be empty.
final controller = SequenceEffectController([
LinearEffectController(1),
PauseEffectController(0.2),
ReverseLinearEffectController(1),
]);
SpeedEffectController
¶
Alters the duration of its child effect controller so that the effect proceeds at the predefined
speed. The initial duration of the child EffectController is irrelevant. The child controller must
be the subclass of DurationEffectController
.
The SpeedEffectController
can only be applied to effects for which the notion of speed is
well-defined. Such effects must implement the MeasurableEffect
interface. For example, the
following effects qualify:
The parameter speed
is in units per second, where the notion of a “unit” depends on the target
effect. For example, for move effects, they refer to the distance traveled; for rotation effects
the units are radians.
final speedController = SpeedEffectController(LinearEffectController(0), speed: 1);
final controller = EffectController(speed: 1); // same as speedController
DelayedEffectController
¶
Effect controller that executes its child controller after the prescribed delay
. While the
controller is executing the “delay” stage, the effect will be considered “not started”, i.e. its
.started
property will be returning false
.
final controller = DelayedEffectController(LinearEffectController(1), delay: 5);
NoiseEffectController
¶
This effect controller exhibits noisy behavior, i.e. it oscillates randomly around zero. Such effect controller can be used to implement a variety of shake effects.
final controller = NoiseEffectController(duration: 0.6, frequency: 10);
RandomEffectController
¶
This controller wraps another controller and makes its duration random. The actual value for the duration is re-generated upon each reset, which makes this controller particularly useful within repeated contexts, such as RepeatedEffectController or InfiniteEffectController.
final controller = RandomEffectController.uniform(
LinearEffectController(0), // duration here is irrelevant
min: 0.5,
max: 1.5,
);
The user has the ability to control which Random
source to use, as well as the exact distribution
of the produced random durations. Two distributions – .uniform
and .exponential
are included,
any other can be implemented by the user.
SineEffectController
¶
An effect controller that represents a single period of the sine function. Use this to create
natural-looking harmonic oscillations. Two perpendicular move effects governed by
SineEffectControllers
with different periods, will create a Lissajous curve.
final controller = SineEffectController(period: 1);
ZigzagEffectController
¶
Simple alternating effect controller. Over the course of one period
, this controller will proceed
linearly from 0 to 1, then to -1, and then back to 0. Use this for oscillating effects where the
starting position should be the center of the oscillations, rather than the extreme (as provided
by the standard alternating EffectController
).
final controller = ZigzagEffectController(period: 2);