Expand description

A sprite-sheet animation plugin for bevy

Usage

  1. Add the AnimationPlugin plugin
use std::time::Duration;
use bevy::prelude::*;
use benimator::*;

fn main() {
    App::new()
        .add_plugins(DefaultPlugins)
        .add_plugin(AnimationPlugin::default()) // <-- Enable sprite-sheet animations
        .add_startup_system(spawn.system())
        // ...
        .run()
}

fn spawn() { /* ... */ }
  1. Create a SpriteSheetAnimation and insert the asset handle to the sprite sheet entity you want to animate

fn spawn(mut commands: Commands, mut animations: ResMut<Assets<SpriteSheetAnimation>>) {

    // Create an animation
    let animation_handle = animations.add(SpriteSheetAnimation::from_range(
        0..=2,                               // Indices of the sprite atlas
        Duration::from_secs_f64(1.0 / 12.0), // Duration of each frame
    ));

    commands
        .spawn_bundle(SpriteSheetBundle {
            // TODO: Configure the sprite sheet
            ..Default::default()
        })
        // Insert the asset handle of the animation
        .insert(animation_handle)
        // Start the animation immediately
        .insert(Play);
}

Run the animation only once

By default the animation loops forever. But it is possible to configure it differently:

SpriteSheetAnimation::from_range(0..=2, Duration::from_millis(100))
     .once(); // <-- Runs the animation only once

Note that, for animations that run once, the Play component is automatically removed when the animation is done. So you can use the RemovedComponents<Play> system parameter to execute logic at the end of the animation.

Play/Pause

Animations proceed only if the Play component is present in the entity.

To pause or resume an animation, simply remove/insert the Play component.

Fine-grained frame-duration

For a more precise configuration, it is possible to define the duration of each frame:

SpriteSheetAnimation::from_frames(vec![
    Frame::new(0, Duration::from_millis(120)),
    Frame::new(1, Duration::from_millis(100)),
    Frame::new(2, Duration::from_millis(80)),
]);

Reset animation

For each entity with a SpriteSheetAnimation, a SpriteSheetAnimationState component is automatically inserted. It can be used to reset the animation state by calling SpriteSheetAnimationState::reset


fn restart_anim_from_start(mut query: Query<&mut SpriteSheetAnimationState>) {
  for mut state in query.iter_mut() {
    state.reset();
  }
}

(Unstable) Load animation from file

By enabling the cargo feature: unstable-load-from-file you can write the animation in an asset file with the extension .animation.yml then load with the asset-server.

Here is how the animation file looks like:

mode: ping-pong
frames:
  - index: 0 # index in the sprite sheet for that frame
    duration: 100 # duration of the frame in milliseconds
  - index: 1
    duration: 100
  - index: 2
    duration: 120

And how to load it with the asset server

fn load(mut commands: Commands, asset_server: Res<AssetServer>) {

    // Load animation from the asset server
    let animation_handle: Handle<SpriteSheetAnimation> = asset_server.load("player_run.animation.yml");

    // TODO insert the handle in an entity...
}

Structs

Plugin to enable sprite-sheet animation

A single animation frame

Components that indicates the animation is playing

Asset that define an animation of TextureAtlasSprite

Animation state component which is automatically inserted/removed

Enums

Labels of systems that run during the post-update stage