# Tweens

A Tween can be used to interpolate some state over time.

A Tween is created by instancing the `Scar::Tween` class and managed by a `Scar::App`. To start the Tween, use `app#tween(t : Tween)` method. The constructor works like this:

```ruby
def initialize(
    duration : Number,
    @ease : Easing::EasingDefinition,
    @on_update : Proc(Tween, Nil) = ->(t : Tween) {},
    @on_completed : Proc(Tween, Nil) = ->(t : Tween) {}
    )
```

* `duration` denotes how long the tweening should last (in seconds)
* `ease` defines how the fraction is calculated (see below)
* `on_update` is called every frame
* `on_completed` is called before the Tween is deleted

In `on_update` you should define what  the Tween should modify. For example, if you want to tween a screen transition, you would modify the alpha value in `on_update`.

In `on_completed` you could for example start another tween to fade the alpha value back.

There are some instance methods to query or modify the state of a Tween:

* `linear_fraction` returns the linear progression
* `fraction` returns the fraction calculated by `@ease`
* `completed?` returns if the duration has passed
* `reset` resets the elapsed time to 0 (restarts the Tween)
* `abort` cancels execution WITHOUT calling `on_completed`
* getter and setter for `@paused` to pause/unpause the Tween

### EasingDefinition

The abstract struct `Scar::Easing::EasingDefinition` exists to define how a Tween calculates it's fraction. You can either inherit this struct, use `Scar::Easing::EaseWithFunction` which can be initialized with a calculate function `def initialize(@fn : Proc(Float32, Float32)); end` or use the `Scar::Easing#simple_easing_function(name, fn)` macro where you can provide fn as a stringified mathematical expression like `simple_easing_function(:EaseInQuad, "lf ** 2")`.

There are some builtin easing definitions, please refer to the [reference](https://vypxl.github.io/scar/Scar/Easing.html) for further information.

### Example

```ruby
app.tween(Tween.new 
    JUMP_TIME,
    Easing::EaseOutQuad.new, 
    ->(t : Tween) { tr.pos.y = t.fraction * JUMP_HEIGHT; nil },
    ->(t : Tween) { nil })
```
