# GDScript: Syntax & Sugar

Source: https://tweens.gd/gdscript/syntax-sugar/

No, you’re not seeing things: there’s more than one way to tween a ferret, and that’s fully intentional. While developing tweens.gd, we set out to solve at least two, probably four, problems:

-   Fire onceA one-off that just does its thing.`Tweens.play(self, …)`
-   Set values each timeDestinations or timings you want to specify each time.`(to, 0.6, Out.CUBIC)`
-   Several targetsThe same motion, applied to several different nodes.`Tweens.play(node, hop)`
-   Small variationsSmall variations for that extra juice.`hop.with_delay(0.2)`

Between them, the Structured and Convenient syntaxes cover all four, and both take safe or sweet endpoints.

## Definitions: Structured vs. Convenient

The **Structured** syntax creates a definition object to reuse, or to vary with `with_*()` copies.

Structured

```gdscript
var arrive := Tweens.position_2d([400, 180], 0.6, Out.CUBIC)

Tweens.play(sprite, arrive.with_delay(0.1))
```

Fully Structured

```gdscript
var arrive := Tweens.position_2d()
arrive.to_value = Vector2(400, 180)
arrive.duration = 0.6
arrive.ease = Out.CUBIC
arrive.delay = 0.1

Tweens.play(sprite, arrive)
```

The **Convenient** syntax creates and starts a local animation in one `Tweens.play()` expression.

Convenient

```gdscript
Tweens.play(sprite, Tweens.position_2d([400, 180], 0.6, Out.CUBIC, 0.1))
```

GDScript uses helpers rather than node extensions. Thus, it’s always somewhat close to the Structured way of doing things. Just store the definition in a `var` and you’re golden!

These are alternative ways to start the same motion. Both return a handle when played.

## Values: Safe vs. Sweet

A Godot value states the endpoint’s type explicitly.

Safe: explicit type

```gdscript
Tweens.play(sprite, Tweens.position_2d(Vector2(400, 180), 0.6))
```

An array of components is shorter, and the start converts it to the expected type.

Sweet: array

```gdscript
Tweens.play(sprite, Tweens.position_2d([400, 180], 0.6))
```

An array of mismatched length rejects at start with `FAILED`.

Both move to the same position, and definition helpers accept the same forms. GDScript has no tuple syntax or C#’s compile-time endpoint checks.

| Animate | Sweet endpoint |
| --- | --- |
| Uniform scale | `Tweens.scale_2d([1.2, 1.2], 0.2)` |
| RGB color | `Tweens.modulate([1, 0.5, 0], 0.3)` |
| Named or HTML color | `Tweens.modulate(Color("tomato"), 0.3)` |

Three color components imply alpha 1. Arrays also work with `with_from()`, `with_to()`, and `with_by()`. For `Tweens.value()`, supply real vectors or colors so their type is known.

## Easing and delay

Arguments follow **endpoint, duration, ease, delay**. Times are seconds.

Fields name every setting.

Clean: explicit & readable

```gdscript
var arrive := Tweens.position_2d()
arrive.to_value = Vector2(400, 180)
arrive.duration = 0.6
arrive.ease = Out.CUBIC
arrive.delay = 0.2
```

Helper arguments take the same settings in order.

Quick: convenient & concise

```gdscript
var arrive := Tweens.position_2d([400, 180], 0.6, Out.CUBIC, 0.2)
Tweens.play(sprite, Tweens.position_2d([400, 180], 0.6, Out.CUBIC, 0.2))
```

A helper takes the same arguments on its own or inside `Tweens.play()`.

## More options

Set any other field on the definition. Definitions are mutable, so vary a copy with `with_*()` to leave the original unchanged.

Structured

```gdscript
var pulse := Tweens.scale_2d([1.2, 1.2], 0.2)
pulse.ping_pong = true
Tweens.play(sprite, pulse.with_repeats(2))
```

Chain `with_*()` copies on the helper inside the `Tweens.play()` call.

Convenient

```gdscript
Tweens.play(sprite, Tweens.scale_2d([1.2, 1.2], 0.2).with_ping_pong().with_repeats(2))
```
