generated from 2ndbeam/bevy-template
feat: More AnimatedSprite methods
This commit is contained in:
parent
f3b2d0313e
commit
be36504a00
1 changed files with 55 additions and 7 deletions
|
|
@ -5,6 +5,8 @@ use std::{collections::HashMap, time::Duration};
|
||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
use bevy_ecs::system::EntityEntryCommands;
|
use bevy_ecs::system::EntityEntryCommands;
|
||||||
|
|
||||||
|
type SpriteCommands<'a> = EntityEntryCommands<'a, Sprite>;
|
||||||
|
|
||||||
/// Data for [AnimatedSprite]
|
/// Data for [AnimatedSprite]
|
||||||
#[derive(Clone, PartialEq, Debug, Default, Reflect)]
|
#[derive(Clone, PartialEq, Debug, Default, Reflect)]
|
||||||
#[reflect(Clone, PartialEq, Debug, Default)]
|
#[reflect(Clone, PartialEq, Debug, Default)]
|
||||||
|
|
@ -19,6 +21,7 @@ pub struct AnimationData {
|
||||||
|
|
||||||
impl AnimationData {
|
impl AnimationData {
|
||||||
/// Construct new [AnimationData] from given [Handle<TextureAtlasLayout>]
|
/// Construct new [AnimationData] from given [Handle<TextureAtlasLayout>]
|
||||||
|
#[inline(always)]
|
||||||
pub fn new(image: Handle<Image>, frames: Handle<TextureAtlasLayout>, duration_multiplier: f32) -> Self {
|
pub fn new(image: Handle<Image>, frames: Handle<TextureAtlasLayout>, duration_multiplier: f32) -> Self {
|
||||||
Self { image, frames, duration_multiplier }
|
Self { image, frames, duration_multiplier }
|
||||||
}
|
}
|
||||||
|
|
@ -33,36 +36,41 @@ pub struct AnimatedSprite {
|
||||||
current: Option<AnimationData>,
|
current: Option<AnimationData>,
|
||||||
timer: Timer,
|
timer: Timer,
|
||||||
duration: Duration,
|
duration: Duration,
|
||||||
|
backwards: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AnimatedSprite {
|
impl AnimatedSprite {
|
||||||
/// Constructs new AnimatedSprite
|
/// Constructs new AnimatedSprite
|
||||||
|
#[inline(always)]
|
||||||
pub fn new(data: HashMap<String, AnimationData>, duration: Duration) -> Self {
|
pub fn new(data: HashMap<String, AnimationData>, duration: Duration) -> Self {
|
||||||
let timer = Timer::new(duration, TimerMode::Once);
|
let timer = Timer::new(duration, TimerMode::Once);
|
||||||
|
|
||||||
Self { data, current: None, timer, duration }
|
Self { data, current: None, timer, duration, backwards: false }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Add new animation to sprite
|
/// Add new animation to sprite
|
||||||
|
#[inline(always)]
|
||||||
pub fn add(&mut self, data: AnimationData, label: String) {
|
pub fn add(&mut self, data: AnimationData, label: String) {
|
||||||
self.data.insert(label, data);
|
self.data.insert(label, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sets internal duration
|
/// Sets internal duration
|
||||||
|
#[inline(always)]
|
||||||
pub fn set_duration(&mut self, duration: Duration) {
|
pub fn set_duration(&mut self, duration: Duration) {
|
||||||
self.duration = duration;
|
self.duration = duration;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Finds animation by its label and returns it if started playing
|
fn play_inner(
|
||||||
pub fn play(
|
|
||||||
&mut self,
|
&mut self,
|
||||||
label: &str,
|
label: &str,
|
||||||
mode: TimerMode,
|
mode: TimerMode,
|
||||||
mut sprite: EntityEntryCommands<Sprite>,
|
mut sprite: SpriteCommands,
|
||||||
|
backwards: bool,
|
||||||
) -> Option<&AnimationData> {
|
) -> Option<&AnimationData> {
|
||||||
self.data.get(label).map(|data| {
|
self.data.get(label).map(|data| {
|
||||||
self.current = Some(data.clone());
|
self.current = Some(data.clone());
|
||||||
self.timer = Timer::new(self.duration.mul_f32(data.duration_multiplier), mode);
|
self.timer = Timer::new(self.duration.mul_f32(data.duration_multiplier), mode);
|
||||||
|
self.backwards = backwards;
|
||||||
|
|
||||||
let sprite_image = data.image.clone();
|
let sprite_image = data.image.clone();
|
||||||
let layout = data.frames.clone();
|
let layout = data.frames.clone();
|
||||||
|
|
@ -76,14 +84,54 @@ impl AnimatedSprite {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Finds animation by its label, plays it and returns it if started playing
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn play(
|
||||||
|
&mut self,
|
||||||
|
label: &str,
|
||||||
|
mode: TimerMode,
|
||||||
|
sprite: SpriteCommands,
|
||||||
|
) -> Option<&AnimationData> {
|
||||||
|
self.play_inner(label, mode, sprite, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Same as [play](AnimatedSprite::play), but animation plays from the end to the beginning
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn play_backwards(
|
||||||
|
&mut self,
|
||||||
|
label: &str,
|
||||||
|
mode: TimerMode,
|
||||||
|
sprite: SpriteCommands,
|
||||||
|
) -> Option<&AnimationData> {
|
||||||
|
self.play_inner(label, mode, sprite, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Stops the animation
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn stop(&mut self) {
|
||||||
|
self.current = None;
|
||||||
|
self.timer.reset();
|
||||||
|
}
|
||||||
|
|
||||||
/// Updates animation timer
|
/// Updates animation timer
|
||||||
|
#[inline(always)]
|
||||||
pub fn tick(&mut self, dt: Duration) {
|
pub fn tick(&mut self, dt: Duration) {
|
||||||
self.timer.tick(dt);
|
self.timer.tick(dt);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns inner [Timer::fraction]
|
/// Returns inner [Timer::fraction] or [Timer::fraction_remaining] if playing backwards
|
||||||
|
#[inline(always)]
|
||||||
pub fn fraction(&self) -> f32 {
|
pub fn fraction(&self) -> f32 {
|
||||||
self.timer.fraction()
|
match self.backwards {
|
||||||
|
true => self.timer.fraction_remaining(),
|
||||||
|
false => self.timer.fraction(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns [Timer::mode]
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn mode(&self) -> TimerMode {
|
||||||
|
self.timer.mode()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -107,7 +155,7 @@ pub fn update_animated_sprites(
|
||||||
|
|
||||||
let max_frames = atlas.len() as f32;
|
let max_frames = atlas.len() as f32;
|
||||||
|
|
||||||
let current_frame = (max_frames * animation.fraction()) as usize;
|
let current_frame = (max_frames * animation.fraction()).min(max_frames - 1.) as usize;
|
||||||
|
|
||||||
if let Some(atlas) = &mut sprite.texture_atlas {
|
if let Some(atlas) = &mut sprite.texture_atlas {
|
||||||
atlas.index = current_frame;
|
atlas.index = current_frame;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue