Crate bevy_tween

source ·
Expand description

All examples in this crate will be using the span_tween implementation which requires the feature “span_tween” and it is enabled by default.

§Getting started

DefaultTweenPlugins provide most the stuff you will need. Add the plugin to your app:

use bevy::prelude::*;
use bevy_tween::*;

fn main() {
    App::default()
        .add_plugins((DefaultPlugins, DefaultTweenPlugins))
        .run();
}

§Tween and Tweener

Tweener is a made up word to describe an entity that handles the current actual playback timing for any tweens that it’s responsible for. It can be understand as a tween runtime or a tween player.

Tween is your animation parameters that declares:

§Multi-entities architecture

This crate will uses multiple entities to provide most of the flexiblity. Generally implemented by using child-parent hierarchy. The exact details is specific to a tweener/tween implementation.

See span tween structure.

§Examples

§Custom interpolator quick example

See “Your own interpolator”. See “Registering systems”.

use bevy::prelude::*;
use bevy_tween::prelude::*;

#[derive(Component)]
struct Foo {
    a: f32,
    b: f32,
}

struct InterpolateFooA {
    start: f32,
    end: f32,
}

impl Interpolator for InterpolateFooA {
    type Item = Foo;

    fn interpolate(&self, item: &mut Self::Item, value: f32) {
        item.a = self.start.lerp(self.end, value);
    }
}

struct InterpolateFooB {
    start: f32,
    end: f32,
}

impl Interpolator for InterpolateFooB {
    type Item = Foo;

    fn interpolate(&self, item: &mut Self::Item, value: f32) {
        item.b = self.start.lerp(self.end, value);
    }
}

fn main() {
    App::new().add_tween_systems((
        bevy_tween::component_tween_system::<BoxedInterpolator<Foo>>(),
        bevy_tween::component_tween_system::<InterpolateFooA>(),
        bevy_tween::component_tween_system::<InterpolateFooB>(),
    ));
}

§Usages

Run cargo run --example span_tween to see this in action.

use bevy::prelude::*;
use bevy_tween::prelude::*;
// This import isn't needed if you're using shortcuts.
use bevy_tween::tween::TargetComponent;

fn main() {
    App::new()
        .add_plugins((DefaultPlugins, DefaultTweenPlugins))
        .add_systems(Startup, setup)
        .run();
}

fn sprite(start_x: f32, start_y: f32) -> SpriteBundle {
    SpriteBundle {
        sprite: Sprite {
            custom_size: Some(Vec2::new(50., 50.)),
            color: Color::WHITE,
            ..Default::default()
        },
        transform: Transform::from_xyz(start_x, start_y, 0.),
        ..Default::default()
    }
}

