Dead Simple Sprite-Sheet Animations
source link: https://hackernoon.com/dead-simple-sprite-sheet-animations
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
Dead Simple Sprite-Sheet Animations
Dead Simple Sprite-Sheet Animations
Too Long; Didn't Read
I’ve been using Bevy for a personal project and it’s been delightful. As the project has grown, I’ve turned into a level designer, animator, illustrator, along with the usual programmer.
Sometimes I hit walls, and rabbit holes around those walls are just too compelling to pass up. One such rabbit hole was figuring out sprite animation loops from a single sprite sheet. The only reason for using a single sprite-sheet is that being the dev and the illustrator is very time consuming and I wanted my workflow to remain as simple as possible.
audio
element.I’ve been using Bevy for a personal project and it’s been delightful. As the project has grown, I’ve turned into a level designer, animator, illustrator, along with the usual programmer.
Sometimes I hit walls, and rabbit holes around those walls are just too compelling to pass up. One such rabbit hole was figuring out sprite animation loops from a single sprite sheet. The only reason for using a single sprite-sheet is that being the dev and the illustrator is very time consuming and I wanted my workflow to remain as simple as possible.
Sprite sheet
Animated
Creating Animation Pages
An animation page is a group of frames that form a looping animation. In the following example the animation pages are represented by an enum.
Defining animation loop in an array
Implementation
Defining animation variants in an enum
I refer to the animation sections as variants, and the offset/size tuple as a page
#[derive(Clone, PartialEq)]
pub enum PlayerAnimationVariant {
Idle,
Rising,
Falling,
}
Creating an AnimationLoop
trait
The trait is straightforward, defines a function that would return the offset and size of the animation page.
pub trait AnimationLoop {
fn page(&self) -> (usize, usize);
}
Implementing the AnimationLoop
trait for the enum
The trait is straightforward, defines a function that would return the offset and size of the animation page.
impl AnimationLoop for PlayerAnimationVariant {
fn page(&self) -> (usize, usize) {
match self {
// return values (idx_offset, loop_size) describe the animation loop
PlayerAnimationVariant::Idle => (0, 3),
PlayerAnimationVariant::Rising => (2, 2),
PlayerAnimationVariant::Falling => (4, 4),
}
}
}
Frame and Page transitions
looping
Implementation
Implementing an animation state manager
The struct stores the animation variant to play, and the current index of the frame.
pub struct PlayerAnimationState {
pub variant: PlayerAnimationVariant,
pub idx: usize,
}
Implementing transition functions
wrapping_next_idx
increments the idx
and wraps around at the page boundary
impl PlayerAnimationState {
fn wrapping_next_idx(&mut self) -> usize {
let current_idx = self.idx;
let (offset, size) = self.variant.page();
self.idx = offset + (current_idx + 1) % size;
self.idx
}
}
transition_variant
updates the animation state manager to play the variant passed as an argument
impl PlayerAnimationState {
...
fn transition_variant(&mut self, to: PlayerAnimationVariant) {
let (offset, _) = to.page();
self.variant = to;
self.idx = offset;
}
}
This can be somewhat tedious, so I created a Rust crate that simplifies the process by providing:
- the traits
AnimationLoop
andAnimationTransition<T: AnimationLoop>
- a handy macro
AnimationTransitionMacro
that implements the necessary index manipulation functions for the animation state manager
Check out the final product here! And here's the repository.
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK