use bevy::{prelude::*, window::PrimaryWindow};
use bevy_spritesheet_animation::prelude::*;
fn main() {
App::new()
.add_plugins((
DefaultPlugins.set(ImagePlugin::default_nearest()),
SpritesheetAnimationPlugin,
))
.add_systems(Startup, spawn_animations)
.run();
}
fn spawn_animations(
windows: Query<&Window, With<PrimaryWindow>>,
mut commands: Commands,
assets: Res<AssetServer>,
mut animations: ResMut<Assets<Animation>>,
mut atlas_layouts: ResMut<Assets<TextureAtlasLayout>>,
) {
let window = windows.single().expect("no primary window");
commands.spawn(Camera2d);
let image = assets.load("ball.png");
let spritesheet = Spritesheet::new(&image, 1, 30);
let mut parameters = vec![
(Some(AnimationDuration::PerFrame(50)), None, None, None),
(Some(AnimationDuration::PerFrame(500)), None, None, None),
(Some(AnimationDuration::PerFrame(2000)), None, None, None),
(
Some(AnimationDuration::PerRepetition(2000)),
None,
None,
None,
),
(
Some(AnimationDuration::PerRepetition(100)),
None,
None,
None,
),
(None, Some(AnimationRepeat::Times(10)), None, None),
(None, Some(AnimationRepeat::Times(100)), None, None),
(None, Some(AnimationRepeat::Loop), None, None),
(None, None, Some(AnimationDirection::Forwards), None),
(None, None, Some(AnimationDirection::Backwards), None),
(None, None, Some(AnimationDirection::PingPong), None),
];
for variety in [
EasingVariety::Quadratic,
EasingVariety::Cubic,
EasingVariety::Quartic,
EasingVariety::Quintic,
EasingVariety::Sin,
EasingVariety::Exponential,
EasingVariety::Circular,
] {
parameters.push((None, None, None, Some(Easing::In(variety))));
parameters.push((None, None, None, Some(Easing::Out(variety))));
parameters.push((None, None, None, Some(Easing::InOut(variety))));
}
for (index, (duration, repetitions, direction, easing)) in parameters.iter().enumerate() {
let mut animation = spritesheet.create_animation().add_column(0);
if let &Some(duration) = duration {
animation = animation.set_duration(duration);
}
if let &Some(repetitions) = repetitions {
animation = animation.set_repetitions(repetitions);
}
if let &Some(direction) = direction {
animation = animation.set_direction(direction);
}
if let &Some(easing) = easing {
animation = animation.set_easing(easing);
}
let animation_handle = animations.add(animation.build());
let sprite = spritesheet
.with_size_hint(100, 600)
.sprite(&mut atlas_layouts);
commands
.spawn((
sprite,
SpritesheetAnimation::new(animation_handle),
Transform::from_translation(grid_position(window, 6, 6, index)),
))
.with_children(|builder| {
let mut description = String::new();
duration.inspect(|x| description.push_str(&format!("duration: {:?}\n", x)));
repetitions.inspect(|x| description.push_str(&format!("repetitions: {:?}\n", x)));
direction.inspect(|x| description.push_str(&format!("direction: {:?}\n", x)));
easing.inspect(|x| description.push_str(&format!("easing: {:?}\n", x)));
builder.spawn((
Text2d(description),
TextColor(Color::WHITE),
Transform::from_xyz(0.0, -50.0, 0.0).with_scale(Vec3::splat(0.7)),
));
});
}
}
fn grid_position(window: &Window, columns: u32, rows: u32, n: usize) -> Vec3 {
const MARGIN: f32 = 100.0;
let width = window.width() - MARGIN * 2.0;
let height = window.height() - MARGIN * 2.0;
let xgap = width / columns.saturating_sub(1) as f32;
let ygap = height / rows.saturating_sub(1) as f32;
let x = (n as u32 % columns) as f32;
let y = (n as u32 / columns) as f32;
Vec3::new(
x * xgap - width / 2.0,
-y * ygap + height / 2.0, 0.0,
)
}