use image::io::Reader as ImageReader; use sdl2::{ rect::Rect, render::{Texture, TextureCreator}, video::WindowContext, }; use std::collections::HashMap; /// A handle for a sprite inside a SpriteAtlas pub struct Sprite<'a> { pub texture: &'a Texture<'a>, pub rect: Rect, } /// A cache of textures we use when drawing the screen. /// /// This is implemented very carefully, since SDL2 textures have tricky lifetimes. pub struct SpriteAtlas<'a> { data: HashMap, Rect)>, } impl<'a> SpriteAtlas<'a> { pub fn new(texture_creator: &'a TextureCreator) -> Result { let mut b = Self { data: HashMap::new(), }; b.load_one(texture_creator, "gypsum.png")?; b.load_one(texture_creator, "a0.png")?; b.load_one(texture_creator, "small.png")?; b.load_one(texture_creator, "earth.png")?; return Ok(b); } pub fn get(&'a self, name: &str) -> Sprite<'a> { let (texture, rect) = self.data.get(name).unwrap(); return Sprite { texture, rect: rect.clone(), }; } fn load_one( &mut self, texture_creator: &'a TextureCreator, s: &str, ) -> Result<(), String> { let im = ImageReader::open(format!("assets/{s}")) .unwrap() .decode() .unwrap(); let width = im.width(); let height = im.height(); let mut im = im.as_bytes().to_vec(); let surface = sdl2::surface::Surface::from_data( &mut im, width, height, width * 4, sdl2::pixels::PixelFormatEnum::RGBA32, )?; let texture = texture_creator .create_texture_from_surface(&surface) .map_err(|e| e.to_string())?; self.data .insert(s.to_owned(), (texture, Rect::new(0, 0, width, height))); return Ok(()); } }