Skip to content

Commit

Permalink
Make it easier to control playback, clean up Animator
Browse files Browse the repository at this point in the history
  • Loading branch information
merwaaan committed Aug 30, 2024
1 parent c017778 commit 99a5653
Show file tree
Hide file tree
Showing 25 changed files with 1,223 additions and 732 deletions.
13 changes: 13 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,18 @@
# Changelog

## 0.4.1 - 2024-??-??

### Added

- Add a `progress` field in the SpritesheetAnimation component to query and control the animation state
- Add a `switch()` method to SpritesheetAnimation component to switch to another animation and reset the progress
- Add `get_clip()` and `get_animation()` methods to the library
- Attach more information to animation events (current clip, current repetition)

### Changed

- Change the type for repetitions from u32 to usize for consistency

## 0.4.0 - 2024-08-28

This update simplifies the high-level API of the library.
Expand Down
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ bevy_spritesheet_animation is a [Bevy](https://bevyengine.org/) plugin for anima
- A [convenient API](https://docs.rs/bevy_spritesheet_animation/latest/bevy_spritesheet_animation/spritesheet/struct.Spritesheet.html) to select frames in spritesheets.

> [!TIP]
> This crate is under active development. Please regularly check [CHANGELOG.md] for recent changes.
> This crate is under active development. Please regularly check the [CHANGELOG](CHANGELOG.md) for recent changes.
# Quick start

Expand Down Expand Up @@ -278,6 +278,7 @@ For more examples, browse the [examples/](examples) directory.
| -------------------------------------- | ------------------------------------------------------------------------ |
| [basic](examples/basic.rs) | Shows how to create an animated sprite |
| [3d](examples/3d.rs) | Shows how to create 3D sprites |
| [progress](examples/progress.rs) | Shows how to control an animation |
| [composition](examples/composition.rs) | Shows how to create an animation with multiple clips |
| [parameters](examples/parameters.rs) | Shows the effect of each animation parameter |
| [character](examples/character.rs) | Shows how to create a controllable character with multiple animations |
Expand Down
11 changes: 7 additions & 4 deletions examples/character.rs
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ fn control_character(
// Set the animation

if let Some(id) = library.animation_with_name("shoot") {
animation.animation_id = id;
animation.switch(id);
}

// Add a Shooting component
Expand All @@ -131,9 +131,11 @@ fn control_character(
// Set the animation

if let Some(id) = library.animation_with_name("run") {
animation.animation_id = id;
animation.switch(id);
}

// TODO keep same frame when moving already?

// Move

transform.translation -= Vec3::X * time.delta_seconds() * CHARACTER_SPEED;
Expand All @@ -144,7 +146,7 @@ fn control_character(
// Set the animation

if let Some(id) = library.animation_with_name("run") {
animation.animation_id = id;
animation.switch(id);
}

// Move
Expand All @@ -157,7 +159,7 @@ fn control_character(
// Set the animation

if let Some(id) = library.animation_with_name("idle") {
animation.animation_id = id;
animation.switch(id);
}
}
}
Expand All @@ -172,6 +174,7 @@ fn control_character(
AnimationEvent::AnimationRepetitionEnd {
entity,
animation_id,
..
} => {
if library.is_animation_name(*animation_id, "shoot") {
commands.entity(*entity).remove::<Shooting>();
Expand Down
12 changes: 0 additions & 12 deletions examples/composition.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ fn main() {
.add_plugins(DefaultPlugins)
.add_plugins(SpritesheetAnimationPlugin)
.add_systems(Startup, setup)
.add_systems(Update, reset_on_keypress)
.run();
}

Expand Down Expand Up @@ -75,14 +74,3 @@ fn setup(
SpritesheetAnimation::from_id(animation_id),
));
}

fn reset_on_keypress(
keyboard: Res<ButtonInput<KeyCode>>,
mut sprites: Query<&mut SpritesheetAnimation>,
) {
if keyboard.get_just_pressed().len() > 0 {
for mut animation in &mut sprites {
animation.reset();
}
}
}
3 changes: 2 additions & 1 deletion examples/events.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,14 @@
#[path = "./common/mod.rs"]
pub mod common;

use std::collections::HashSet;

use bevy::{
color::palettes::css::{DEEP_PINK, GRAY, YELLOW},
prelude::*,
sprite::{MaterialMesh2dBundle, Mesh2dHandle},
};
use bevy_spritesheet_animation::prelude::*;
use std::collections::HashSet;

fn main() {
App::new()
Expand Down
117 changes: 117 additions & 0 deletions examples/progress.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
// This example shows how to control the progress of an animation.

#[path = "./common/mod.rs"]
pub mod common;

use bevy::prelude::*;
use bevy_spritesheet_animation::prelude::*;

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

#[derive(Component)]
struct AllAnimations {
animation1_id: AnimationId,
animation2_id: AnimationId,
}

fn setup(
mut commands: Commands,
mut library: ResMut<AnimationLibrary>,
mut atlas_layouts: ResMut<Assets<TextureAtlasLayout>>,
assets: Res<AssetServer>,
) {
commands.spawn(Camera2dBundle::default());

// Create two animations

let spritesheet = Spritesheet::new(8, 8);

let mut create_animation = |frames| {
let clip = Clip::from_frames(frames).with_duration(AnimationDuration::PerFrame(2000));
let clip_id = library.register_clip(clip);

let animation = Animation::from_clip(clip_id);
library.register_animation(animation)
};

let animation1_id = create_animation(spritesheet.row(3));
let animation2_id = create_animation(spritesheet.horizontal_strip(0, 5, 5));

// Spawn an animated sprite

let texture = assets.load("character.png");

let layout = atlas_layouts.add(Spritesheet::new(8, 8).atlas_layout(96, 96));

commands.spawn((
SpriteBundle {
texture,
..default()
},
TextureAtlas {
layout,
..default()
},
SpritesheetAnimation::from_id(animation1_id),
// Store the two animation IDs in a component for convenience
AllAnimations {
animation1_id,
animation2_id,
},
));
}

fn keyboard(
keyboard: Res<ButtonInput<KeyCode>>,
mut sprites: Query<(&mut SpritesheetAnimation, &AllAnimations)>,
) {
for (mut sprite, all_animations) in &mut sprites {
// Pause the current animation

if keyboard.just_pressed(KeyCode::KeyP) {
sprite.playing = !sprite.playing;
}

// Reset the current animation

if keyboard.just_pressed(KeyCode::KeyR) {
sprite.reset();
}

// Go to a specific frame of the current animation

let keys = [
KeyCode::Numpad0,
KeyCode::Numpad1,
KeyCode::Numpad2,
KeyCode::Numpad3,
KeyCode::Numpad4,
KeyCode::Numpad5,
];

for (frame, key) in keys.iter().enumerate() {
if keyboard.just_pressed(*key) {
sprite.progress.frame = frame;
}
}

// Switch to the other animation

if keyboard.just_pressed(KeyCode::KeyS) {
let next_animation = if sprite.animation_id == all_animations.animation1_id {
all_animations.animation2_id
} else {
all_animations.animation1_id
};

sprite.switch(next_animation);
}
}
}
2 changes: 1 addition & 1 deletion src/animation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ pub enum AnimationRepeat {
/// Loops indefinitely
Loop,
/// Repeats a fixed number of times
Times(u32),
Times(usize),
}

impl Default for AnimationRepeat {
Expand Down
Loading

0 comments on commit 99a5653

Please sign in to comment.