Rendering animation!

This commit is contained in:
Evan Pratten 2022-03-29 14:41:35 -04:00
parent bfe1ea01ce
commit 91991c1f9c
7 changed files with 71 additions and 22 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

View File

@ -35,6 +35,10 @@ def check_sprite_exists(sprite_type: str, sprite_name: str) -> bool:
def stitch_images_and_write_to_disk(sprite_type: str, sprite_name: str, images: List[str], quantize: bool, fps: float, reverse_order: bool) -> None: def stitch_images_and_write_to_disk(sprite_type: str, sprite_name: str, images: List[str], quantize: bool, fps: float, reverse_order: bool) -> None:
# Handle reverse order
if reverse_order:
images = images[::-1]
# Load all the images # Load all the images
images_to_stitch = [] images_to_stitch = []
for image_path in images: for image_path in images:
@ -74,13 +78,9 @@ def stitch_images_and_write_to_disk(sprite_type: str, sprite_name: str, images:
"frames": [] "frames": []
} }
# Handle reverse order
if reverse_order:
images_to_stitch.reverse()
# Add the metadata for each image # Add the metadata for each image
x_offset = 0 x_offset = 0
for image in images_to_stitch: for i in range(len(images_to_stitch)):
metadata["frames"].append({ metadata["frames"].append({
"x": x_offset, "x": x_offset,
"y": 0, "y": 0,

View File

@ -1,7 +1,7 @@
{ {
"sheet_height": 338, "sheet_height": 338,
"sheet_width": 10800, "sheet_width": 9600,
"published_at": "2022-03-29 18:21:28", "published_at": "2022-03-29 18:40:22",
"published_by": "ewpratten", "published_by": "ewpratten",
"fps": 24.0, "fps": 24.0,
"frames": [ "frames": [
@ -100,18 +100,6 @@
"y": 0, "y": 0,
"width": 600, "width": 600,
"height": 338 "height": 338
},
{
"x": 9600,
"y": 0,
"width": 600,
"height": 338
},
{
"x": 10200,
"y": 0,
"width": 600,
"height": 338
} }
] ]
} }

Binary file not shown.

Before

Width:  |  Height:  |  Size: 200 KiB

After

Width:  |  Height:  |  Size: 191 KiB

View File

@ -1,5 +1,6 @@
//! This module handles the code for rendering framerate-locked animations from textures //! This module handles the code for rendering framerate-locked animations from textures
use chrono::{DateTime, Utc};
use nalgebra::Vector2; use nalgebra::Vector2;
use raylib::{ use raylib::{
color::Color, color::Color,
@ -54,14 +55,20 @@ struct AnimatedTextureMetadata {
#[derive(Debug)] #[derive(Debug)]
pub struct AnimatedTexture { pub struct AnimatedTexture {
/// The whole internal spritesheet
texture: Texture2D, texture: Texture2D,
/// The metadata describing the spritesheet
texture_metadata: AnimatedTextureMetadata, texture_metadata: AnimatedTextureMetadata,
// a list of source rects to reduce memory allocation needs during render time /// a list of source rects to reduce memory allocation needs during render time
texture_source_rects: Vec<Rectangle>, texture_source_rects: Vec<Rectangle>,
/// The animation start timestamp
start_time: Option<DateTime<Utc>>,
} }
impl AnimatedTexture { impl AnimatedTexture {
/// Construct a new `AnimatedTexture` /// Construct a new `AnimatedTexture`
///
/// This will load all resources from RAM or disk. May take a while.
#[profiling::function] #[profiling::function]
pub fn new( pub fn new(
raylib_handle: &mut RaylibHandle, raylib_handle: &mut RaylibHandle,
@ -112,9 +119,11 @@ impl AnimatedTexture {
texture, texture,
texture_metadata, texture_metadata,
texture_source_rects: source_rects, texture_source_rects: source_rects,
start_time: None,
}) })
} }
/// Render a single frame to the screen
#[profiling::function] #[profiling::function]
pub fn render_frame_by_index( pub fn render_frame_by_index(
&self, &self,
@ -154,4 +163,57 @@ impl AnimatedTexture {
tint.unwrap_or(Color::WHITE), tint.unwrap_or(Color::WHITE),
); );
} }
/// Clear the internal tracker for when the animation started
///
/// This will bring the animation back to frame 1. Useful for non-looping rendering
pub fn reset_animation(&mut self) {
self.start_time = None;
}
/// Get the current frame index
pub fn get_current_frame_index(&self) -> Option<usize> {
self.start_time.map(|start_time| {
let elapsed_time_ms = Utc::now()
.signed_duration_since(start_time)
.num_milliseconds() as f32;
let elapsed_time_s = elapsed_time_ms / 1000.0;
let frame_index = (elapsed_time_s * self.texture_metadata.fps) as usize;
frame_index % self.texture_metadata.frames.len()
})
}
/// Render the animation based on timestamp
pub fn render_automatic(
&mut self,
draw_handle: &mut RaylibDrawHandle,
position: Vector2<f32>,
percent_scale: Option<Vector2<f32>>,
origin: Option<Vector2<f32>>,
rotation: Option<f32>,
tint: Option<Color>,
) {
// If this is the first time we're rendering, set the start time
if self.start_time.is_none() {
self.start_time = Some(Utc::now());
}
// Get the current frame index
let current_frame_index = self.get_current_frame_index();
// If we have a valid index, render it
if let Some(current_frame_index) = current_frame_index {
self.render_frame_by_index(
draw_handle,
current_frame_index,
position,
percent_scale,
origin,
rotation,
tint,
);
} else {
warn!("We somehow got a frame index of None");
}
}
} }

View File

@ -38,9 +38,8 @@ impl TestFoxScene {
draw.clear_background(Color::WHITE); draw.clear_background(Color::WHITE);
// Render the fox // Render the fox
self.fox_animation.render_frame_by_index( self.fox_animation.render_automatic(
&mut draw, &mut draw,
0,
na::Vector2::new(0.0, 0.0), na::Vector2::new(0.0, 0.0),
None, None,
None, None,