/// This show all the possible structure you can use.
/// All of these result in exactly the same animation!
/// Just use what fit for your use case.
///
/// These will be presented using the more barebone APIs for clarity.
/// You might want to use shortcuts under "----- or -----" comment.
/// `ComponentTween`, `ResourceTween`, and `AssetTween` is all type alias
/// of `Tween`
fn setup(mut commands: Commands) {
    commands.spawn(Camera2dBundle::default());

    let angle_start = 0.;
    let angle_end = std::f32::consts::PI * 2.;

    let start_x = -300.;
    let end_x = 300.;

    let spacing_y = 100.;
    let offset_y = -(spacing_y * 3.) / 2.;

    // Everything in the same entity
    let y = 0. * spacing_y + offset_y;
    commands.spawn((
        sprite(start_x, y),
        SpanTweenerBundle::new(Duration::from_secs(5)),
        SpanTweenBundle::new(..Duration::from_secs(5)),
        EaseFunction::QuadraticInOut,
        ComponentTween::new_target(
            TargetComponent::tweener_entity(),
            interpolate::Translation {
                start: Vec3::new(start_x, y, 0.),
                end: Vec3::new(end_x, y, 0.),
            },
        ),
        ComponentTween::new_target(
            TargetComponent::tweener_entity(),
            interpolate::AngleZ {
                start: angle_start,
                end: angle_end,
            },
        ),
        // ----- or -----
        // ComponentTween::tweener_entity( ... ),
        // ----- or -----
        // ComponentTween::new( ... ),
    ));

    // Sprite and tweener as parent, tweens as children.
    let y = 1. * spacing_y + offset_y;
    commands
        .spawn((
            sprite(start_x, y),
            SpanTweenerBundle::new(Duration::from_secs(5)),
        ))
        .with_children(|c| {
            c.spawn((
                SpanTweenBundle::new(..Duration::from_secs(5)),
                EaseFunction::QuadraticInOut,
                ComponentTween::new_target(
                    TargetComponent::tweener_entity(),
                    interpolate::Translation {
                        start: Vec3::new(start_x, y, 0.),
                        end: Vec3::new(end_x, y, 0.),
                    },
                ),
                ComponentTween::new_target(
                    TargetComponent::tweener_entity(),
                    interpolate::AngleZ {
                        start: angle_start,
                        end: angle_end,
                    },
                ),
                // ----- or -----
                // ComponentTween::tweener_entity( ... ),
                // ----- or -----
                // ComponentTween::new( ... ),
            ));
        });

    // Only Sprite as parent, tweener and tweens as children.
    let y = 2. * spacing_y + offset_y;
    commands.spawn(sprite(start_x, y)).with_children(|c| {
        c.spawn((
            SpanTweenerBundle::new(Duration::from_secs(5)),
            SpanTweenBundle::new(..Duration::from_secs(5)),
            EaseFunction::QuadraticInOut,
            ComponentTween::new_target(
                TargetComponent::tweener_parent(),
                interpolate::Translation {
                    start: Vec3::new(start_x, y, 0.),
                    end: Vec3::new(end_x, y, 0.),
                },
            ),
            ComponentTween::new_target(
                TargetComponent::tweener_parent(),
                interpolate::AngleZ {
                    start: angle_start,
                    end: angle_end,
                },
            ),
            // ----- or -----
            // ComponentTween::tweener_parent( ... ),
        ));
    });

    // Only Sprite as parent, tweens as children of a tweener.
    let y = 3. * spacing_y + offset_y;
    commands.spawn(sprite(start_x, y)).with_children(|c| {
        c.spawn(SpanTweenerBundle::new(Duration::from_secs(5)))
            .with_children(|c| {
                c.spawn((
                    SpanTweenBundle::new(..Duration::from_secs(5)),
                    EaseFunction::QuadraticInOut,
                    ComponentTween::new_target(
                        TargetComponent::tweener_parent(),
                        interpolate::Translation {
                            start: Vec3::new(start_x, y, 0.),
                            end: Vec3::new(end_x, y, 0.),
                        },
                    ),
                    ComponentTween::new_target(
                        TargetComponent::tweener_parent(),
                        interpolate::AngleZ {
                            start: angle_start,
                            end: angle_end,
                        },
                    ),
                    // ----- or -----
                    // ComponentTween::tweener_parent( ... ),
                ));
            });
    });

    // or with this completely detached
    let y = 4. * spacing_y + offset_y;

    let sprite = commands.spawn(sprite(start_x, y)).id();

    commands
        .spawn(SpanTweenerBundle::new(Duration::from_secs(5)))
        .with_children(|c| {
            c.spawn((
                SpanTweenBundle::new(..Duration::from_secs(5)),
                EaseFunction::QuadraticInOut,
                ComponentTween::new_target(
                    sprite,
                    interpolate::Translation {
                        start: Vec3::new(start_x, y, 0.),
                        end: Vec3::new(end_x, y, 0.),
                    },
                ),
                ComponentTween::new_target(
                    sprite,
                    interpolate::AngleZ {
                        start: angle_start,
                        end: angle_end,
                    },
                ),
            ));
        });
}

Re-exports§

Modules§

  • Module containing some basic built-in interpolator
  • Module containing ease functions and related systems.
  • Commonly used items
  • Module containing span tween implementation
  • Module containing implementations for tween
  • Module containing implementation of a tween timer

Structs§

Enums§

Traits§

  • Helper trait to add systems by this crate to your app and avoid mistake from forgetting to use the intended schedule and set.