feat: atlas decoding & frame acquisition

This commit is contained in:
2025-07-25 12:27:19 -05:00
parent 8cf30cd78d
commit 6ca2e01fba
8 changed files with 206 additions and 152 deletions

View File

@@ -1,34 +1,24 @@
//! This module provides a simple animation and atlas system for textures.
use anyhow::Result;
use glam::IVec2;
use sdl2::{
render::{Canvas, Texture},
video::Window,
};
use sdl2::render::WindowCanvas;
use crate::entity::direction::Direction;
use crate::texture::atlas::AtlasTexture;
use crate::texture::FrameDrawn;
use crate::texture::sprite::AtlasTile;
/// An animated texture using a texture atlas.
pub struct AnimatedAtlasTexture {
pub atlas: AtlasTexture,
#[derive(Clone)]
pub struct AnimatedTexture {
pub frames: Vec<AtlasTile>,
pub ticks_per_frame: u32,
pub ticker: u32,
pub reversed: bool,
pub paused: bool,
}
impl AnimatedAtlasTexture {
pub fn new(
texture: Texture<'static>,
ticks_per_frame: u32,
frame_count: u32,
width: u32,
height: u32,
offset: Option<IVec2>,
) -> Self {
AnimatedAtlasTexture {
atlas: AtlasTexture::new(texture, frame_count, width, height, offset),
impl AnimatedTexture {
pub fn new(frames: Vec<AtlasTile>, ticks_per_frame: u32) -> Self {
AnimatedTexture {
frames,
ticks_per_frame,
ticker: 0,
reversed: false,
@@ -36,38 +26,25 @@ impl AnimatedAtlasTexture {
}
}
fn current_frame(&self) -> u32 {
self.ticker / self.ticks_per_frame
}
/// Advances the animation by one tick, unless paused.
pub fn tick(&mut self) {
if self.paused {
if self.paused || self.ticks_per_frame == 0 {
return;
}
if self.reversed {
if self.ticker > 0 {
self.ticker -= 1;
}
if self.ticker == 0 {
self.reversed = !self.reversed;
}
} else {
self.ticker += 1;
if self.ticker + 1 == self.ticks_per_frame * self.atlas.frame_count {
self.reversed = !self.reversed;
}
self.ticker += 1;
}
pub fn current_tile(&self) -> &AtlasTile {
if self.ticks_per_frame == 0 {
return &self.frames[0];
}
let frame_index = (self.ticker / self.ticks_per_frame) as usize % self.frames.len();
&self.frames[frame_index]
}
pub fn set_color_modulation(&mut self, r: u8, g: u8, b: u8) {
self.atlas.set_color_modulation(r, g, b);
}
}
impl FrameDrawn for AnimatedAtlasTexture {
fn render(&self, canvas: &mut Canvas<Window>, position: IVec2, direction: Direction, frame: Option<u32>) {
let frame = frame.unwrap_or_else(|| self.current_frame());
self.atlas.render(canvas, position, direction, Some(frame));
pub fn render(&self, canvas: &mut WindowCanvas, dest: sdl2::rect::Rect) -> Result<()> {
let tile = self.current_tile();
tile.render(canvas, dest)
}
}