use std::collections::HashMap; use std::ops::{Add, AddAssign, Mul, Sub, SubAssign}; use std::path::Path; use crate::agnostic_interface::{ FontInterface, GameInterface, ImageInterface, MusicInterface, SoundInterface, }; #[derive(Copy, Clone, Debug, PartialEq, Eq)] pub struct Color { pub r: u8, pub g: u8, pub b: u8, pub a: u8, } impl Default for Color { fn default() -> Self { Self::WHITE } } impl Color { pub const WHITE: Self = Self { r: 255, g: 255, b: 255, a: 255, }; pub const BLACK: Self = Self { r: 0, g: 0, b: 0, a: 255, }; pub const GREEN: Self = Self { r: 0, g: 255, b: 0, a: 255, }; pub fn from_rgba(r: u8, g: u8, b: u8, a: u8) -> Self { Self { r, g, b, a } } pub fn deserialize(data: &[u8], offset: usize) -> Result<(Color, usize), ()> { if data.len() < offset + 4 { Err(()) } else { let mut color = Color::WHITE; color.r = data[offset]; color.g = data[offset + 1]; color.b = data[offset + 2]; color.a = data[offset + 3]; Ok((color, 4)) } } pub fn serialize(&self) -> Vec { vec![self.r, self.g, self.b, self.a] } } #[derive(Copy, Clone, Debug, PartialEq)] pub struct Rectangle { pub x: f32, pub y: f32, pub w: f32, pub h: f32, } impl Rectangle { pub fn new(x: f32, y: f32, w: f32, h: f32) -> Self { Self { x, y, w, h } } pub fn pos_add_vec(&mut self, v: Vector) { self.x += v.x; self.y += v.y; } pub fn deserialize(data: &[u8], offset: usize) -> Result<(Rectangle, usize), ()> { if data.len() < offset + std::mem::size_of::() * 4 { return Err(()); } let mut idx: usize = 0; let mut rect = Rectangle::new(0.0, 0.0, 0.0, 0.0); rect.x = f32::from_be_bytes( data[(offset + idx)..(offset + idx + std::mem::size_of::())] .try_into() .map_err(|_| ())?, ); idx += std::mem::size_of::(); rect.y = f32::from_be_bytes( data[(offset + idx)..(offset + idx + std::mem::size_of::())] .try_into() .map_err(|_| ())?, ); idx += std::mem::size_of::(); rect.w = f32::from_be_bytes( data[(offset + idx)..(offset + idx + std::mem::size_of::())] .try_into() .map_err(|_| ())?, ); idx += std::mem::size_of::(); rect.h = f32::from_be_bytes( data[(offset + idx)..(offset + idx + std::mem::size_of::())] .try_into() .map_err(|_| ())?, ); idx += std::mem::size_of::(); Ok((rect, idx)) } pub fn serialize(&self) -> Vec { let mut bytes = Vec::new(); for byte in self.x.to_be_bytes() { bytes.push(byte); } for byte in self.y.to_be_bytes() { bytes.push(byte); } for byte in self.w.to_be_bytes() { bytes.push(byte); } for byte in self.h.to_be_bytes() { bytes.push(byte); } bytes } } impl Default for Rectangle { fn default() -> Self { Self { x: 0.0, y: 0.0, w: 1.0, h: 1.0, } } } #[derive(Copy, Clone, Debug, PartialEq)] pub struct Circle { pub x: f32, pub y: f32, pub r: f32, } impl Default for Circle { fn default() -> Self { Self { x: 0.0, y: 0.0, r: 1.0, } } } impl Circle { pub fn new(x: f32, y: f32, r: f32) -> Self { Self { x, y, r } } pub fn pos_add_vec(&mut self, v: Vector) { self.x += v.x; self.y += v.y; } pub fn deserialize(data: &[u8], offset: usize) -> Result<(Circle, usize), ()> { if data.len() < 12 + offset { return Err(()); } let mut idx: usize = 0; let mut circle = Circle::new(0.0, 0.0, 1.0); circle.x = f32::from_be_bytes( data[(offset + idx)..(offset + idx + std::mem::size_of::())] .try_into() .map_err(|_| ())?, ); idx += std::mem::size_of::(); circle.y = f32::from_be_bytes( data[(offset + idx)..(offset + idx + std::mem::size_of::())] .try_into() .map_err(|_| ())?, ); idx += std::mem::size_of::(); circle.r = f32::from_be_bytes( data[(offset + idx)..(offset + idx + std::mem::size_of::())] .try_into() .map_err(|_| ())?, ); idx += std::mem::size_of::(); Ok((circle, idx)) } pub fn serialize(&self) -> Vec { let mut bytes = Vec::new(); for byte in self.x.to_be_bytes() { bytes.push(byte); } for byte in self.y.to_be_bytes() { bytes.push(byte); } for byte in self.r.to_be_bytes() { bytes.push(byte); } bytes } } #[derive(Copy, Clone, Debug, PartialEq)] pub struct Vector { pub x: f32, pub y: f32, } impl Default for Vector { fn default() -> Self { Self { x: 1.0, y: 1.0 } } } impl Add for Vector { type Output = Vector; fn add(self, rhs: Vector) -> Self::Output { Vector { x: self.x + rhs.x, y: self.y + rhs.y, } } } impl Sub for Vector { type Output = Vector; fn sub(self, rhs: Vector) -> Self::Output { Vector { x: self.x - rhs.x, y: self.y - rhs.y, } } } impl AddAssign for Vector { fn add_assign(&mut self, rhs: Vector) { self.x += rhs.x; self.y += rhs.y; } } impl SubAssign for Vector { fn sub_assign(&mut self, rhs: Vector) { self.x -= rhs.x; self.y -= rhs.y; } } impl Mul for Vector { type Output = Vector; fn mul(self, rhs: f32) -> Self::Output { Vector { x: self.x * rhs, y: self.y * rhs, } } } impl Vector { pub fn new(x: f32, y: f32) -> Self { Self { x, y } } pub fn deserialize(data: &[u8], offset: usize) -> Result<(Vector, usize), ()> { let mut idx: usize = 0; let mut vector = Vector::new(0.0, 0.0); if data.len() < offset + idx + std::mem::size_of::() { return Err(()); } vector.x = f32::from_be_bytes( data[(offset + idx)..(offset + idx + std::mem::size_of::())] .try_into() .map_err(|_| ())?, ); idx += std::mem::size_of::(); vector.y = f32::from_be_bytes( data[(offset + idx)..(offset + idx + std::mem::size_of::())] .try_into() .map_err(|_| ())?, ); idx += std::mem::size_of::(); Ok((vector, idx)) } pub fn serialize(&self) -> Vec { let mut bytes = Vec::new(); for byte in self.x.to_be_bytes() { bytes.push(byte); } for byte in self.y.to_be_bytes() { bytes.push(byte); } bytes } } impl From<(f32, f32)> for Vector { fn from(t: (f32, f32)) -> Self { Self { x: t.0, y: t.1 } } } #[derive(Copy, Clone, Debug, PartialEq)] pub struct Transform { pub mat: [f32; 9], } impl Default for Transform { fn default() -> Self { Self { mat: [1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0], } } } impl Mul for Transform { type Output = Vector; fn mul(self, rhs: Vector) -> Self::Output { Vector { x: rhs.x * self.mat[0] + rhs.y * self.mat[1] + self.mat[2], y: rhs.x * self.mat[3] + rhs.y * self.mat[4] + self.mat[5], } } } impl Mul for Transform { type Output = Transform; fn mul(self, rhs: Transform) -> Self::Output { Self { mat: [ self.mat[0] * rhs.mat[0] + self.mat[1] * rhs.mat[3] + self.mat[2] * rhs.mat[6], self.mat[0] * rhs.mat[1] + self.mat[1] * rhs.mat[4] + self.mat[2] * rhs.mat[7], self.mat[0] * rhs.mat[2] + self.mat[1] * rhs.mat[5] + self.mat[2] * rhs.mat[8], self.mat[3] * rhs.mat[0] + self.mat[4] * rhs.mat[3] + self.mat[5] * rhs.mat[6], self.mat[3] * rhs.mat[1] + self.mat[4] * rhs.mat[4] + self.mat[5] * rhs.mat[7], self.mat[3] * rhs.mat[2] + self.mat[4] * rhs.mat[5] + self.mat[5] * rhs.mat[8], self.mat[6] * rhs.mat[0] + self.mat[7] * rhs.mat[3] + self.mat[8] * rhs.mat[6], self.mat[6] * rhs.mat[1] + self.mat[7] * rhs.mat[4] + self.mat[8] * rhs.mat[7], self.mat[6] * rhs.mat[2] + self.mat[7] * rhs.mat[5] + self.mat[8] * rhs.mat[8], ], } } } impl Transform { pub const IDENTITY: Self = Self { mat: [1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0], }; pub fn rotate(rot: f32) -> Self { Self { mat: [ rot.cos(), -rot.sin(), 0.0, rot.sin(), rot.cos(), 0.0, 0.0, 0.0, 1.0, ], } } pub fn translate(x: f32, y: f32) -> Self { Self { mat: [1.0, 0.0, x, 0.0, 1.0, y, 0.0, 0.0, 1.0], } } } pub struct Window { gi: Box, images: HashMap>, fonts: HashMap>, sounds: HashMap>, music: HashMap>, } impl Window { pub fn new(gi: Box) -> Self { Self { gi, images: HashMap::new(), fonts: HashMap::new(), sounds: HashMap::new(), music: HashMap::new(), } } pub fn get_gi(&self) -> &dyn GameInterface { self.gi.as_ref() } pub fn get_gi_mut(&mut self) -> &mut dyn GameInterface { self.gi.as_mut() } pub fn load_image(&mut self, path: &Path, name: String) -> Result<(), String> { self.images.insert(name, self.gi.load_image(path)?); Ok(()) } pub fn load_font(&mut self, path: &Path, name: String) -> Result<(), String> { self.fonts.insert(name, self.gi.load_font(path)?); Ok(()) } pub fn load_sound(&mut self, path: &Path, name: String) -> Result<(), String> { self.sounds.insert(name, self.gi.load_sound(path)?); Ok(()) } pub fn load_music(&mut self, path: &Path, name: String) -> Result<(), String> { self.music.insert(name, self.gi.load_music(path)?); Ok(()) } pub fn get_image(&self, name: &str) -> Result<&dyn ImageInterface, String> { Ok(self .images .get(name) .ok_or_else(|| format!("Image \"{name}\" not found"))? .as_ref()) } pub fn get_image_mut(&mut self, name: &str) -> Result<&mut dyn ImageInterface, String> { Ok(self .images .get_mut(name) .ok_or_else(|| format!("Image \"{name}\" not found"))? .as_mut()) } pub fn get_font(&self, name: &str) -> Result<&dyn FontInterface, String> { Ok(self .fonts .get(name) .ok_or_else(|| format!("Font \"{name}\" not found"))? .as_ref()) } pub fn get_font_mut(&mut self, name: &str) -> Result<&mut dyn FontInterface, String> { Ok(self .fonts .get_mut(name) .ok_or_else(|| format!("Font \"{name}\" not found"))? .as_mut()) } pub fn get_sound(&self, name: &str) -> Result<&dyn SoundInterface, String> { Ok(self .sounds .get(name) .ok_or_else(|| format!("Sound \"{name}\" not found"))? .as_ref()) } pub fn get_sound_mut(&mut self, name: &str) -> Result<&mut dyn SoundInterface, String> { Ok(self .sounds .get_mut(name) .ok_or_else(|| format!("Sound \"{name}\" not found"))? .as_mut()) } pub fn get_music(&self, name: &str) -> Result<&dyn MusicInterface, String> { Ok(self .music .get(name) .ok_or_else(|| format!("Music \"{name}\" not found"))? .as_ref()) } pub fn get_music_mut(&mut self, name: &str) -> Result<&mut dyn MusicInterface, String> { Ok(self .music .get_mut(name) .ok_or_else(|| format!("Music \"{name}\" not found"))? .as_mut()) } pub fn update_music(&mut self) -> Result<(), String> { for music in self.music.values_mut() { music.update()?; } Ok(()) } } #[cfg(test)] mod tests { use super::*; #[test] fn test_de_serialize_color() { let color = Color::from_rgba(1, 2, 3, 4); let bytes = color.serialize(); let (des_color, size) = Color::deserialize(&bytes, 0).expect("Should be able to deserialize Color!"); assert_eq!(color, des_color); assert_eq!(bytes.len(), size); } #[test] fn test_de_serialize_rectangle() { let rect = Rectangle::new(1.0, 2.0, 3.0, 4.0); let bytes = rect.serialize(); let (des_rect, size) = Rectangle::deserialize(&bytes, 0).expect("Should be able to deserialize Rectangle!"); assert_eq!(rect, des_rect); assert_eq!(bytes.len(), size); } #[test] fn test_de_serialize_circle() { let circle = Circle::new(1.0, 2.0, 3.0); let bytes = circle.serialize(); let (des_circle, size) = Circle::deserialize(&bytes, 0).expect("Should be able to deserialize Circle!"); assert_eq!(circle, des_circle); assert_eq!(bytes.len(), size); } #[test] fn test_de_serialize_vector() { let vect = Vector::new(1.0, 2.0); let bytes = vect.serialize(); let (des_vect, size) = Vector::deserialize(&bytes, 0).expect("Should be able to deserialize Vector!"); assert_eq!(vect, des_vect); assert_eq!(bytes.len(), size); } }