use std::time::Duration; use std::ops::{Index, IndexMut}; use serde::{Serialize, Deserialize}; /// Clamp a number between two boundaries. pub fn clamp(number: f32, min: f32, max: f32) -> f32 { if number < min { min } else if number > max { max } else { number } } /// Converts a duration into an animation frame number. pub fn duration_as_frame(duration: &Duration, total: usize) -> i32 { let secs = duration_as_f32(duration); (secs * 4.0) as i32 % total as i32 } /// Converts a duration into its number of seconds. pub fn duration_as_f32(duration: &Duration) -> f32 { duration.as_secs() as f32 + duration.subsec_nanos() as f32 / 1_000_000_000.0 } /// A generic matrix type, useful for levels. #[derive(Serialize, Deserialize, Clone)] pub struct Matrix { /// The number of rows of the matrix. rows: usize, /// The number of cols of the matrix. cols: usize, /// The contained data in the matrix. data: Vec, } impl Matrix where T: Clone, { /// Creates a matrix from an element and duplicates it. pub fn from_size(rows: usize, cols: usize, element: T) -> Matrix { Matrix { rows, cols, data: vec![element; rows * cols], } } } impl Matrix { /// Converts an a pair corresponding to the row and columns into an integer. pub fn to_usize(&self, (row, col): (usize, usize)) -> usize { self.rows * col + row } /// Returns the number of rows. pub fn rows(&self) -> usize { self.rows } /// Returns the number of columns. pub fn cols(&self) -> usize { self.cols } /// Returns the tile if any, none otherwise. pub fn get(&self, (row, col): (usize, usize)) -> Option<&T> { if row < self.rows && col < self.cols { Some(&self[(row, col)]) } else { None } } /// Returns the tile if any, none otherwise. pub fn get_isize(&self, row: isize, col: isize) -> Option<&T> { if row >= 0 && col >= 0 && (row as usize) < self.rows && (col as usize) < self.cols { Some(&self[(row as usize, col as usize)]) } else { None } } /// Returns a mutable reference to the tile if any. pub fn get_mut(&mut self, (row, col): (usize, usize)) -> Option<&mut T> { if row < self.rows && col < self.cols { Some(&mut self[(row, col)]) } else { None } } } impl Index<(usize, usize)> for Matrix { type Output = T; fn index(&self, index: (usize, usize)) -> &T { let index = self.to_usize(index); &self.data[index] } } impl IndexMut<(usize, usize)> for Matrix { fn index_mut(&mut self, index: (usize, usize)) -> &mut T { let index = self.to_usize(index); &mut self.data[index] } }