micro_games_kit/
animation.rsuse spitfire_draw::utils::TextureRef;
use std::{
collections::{HashMap, HashSet},
ops::Range,
};
use vek::Rect;
#[derive(Debug, Clone, PartialEq)]
pub struct FrameAnimation {
frames: Range<usize>,
current: Option<usize>,
accumulator: f32,
events: HashMap<usize, HashSet<String>>,
pub fps: f32,
pub is_playing: bool,
pub looping: bool,
}
impl FrameAnimation {
pub fn new(frames: Range<usize>) -> Self {
Self {
frames,
current: None,
accumulator: 0.0,
events: Default::default(),
fps: 30.0,
is_playing: false,
looping: false,
}
}
pub fn event(mut self, frame: usize, id: impl ToString) -> Self {
self.events.entry(frame).or_default().insert(id.to_string());
self
}
pub fn fps(mut self, value: f32) -> Self {
self.fps = value;
self
}
pub fn playing(mut self) -> Self {
self.play();
self
}
pub fn looping(mut self) -> Self {
self.looping = true;
self
}
pub fn play(&mut self) {
if self.frames.is_empty() {
return;
}
self.is_playing = true;
self.accumulator = 0.0;
self.current = Some(self.frames.start);
}
pub fn stop(&mut self) {
self.is_playing = false;
self.accumulator = 0.0;
self.current = None;
}
pub fn update(&mut self, delta_time: f32) -> HashSet<&str> {
if self.frames.is_empty() || !self.is_playing {
return Default::default();
}
let Some(mut current) = self.current else {
return Default::default();
};
let mut result = HashSet::default();
self.accumulator += (delta_time * self.fps).max(0.0);
while self.accumulator >= 1.0 {
self.accumulator -= 1.0;
if let Some(events) = self.events.get(¤t) {
result.extend(events.iter().map(|id| id.as_str()));
}
current += 1;
if current >= self.frames.end {
if self.looping {
current = self.frames.start;
} else {
self.is_playing = false;
self.accumulator = 0.0;
self.current = None;
return result;
}
}
}
self.current = Some(current);
result
}
pub fn current_frame(&self) -> Option<usize> {
self.current
}
}
#[derive(Debug, Clone)]
pub struct NamedAnimation {
pub animation: FrameAnimation,
pub id: String,
}
#[derive(Debug, Clone)]
pub struct SpriteAnimationFrame {
pub texture: TextureRef,
pub region: Rect<f32, f32>,
pub page: f32,
}
#[derive(Debug, Clone)]
pub struct SpriteAnimation {
pub animation: FrameAnimation,
pub frames: HashMap<usize, SpriteAnimationFrame>,
}
impl SpriteAnimation {
pub fn current_frame(&self) -> Option<&SpriteAnimationFrame> {
self.frames.get(&self.animation.current_frame()?)
}
}