From 3c3025668afc6fe31d87c1748b8e9cb0456b36bb Mon Sep 17 00:00:00 2001 From: SeanOMik Date: Sun, 24 Nov 2024 21:52:48 -0500 Subject: [PATCH] Make sprite texture atlas more generic --- .../lyra-game/src/sprite/animation_sheet.rs | 2 +- crates/lyra-game/src/sprite/texture_atlas.rs | 85 ++++++------------- examples/2d/src/main.rs | 54 +++++++----- 3 files changed, 63 insertions(+), 78 deletions(-) diff --git a/crates/lyra-game/src/sprite/animation_sheet.rs b/crates/lyra-game/src/sprite/animation_sheet.rs index 97b5385..2eab8e3 100644 --- a/crates/lyra-game/src/sprite/animation_sheet.rs +++ b/crates/lyra-game/src/sprite/animation_sheet.rs @@ -43,7 +43,7 @@ impl SpriteAnimation { let mut frames = vec![]; //Vec::with_capacity(sprites.len()); for i in sprites { - let r = atlas.index_rect(i); + let r = atlas.frames.get(i as usize).cloned().unwrap(); frames.push(r); } diff --git a/crates/lyra-game/src/sprite/texture_atlas.rs b/crates/lyra-game/src/sprite/texture_atlas.rs index 6143ec3..39015e9 100644 --- a/crates/lyra-game/src/sprite/texture_atlas.rs +++ b/crates/lyra-game/src/sprite/texture_atlas.rs @@ -1,72 +1,43 @@ -use glam::{UVec2, Vec3}; +use glam::UVec2; use lyra_ecs::Component; use lyra_math::URect; use lyra_reflect::Reflect; use lyra_resource::ResHandle; -use super::Pivot; - /// A texture atlas of multiple sprites. #[derive(Clone, Component, Reflect)] pub struct TextureAtlas { pub texture: ResHandle, - /// The coordinates in the texture where the grid starts. - pub grid_offset: UVec2, - /// The size of the grid in cells. - pub grid_size: UVec2, - /// The size of each cell. - pub cell_size: UVec2, - - pub sprite_color: Vec3, - pub pivot: Pivot, + pub frames: Vec, } impl TextureAtlas { - /// The cell x and y in the grid of a specific index. - pub fn index_cell(&self, i: u32) -> UVec2 { - let x = i % self.grid_size.x; - let y = i / self.grid_size.x; - UVec2 { x, y } - } - - /// The coords of the cell at x and y in the grid. + /// Create a texture atlas with rectangles of a grid. /// - /// The indices are different then the image coords, this is the position in the grid. - /// So if you have a 9x7 grid, and wanted to get the 1nd cell on the 2nd row, you'd - /// use the values `x = 0, y = 1` (indices start at zero like arrays). - #[inline(always)] - pub fn cell_coords(&self, x: u32, y: u32) -> UVec2 { - UVec2 { - x: x * self.cell_size.x, - y: y * self.cell_size.y, + /// Parameters: + /// * `texture` - The asset handle of the texture to get the sprites from. + /// * `grid_size` - The number of the cells in the grid (i.e., 9x7 grid). + /// * `cell_size` - The dimensions of each cell in the grid (i.e., 100x100 sprites). + pub fn from_grid( + texture: ResHandle, + grid_size: UVec2, + cell_size: UVec2, + ) -> Self { + let mut frames = vec![]; + + for y in 0..grid_size.y { + for x in 0..grid_size.x { + let r = URect::new( + cell_size.x * x, + cell_size.y * y, + cell_size.x * (x + 1), + cell_size.y * (y + 1), + ); + frames.push(r); + } } - } - /// The coords of the cell at an index. - #[inline(always)] - pub fn index_coords(&self, i: u32) -> UVec2 { - let cell = self.index_cell(i); - - self.cell_coords(cell.x, cell.y) - } - - /// The rectangle of the cell at the x and y indices in the grid. - /// - /// The indices are different then the image coords, this is the position in the grid. - /// So if you have a 9x7 grid, and wanted to get the 1nd cell on the 2nd row, you'd - /// use the values `x = 0, y = 1` (indices start at zero like arrays). - #[inline(always)] - pub fn cell_rect(&self, x: u32, y: u32) -> URect { - let start = self.cell_coords(x, y); - let end = start + self.cell_size; - URect { min: start, max: end } - } - - /// The rectangle of the cell at an index. - #[inline(always)] - pub fn index_rect(&self, i: u32) -> URect { - let cell = self.index_cell(i); - self.cell_rect(cell.x, cell.y) + Self { texture, frames } } } @@ -95,11 +66,11 @@ impl AtlasSprite { #[inline(always)] pub fn from_atlas_index(atlas: ResHandle, i: u32) -> Self { let a = atlas.data_ref().unwrap(); - let rect = a.index_rect(i); + let rect = a.frames.get(i as usize).cloned().unwrap(); //index_rect(i); Self { atlas: atlas.clone(), - sprite: rect, + sprite: rect, } } -} \ No newline at end of file +} diff --git a/examples/2d/src/main.rs b/examples/2d/src/main.rs index cc40c29..d0aaaf4 100644 --- a/examples/2d/src/main.rs +++ b/examples/2d/src/main.rs @@ -1,10 +1,22 @@ use lyra_engine::{ - assets::{Image, ResourceManager}, ecs::query::{Res, ResMut, View}, game::App, gltf::Gltf, input::{ + assets::{Image, ResourceManager}, + ecs::query::{Res, ResMut, View}, + game::App, + gltf::Gltf, + input::{ Action, ActionHandler, ActionKind, ActionMapping, ActionMappingId, ActionSource, InputActionPlugin, KeyCode, LayoutId, - }, math::{self, Rect, Transform, URect, UVec2, Vec2, Vec3}, render::light::directional::DirectionalLight, scene::{ - system_update_world_transforms, Camera2dBundle, CameraProjection, OrthographicProjection, ScaleMode, TopDown2dCamera, TopDown2dCameraPlugin, WorldTransform, ACTLBL_LOOK_LEFT_RIGHT, ACTLBL_LOOK_ROLL, ACTLBL_LOOK_UP_DOWN, ACTLBL_MOVE_FORWARD_BACKWARD, ACTLBL_MOVE_LEFT_RIGHT, ACTLBL_MOVE_UP_DOWN - }, sprite::{self, AtlasAnimations, AtlasSprite, Pivot, Sprite, SpriteAnimation, TextureAtlas}, DeltaTime + }, + math::{self, Rect, Transform, URect, UVec2, Vec2, Vec3}, + render::light::directional::DirectionalLight, + scene::{ + system_update_world_transforms, Camera2dBundle, CameraProjection, OrthographicProjection, + ScaleMode, TopDown2dCamera, TopDown2dCameraPlugin, WorldTransform, ACTLBL_LOOK_LEFT_RIGHT, + ACTLBL_LOOK_ROLL, ACTLBL_LOOK_UP_DOWN, ACTLBL_MOVE_FORWARD_BACKWARD, + ACTLBL_MOVE_LEFT_RIGHT, ACTLBL_MOVE_UP_DOWN, + }, + sprite::{self, AtlasAnimations, AtlasSprite, Pivot, Sprite, SpriteAnimation, TextureAtlas}, + DeltaTime, }; use tracing::debug; @@ -96,7 +108,11 @@ async fn main() { fn setup_scene_plugin(app: &mut App) { //app.add_resource(Timer(0.0)); //app.with_system("sprite_change", sprite_change, &[]); - app.with_system("sprite_atlas_animation", sprite::system_sprite_atlas_animation, &[]); + app.with_system( + "sprite_atlas_animation", + sprite::system_sprite_atlas_animation, + &[], + ); let world = &mut app.world; let resman = world.get_resource_mut::().unwrap(); @@ -125,21 +141,19 @@ fn setup_scene_plugin(app: &mut App) { let image = resman.request::("../assets/Egg_item.png").unwrap(); image.wait_recurse_dependencies_load().unwrap(); - let soldier = resman.request::("../assets/tiny_rpg_characters/Characters(100x100)/Soldier/Soldier/Soldier.png").unwrap(); + let soldier = resman + .request::( + "../assets/tiny_rpg_characters/Characters(100x100)/Soldier/Soldier/Soldier.png", + ) + .unwrap(); soldier.wait_recurse_dependencies_load().unwrap(); - let atlas = resman.store_new(TextureAtlas { - texture: soldier, - grid_offset: UVec2::ZERO, - grid_size: UVec2::new(9, 7), - cell_size: UVec2::new(100, 100), - sprite_color: Vec3::ONE, - pivot: Pivot::default(), - }); - - let animations = AtlasAnimations::new(atlas, &[ - ("soldier_run", 0.1, 9..=16), - ]); + let atlas = resman.store_new(TextureAtlas::from_grid( + soldier, + UVec2::new(9, 7), + UVec2::new(100, 100), + )); + let animations = AtlasAnimations::new(atlas, &[("soldier_run", 0.1, 9..=16)]); let run_anim = animations.get_active("soldier_run"); let animations = resman.store_new(animations); @@ -180,6 +194,6 @@ fn setup_scene_plugin(app: &mut App) { zoom_speed: Some(0.2), speed: 14.0, ..Default::default() - } + }, )); -} \ No newline at end of file +}