Effects

An effect is a special component that can attach to another component in order to modify its properties or appearance.

For example, suppose you are making a game with collectible power-up items. You want these power-ups to generate randomly around the map and then de-spawn after some time. Obviously, you could make a sprite component for the power-up and then place that component on the map, but we could do even better!

Let’s add a ScaleEffect to grow the item from 0 to 100% when the power-up first appears. Add another infinitely repeating alternating MoveEffect in order to make the item move slightly up and down. Then add an OpacityEffect that will “blink” the item 3 times, this effect will have a built-in delay of 30 seconds, or however long you want your power-up to stay in place. Lastly, add a RemoveEffect that will automatically remove the item from the game tree after the specified time (you probably want to time it right after the end of the OpacityEffect).

As you can see, with a few simple effects we have turned a simple lifeless sprite into a much more interesting item. And what’s more important, it didn’t result in an increased code complexity: the effects, once added, will work automatically, and then self-remove from the game tree when finished.

Overview

The function of an Effect is to effect a change over time in some component’s property. In order to achieve that, the Effect must know the initial value of the property, the final value, and how it should progress over time. The initial value is usually determined by an effect automatically, the final value is provided by the user explicitly, and progression over time is handled by EffectControllers.

Effect

The base Effect class is not usable on its own (it is abstract), but it provides some common functionality inherited by all other effects. This includes:

  • The ability to pause/resume the effect using effect.pause() and effect.resume(). You can check whether the effect is currently paused using effect.isPaused.

  • Property removeOnFinish (which is true by default) will cause the effect component to be removed from the game tree and garbage-collected once the effect completes. Set this to false if you plan to reuse the effect after it is finished.

  • Optional user-provided onComplete, which will be invoked when the effect has just completed its execution but before it is removed from the game.

  • A completed future that completes when the effect finishes.

  • The reset() method reverts the effect to its original state, allowing it to run once again.

There are multiple pre-built effects provided by Flame, and you can also create your own. The following effects are included:

Creating new effects

Although Flame provides a wide array of built-in effects, eventually you may find them to be insufficient. Luckily, creating new effects is very simple.

Each effect extends the base Effect class, possibly via one of the more specialized abstract subclasses such as ComponentEffect<T> or Transform2DEffect.

The Effect class’ constructor requires an EffectController instance as an argument. In most cases you may want to pass that controller from your own constructor. Luckily, the effect controller encapsulates much of the complexity of an effect’s implementation, so you don’t need to worry about re-creating that functionality.

Lastly, you will need to implement a single method apply(double progress) that will be called at each update tick while the effect is active. In this method you are supposed to make changes to the target of your effect.

In addition, you may want to implement callbacks onStart() and onFinish() if there are any actions that must be taken when the effect starts or ends.

When implementing the apply() method we recommend to use relative updates only. That is, change the target property by incrementing/decrementing its current value, rather than directly setting that property to a fixed value. This way multiple effects would be able to act on the same component without interfering with each other.

See also