use crate::Textures; use super::tile::*; use raylib::prelude::*; #[derive(Debug, Default, Clone, Copy, PartialEq)] pub struct Pos { pub x: isize, pub y: isize, } impl Pos { pub const fn to_vec(self) -> Vector2 { Vector2 { x: self.x as f32, y: self.y as f32, } } } impl From<(usize, usize)> for Pos { fn from(value: (usize, usize)) -> Self { Self { x: value.0 as isize, y: value.1 as isize, } } } impl From for Pos { fn from(vec: Vector2) -> Self { Self { x: vec.x as isize, y: vec.y as isize, } } } #[derive(Debug, Clone)] pub struct Board { rows: Vec>, width: usize, height: usize, } impl Board { pub fn parse(source: &str) -> Self { let mut rows = Vec::new(); let mut width = 0; for line in source.lines() { width = width.max(line.len()); let mut tiles = Vec::new(); for char in line.chars() { tiles.push(Tile::from_char(char)); } rows.push(tiles); } for line in &mut rows { line.resize(width, Tile::Blank); } Board::new(rows) } pub fn to_string(&self) -> String { let mut out = String::new(); for row in &self.rows { for tile in row { out.push(tile.to_char()) } out.push('\n'); } out } pub fn new_empty(width: usize, height: usize) -> Self { let rows = vec![vec![Tile::Blank; width]; height]; Self { rows, width, height, } } pub fn new(rows: Vec>) -> Self { Self { width: rows[0].len(), height: rows.len(), rows, } } pub fn count_tiles(&self) -> usize { let mut sum = 0; for row in &self.rows { for tile in row { match tile { Tile::Blank | Tile::Block => (), _ => sum += 1, } } } sum } pub fn in_bounds(&self, p: Pos) -> bool { p.x >= 0 && p.y >= 0 && p.x < self.width as isize && p.y < self.height as isize } pub fn get(&self, p: Pos) -> Option { if self.in_bounds(p) { Some(self.rows[p.y as usize][p.x as usize]) } else { None } } pub fn get_or_blank(&self, p: Pos) -> Tile { if self.in_bounds(p) { self.rows[p.y as usize][p.x as usize] } else { Tile::default() } } pub fn get_mut(&mut self, p: Pos) -> Option<&mut Tile> { if self.in_bounds(p) { Some(&mut self.rows[p.y as usize][p.x as usize]) } else { None } } pub fn get_blank_mut(&mut self, p: Pos) -> Option<&mut Tile> { if self.in_bounds(p) { let tile = &mut self.rows[p.y as usize][p.x as usize]; if tile == &Tile::Blank { return Some(tile); } } None } pub fn set(&mut self, p: Pos, tile: Tile) { if self.in_bounds(p) { self.rows[p.y as usize][p.x as usize] = tile; } } pub fn width(&self) -> usize { self.width } pub fn height(&self) -> usize { self.height } pub fn draw(&self, d: &mut RaylibDrawHandle, textures: &Textures, offset: Vector2, zoom: i32) { let tile_size = 16 << zoom; for x in 0..self.width { for y in 0..self.height { if let Some(tile) = self.get((x, y).into()) { let px = x as i32 * tile_size + offset.x as i32 + tile_size / 2; let py = y as i32 * tile_size + offset.y as i32 + tile_size / 2; let texture = textures.get(&tile.texture()); d.draw_texture_ex( texture, Vector2::new((px - tile_size / 2) as f32, (py - tile_size / 2) as f32), 0.0, (1 << zoom) as f32, Color::WHITE, ); } } } } }