diff --git a/src/config.rs b/src/config.rs index 677d10b..d71b79c 100644 --- a/src/config.rs +++ b/src/config.rs @@ -34,4 +34,4 @@ pub const RES_PATH: &str = "res"; pub const RES_PATH: &str = "/usr/games/septadrop"; pub const RES_AUDIO_PATH: &str = formatcp!("{RES_PATH}/audio"); -pub const RES_TEXTURES_PATH: &str = formatcp!("{RES_PATH}/textures"); \ No newline at end of file +pub const RES_TEXTURES_PATH: &str = formatcp!("{RES_PATH}/textures"); diff --git a/src/main.rs b/src/main.rs index f9861fe..cc9eedf 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,9 +1,9 @@ +use gcd::Gcd; +use rand::seq::SliceRandom; +use sfml::audio::*; use sfml::graphics::*; -use sfml::window::*; use sfml::system::*; -use sfml::audio::*; -use rand::seq::SliceRandom; -use gcd::Gcd; +use sfml::window::*; use std::io::Write; mod structs; @@ -35,27 +35,31 @@ fn main() { VideoMode::new(WINDOW_WIDTH, WINDOW_HEIGHT, 16), "septadrop", Style::TITLEBAR | Style::CLOSE, - &context_settings + &context_settings, ); window.set_framerate_limit(FPS); window.set_key_repeat_enabled(false); let icon = Image::from_file(&texture("icon")).unwrap(); { - let Vector2u { x: width, y: height } = icon.size(); + let Vector2u { + x: width, + y: height, + } = icon.size(); window.set_icon(width, height, icon.pixel_data()); } let mut thread_rng = rand::thread_rng(); let block_types = BlockType::init_list(); - + let mut random_block = || Block::new(block_types.choose(&mut thread_rng).unwrap()); - + let mut block = random_block(); let mut next_block = random_block(); // Default::default() initializes all array cells to None (no block) - let mut grid: [[Option<&TileType>; GRID_WIDTH as usize]; GRID_HEIGHT as usize] = Default::default(); + let mut grid: [[Option<&TileType>; GRID_WIDTH as usize]; GRID_HEIGHT as usize] = + Default::default(); let blocks_texture = Texture::from_file(&texture("blocks")).unwrap(); let mut sprite = Sprite::with_texture(&blocks_texture); @@ -73,8 +77,10 @@ fn main() { let mut paused_text = Sprite::with_texture(&paused_texture); let paused_texture_size = paused_texture.size(); paused_text.set_position(Vector2f::new( - PLAYFIELD_X as f32 + (GRID_WIDTH as f32 * TILE_SIZE as f32 / 2.0) - paused_texture_size.x as f32 / 2.0, - PLAYFIELD_Y as f32 + (GRID_HEIGHT as f32 * TILE_SIZE as f32 / 2.0) - paused_texture_size.y as f32 / 2.0 + PLAYFIELD_X as f32 + (GRID_WIDTH as f32 * TILE_SIZE as f32 / 2.0) + - paused_texture_size.x as f32 / 2.0, + PLAYFIELD_Y as f32 + (GRID_HEIGHT as f32 * TILE_SIZE as f32 / 2.0) + - paused_texture_size.y as f32 / 2.0, )); paused_text }; @@ -84,7 +90,11 @@ fn main() { let mut highscore: u32; if highscore_file_path.exists() { - highscore = std::fs::read_to_string(&highscore_file_path).unwrap().trim().parse::().unwrap(); + highscore = std::fs::read_to_string(&highscore_file_path) + .unwrap() + .trim() + .parse::() + .unwrap(); let point_gcd = POINTS_1_LINE .gcd(POINTS_2_LINES) .gcd(POINTS_3_LINES) @@ -152,48 +162,56 @@ fn main() { Event::Closed => { window.close(); break; - }, + } Event::GainedFocus => { if paused && paused_from_lost_focus { toggle_pause = true; } - }, + } Event::LostFocus => { if !paused { toggle_pause = true; paused_from_lost_focus = true; } - }, - Event::KeyPressed { code, alt: _, ctrl: _, shift: _, system: _ } => { - match code { - Key::ESCAPE => toggle_pause = true, - Key::SPACE => snap = !paused, - Key::UP => rotate = !paused, - Key::DOWN => fast_forward = !paused, - Key::LEFT => { - move_left = !paused; - move_left_immediate = !paused; - move_clock.restart(); - }, - Key::RIGHT => { - move_right = !paused; - move_right_immediate = !paused; - move_clock.restart(); - } - _ => {} + } + Event::KeyPressed { + code, + alt: _, + ctrl: _, + shift: _, + system: _, + } => match code { + Key::ESCAPE => toggle_pause = true, + Key::SPACE => snap = !paused, + Key::UP => rotate = !paused, + Key::DOWN => fast_forward = !paused, + Key::LEFT => { + move_left = !paused; + move_left_immediate = !paused; + move_clock.restart(); } - }, - Event::KeyReleased { code, alt: _, ctrl: _, shift: _, system: _ } => { - match code { - Key::DOWN => fast_forward = false, - Key::LEFT => move_left = false, - Key::RIGHT => move_right = false, - _ => {} + Key::RIGHT => { + move_right = !paused; + move_right_immediate = !paused; + move_clock.restart(); } - } - _ => {}, + _ => {} + }, + Event::KeyReleased { + code, + alt: _, + ctrl: _, + shift: _, + system: _, + } => match code { + Key::DOWN => fast_forward = false, + Key::LEFT => move_left = false, + Key::RIGHT => move_right = false, + _ => {} + }, + _ => {} }, - None => break + None => break, } } @@ -201,23 +219,17 @@ fn main() { paused = !paused; if paused { pause_clock.restart(); - paused_clear.set_position(Vector2f::new( - PLAYFIELD_X as f32, - PLAYFIELD_Y as f32 - )); + paused_clear.set_position(Vector2f::new(PLAYFIELD_X as f32, PLAYFIELD_Y as f32)); paused_clear.set_size(Vector2f::new( (GRID_WIDTH * TILE_SIZE) as f32, - (GRID_HEIGHT * TILE_SIZE) as f32 + (GRID_HEIGHT * TILE_SIZE) as f32, )); window.draw(&paused_clear); let size = Vector2f::new( (NEXT_WIDTH * TILE_SIZE) as f32, - (NEXT_HEIGHT * TILE_SIZE) as f32 + (NEXT_HEIGHT * TILE_SIZE) as f32, ); - paused_clear.set_position(Vector2f::new( - NEXT_X as f32, - NEXT_Y as f32 - ) - size / 2.0); + paused_clear.set_position(Vector2f::new(NEXT_X as f32, NEXT_Y as f32) - size / 2.0); paused_clear.set_size(size); window.draw(&paused_clear); window.draw(&paused_text); @@ -235,9 +247,8 @@ fn main() { continue; } - let is_update_frame = - update_clock.elapsed_time().as_milliseconds() - pause_offset as i32 > - if fast_forward { + let is_update_frame = update_clock.elapsed_time().as_milliseconds() - pause_offset as i32 + > if fast_forward { std::cmp::min(update_interval, MAX_FAST_FORWARD_INTERVAL) } else { update_interval @@ -245,10 +256,9 @@ fn main() { if is_update_frame { update_clock.restart(); } - - let is_move_frame = - move_clock.elapsed_time().as_milliseconds() - pause_offset as i32 > - MOVE_FRAME_INTERVAL as i32; + + let is_move_frame = move_clock.elapsed_time().as_milliseconds() - pause_offset as i32 + > MOVE_FRAME_INTERVAL as i32; if is_move_frame { move_clock.restart(); } @@ -296,7 +306,10 @@ fn main() { } if movement != 0 { for (i, tile) in block.get_tiles().iter().enumerate().rev() { - if tile.x + movement < 0 || tile.x + movement >= GRID_WIDTH as i32 || grid[tile.y as usize][(tile.x + movement) as usize].is_some() { + if tile.x + movement < 0 + || tile.x + movement >= GRID_WIDTH as i32 + || grid[tile.y as usize][(tile.x + movement) as usize].is_some() + { break; } if i == 0 { @@ -335,9 +348,12 @@ fn main() { block.position.y += snap_offset; snap = false; snap_sound.play(); - } else if is_update_frame { // Land checking + } else if is_update_frame { + // Land checking for tile in block.get_tiles().iter() { - if tile.y == GRID_HEIGHT as i32 - 1 || grid[tile.y as usize + 1][tile.x as usize].is_some() { + if tile.y == GRID_HEIGHT as i32 - 1 + || grid[tile.y as usize + 1][tile.x as usize].is_some() + { landed = true; break; } @@ -345,10 +361,10 @@ fn main() { } let landed = landed; // remove mutability - // Clear window - // Normally, one would run window.clear(), - // but the background image covers the entire window. - window.draw(&background); + // Clear window + // Normally, one would run window.clear(), + // but the background image covers the entire window. + window.draw(&background); // Draw block if !landed { @@ -357,13 +373,13 @@ fn main() { sprite.set_texture_rect(&block.block_type.tile_type.texture_rect); sprite.set_position(Vector2f::new( (PLAYFIELD_X as i32 + tile.x * TILE_SIZE as i32) as f32, - (PLAYFIELD_Y as i32 + tile.y * TILE_SIZE as i32) as f32 + (PLAYFIELD_Y as i32 + tile.y * TILE_SIZE as i32) as f32, )); window.draw(&sprite); sprite.set_texture_rect(&block.block_type.tile_type.ghost_texture_rect); sprite.set_position(Vector2f::new( (PLAYFIELD_X as i32 + tile.x * TILE_SIZE as i32) as f32, - (PLAYFIELD_Y as i32 + snap_y * TILE_SIZE as i32) as f32 + (PLAYFIELD_Y as i32 + snap_y * TILE_SIZE as i32) as f32, )); window.draw(&sprite); } @@ -375,12 +391,16 @@ fn main() { // This is assuming the next block spawns unrotated. // Refactoring is needed if random rotations are added let x_offset = next_block.block_type.width * TILE_SIZE / 2; - let y_offset = (next_block.block_type.height + next_block.block_type.starting_line * 2) * TILE_SIZE / 2; + let y_offset = (next_block.block_type.height + next_block.block_type.starting_line * 2) + * TILE_SIZE + / 2; for tile in next_block_tiles.iter() { sprite.set_texture_rect(&next_block.block_type.tile_type.texture_rect); sprite.set_position(Vector2f::new( - (NEXT_X + (tile.x - next_block.position.x) as u32 * TILE_SIZE - x_offset) as f32, - (NEXT_Y + (tile.y - next_block.position.y) as u32 * TILE_SIZE - y_offset) as f32 + (NEXT_X + (tile.x - next_block.position.x) as u32 * TILE_SIZE - x_offset) + as f32, + (NEXT_Y + (tile.y - next_block.position.y) as u32 * TILE_SIZE - y_offset) + as f32, )); window.draw(&sprite); } @@ -419,7 +439,7 @@ fn main() { 1 => POINTS_1_LINE, 2 => POINTS_2_LINES, 3 => POINTS_3_LINES, - _ => POINTS_4_LINES + _ => POINTS_4_LINES, }; if scored > 0 { let level = get_level(lines); @@ -475,7 +495,7 @@ fn main() { sprite.set_texture_rect(&tile_type.texture_rect); sprite.set_position(Vector2f::new( (PLAYFIELD_X + x * TILE_SIZE) as f32, - (PLAYFIELD_Y + y * TILE_SIZE) as f32 + (PLAYFIELD_Y + y * TILE_SIZE) as f32, )); window.draw(&sprite); } diff --git a/src/structs/block.rs b/src/structs/block.rs index b68360e..f29e3f1 100644 --- a/src/structs/block.rs +++ b/src/structs/block.rs @@ -1,61 +1,61 @@ -use crate::structs::BlockType; use crate::config::GRID_WIDTH; +use crate::structs::BlockType; use sfml::system::Vector2i; pub struct Block<'a> { - pub block_type: &'a BlockType, - pub position: Vector2i, - pub rotation_state: i32 + pub block_type: &'a BlockType, + pub position: Vector2i, + pub rotation_state: i32, } impl<'a> Block<'a> { - pub fn new(block_type: &'a BlockType, ) -> Self { - Self { - block_type, - position: Vector2i::new( - GRID_WIDTH as i32 / 2 - block_type.grid[0].len() as i32 / 2, - 0 - ), - rotation_state: 0 - } - } + pub fn new(block_type: &'a BlockType) -> Self { + Self { + block_type, + position: Vector2i::new( + GRID_WIDTH as i32 / 2 - block_type.grid[0].len() as i32 / 2, + 0, + ), + rotation_state: 0, + } + } - pub fn get_tiles(&mut self) -> Vec { - let mut tiles: Vec = Vec::new(); - for (y, row) in self.block_type.grid.iter().enumerate() { - let y = y as i32; - for (x, cell) in row.iter().enumerate() { - let x = x as i32; - if !cell { - continue; - } - let mut rotated = Vector2i::new(x as i32, y as i32); - if self.block_type.rotate { - let center_x = row.len() as i32 / 2; - let center_y = self.block_type.grid.len() as i32 / 2; - let offset_x = x - center_x; - let offset_y = y - center_y; - match self.rotation_state { - 0 => {}, - 1 => { - rotated.x = center_x + offset_y; - rotated.y = center_y - offset_x; - }, - 2 => { - rotated.x = center_x - offset_x; - rotated.y = center_y - offset_y; - }, - 3 => { - rotated.x = center_x - offset_y; - rotated.y = center_y + offset_x; - } - _ => self.rotation_state %= 4 - } - } - let global = self.position + rotated; - tiles.push(global); - } - } - tiles - } -} \ No newline at end of file + pub fn get_tiles(&mut self) -> Vec { + let mut tiles: Vec = Vec::new(); + for (y, row) in self.block_type.grid.iter().enumerate() { + let y = y as i32; + for (x, cell) in row.iter().enumerate() { + let x = x as i32; + if !cell { + continue; + } + let mut rotated = Vector2i::new(x as i32, y as i32); + if self.block_type.rotate { + let center_x = row.len() as i32 / 2; + let center_y = self.block_type.grid.len() as i32 / 2; + let offset_x = x - center_x; + let offset_y = y - center_y; + match self.rotation_state { + 0 => {} + 1 => { + rotated.x = center_x + offset_y; + rotated.y = center_y - offset_x; + } + 2 => { + rotated.x = center_x - offset_x; + rotated.y = center_y - offset_y; + } + 3 => { + rotated.x = center_x - offset_y; + rotated.y = center_y + offset_x; + } + _ => self.rotation_state %= 4, + } + } + let global = self.position + rotated; + tiles.push(global); + } + } + tiles + } +} diff --git a/src/structs/block_type.rs b/src/structs/block_type.rs index ebc6d3d..a00e926 100644 --- a/src/structs/block_type.rs +++ b/src/structs/block_type.rs @@ -1,151 +1,128 @@ -use crate::structs::TileType; use crate::config::TILE_SIZE; +use crate::structs::TileType; use sfml::graphics::IntRect; pub struct BlockType { - pub tile_type: TileType, - pub grid: Vec>, - pub width: u32, - pub height: u32, - pub starting_line: u32, - pub rotate: bool + pub tile_type: TileType, + pub grid: Vec>, + pub width: u32, + pub height: u32, + pub starting_line: u32, + pub rotate: bool, } impl BlockType { - pub fn new(tile_type: TileType, grid: Vec>, rotate: bool) -> Self { - let mut width: u32 = 0; - let mut height: u32 = 0; - let mut starting_line: u32 = 0; - for (y, row) in grid.iter().enumerate() { - let mut has_content = false; - for (x, cell) in row.iter().enumerate() { - if *cell { - width = std::cmp::max(width, x as u32 + 1); - has_content = true; - } - } - if has_content { - if height == 0 { - starting_line = y as u32; - } - height = y as u32 + 1 - starting_line; - } - } - Self { - tile_type, - grid, - width, - height, - starting_line, - rotate - } - } + pub fn new(tile_type: TileType, grid: Vec>, rotate: bool) -> Self { + let mut width: u32 = 0; + let mut height: u32 = 0; + let mut starting_line: u32 = 0; + for (y, row) in grid.iter().enumerate() { + let mut has_content = false; + for (x, cell) in row.iter().enumerate() { + if *cell { + width = std::cmp::max(width, x as u32 + 1); + has_content = true; + } + } + if has_content { + if height == 0 { + starting_line = y as u32; + } + height = y as u32 + 1 - starting_line; + } + } + Self { + tile_type, + grid, + width, + height, + starting_line, + rotate, + } + } - pub fn init_list() -> Vec { - let mut list = Vec::new(); - let tile_size = TILE_SIZE as i32; + pub fn init_list() -> Vec { + let mut list = Vec::new(); + let tile_size = TILE_SIZE as i32; - const Y: bool = true; - const N: bool = false; + const Y: bool = true; + const N: bool = false; - // I block - list.push(Self::new( - TileType::new( - IntRect::new(0, 0, tile_size, tile_size), - IntRect::new(0, tile_size, tile_size, tile_size) - ), - vec![ - vec![N, N, N, N], - vec![Y, Y, Y, Y], - vec![N, N, N, N], - vec![N, N, N, N] - ], - true - )); + // I block + list.push(Self::new( + TileType::new( + IntRect::new(0, 0, tile_size, tile_size), + IntRect::new(0, tile_size, tile_size, tile_size), + ), + vec![ + vec![N, N, N, N], + vec![Y, Y, Y, Y], + vec![N, N, N, N], + vec![N, N, N, N], + ], + true, + )); - // J Block - list.push(Self::new( - TileType::new( - IntRect::new(tile_size, 0, tile_size, tile_size), - IntRect::new(tile_size, tile_size, tile_size, tile_size), - ), - vec![ - vec![Y, N, N], - vec![Y, Y, Y], - vec![N, N, N] - ], - true - )); + // J Block + list.push(Self::new( + TileType::new( + IntRect::new(tile_size, 0, tile_size, tile_size), + IntRect::new(tile_size, tile_size, tile_size, tile_size), + ), + vec![vec![Y, N, N], vec![Y, Y, Y], vec![N, N, N]], + true, + )); - // L Block - list.push(Self::new( - TileType::new( - IntRect::new(tile_size * 2, 0, tile_size, tile_size), - IntRect::new(tile_size * 2, tile_size, tile_size, tile_size), - ), - vec![ - vec![N, N, Y], - vec![Y, Y, Y], - vec![N, N, N] - ], - true - )); + // L Block + list.push(Self::new( + TileType::new( + IntRect::new(tile_size * 2, 0, tile_size, tile_size), + IntRect::new(tile_size * 2, tile_size, tile_size, tile_size), + ), + vec![vec![N, N, Y], vec![Y, Y, Y], vec![N, N, N]], + true, + )); - // O Block - list.push(Self::new( - TileType::new( - IntRect::new(tile_size * 3, 0, tile_size, tile_size), - IntRect::new(tile_size * 3, tile_size, tile_size, tile_size), - ), - vec![ - vec![Y, Y], - vec![Y, Y] - ], - false - )); + // O Block + list.push(Self::new( + TileType::new( + IntRect::new(tile_size * 3, 0, tile_size, tile_size), + IntRect::new(tile_size * 3, tile_size, tile_size, tile_size), + ), + vec![vec![Y, Y], vec![Y, Y]], + false, + )); - // S Block - list.push(Self::new( - TileType::new( - IntRect::new(tile_size * 4, 0, tile_size, tile_size), - IntRect::new(tile_size * 4, tile_size, tile_size, tile_size), - ), - vec![ - vec![N, Y, Y], - vec![Y, Y, N], - vec![N, N, N] - ], - true - )); + // S Block + list.push(Self::new( + TileType::new( + IntRect::new(tile_size * 4, 0, tile_size, tile_size), + IntRect::new(tile_size * 4, tile_size, tile_size, tile_size), + ), + vec![vec![N, Y, Y], vec![Y, Y, N], vec![N, N, N]], + true, + )); - // T Block - list.push(Self::new( - TileType::new( - IntRect::new(tile_size * 5, 0, tile_size, tile_size), - IntRect::new(tile_size * 5, tile_size, tile_size, tile_size), - ), - vec![ - vec![N, Y, N], - vec![Y, Y, Y], - vec![N, N, N] - ], - true - )); + // T Block + list.push(Self::new( + TileType::new( + IntRect::new(tile_size * 5, 0, tile_size, tile_size), + IntRect::new(tile_size * 5, tile_size, tile_size, tile_size), + ), + vec![vec![N, Y, N], vec![Y, Y, Y], vec![N, N, N]], + true, + )); - // Z Block - list.push(Self::new( - TileType::new( - IntRect::new(tile_size * 6, 0, tile_size, tile_size), - IntRect::new(tile_size * 6, tile_size, tile_size, tile_size) - ), - vec![ - vec![Y, Y, N], - vec![N, Y, Y], - vec![N, N, N] - ], - true - )); - - list - } -} \ No newline at end of file + // Z Block + list.push(Self::new( + TileType::new( + IntRect::new(tile_size * 6, 0, tile_size, tile_size), + IntRect::new(tile_size * 6, tile_size, tile_size, tile_size), + ), + vec![vec![Y, Y, N], vec![N, Y, Y], vec![N, N, N]], + true, + )); + + list + } +} diff --git a/src/structs/mod.rs b/src/structs/mod.rs index 0a5232e..abce96a 100644 --- a/src/structs/mod.rs +++ b/src/structs/mod.rs @@ -8,4 +8,4 @@ mod tile_type; pub use tile_type::TileType; mod number_renderer; -pub use number_renderer::NumberRenderer; \ No newline at end of file +pub use number_renderer::NumberRenderer; diff --git a/src/structs/number_renderer.rs b/src/structs/number_renderer.rs index ed84517..7d55931 100644 --- a/src/structs/number_renderer.rs +++ b/src/structs/number_renderer.rs @@ -3,74 +3,84 @@ use sfml::system::Vector2f; use sfml::SfBox; pub struct NumberRenderer { - texture: SfBox, - comma_rect: IntRect, - numeral_rects: [IntRect; 10], + texture: SfBox, + comma_rect: IntRect, + numeral_rects: [IntRect; 10], } impl NumberRenderer { - pub fn new(texture: SfBox, comma_rect: IntRect, numeral_rects: [IntRect; 10]) -> Self { - Self { - texture, - comma_rect, - numeral_rects - } - } + pub fn new(texture: SfBox, comma_rect: IntRect, numeral_rects: [IntRect; 10]) -> Self { + Self { + texture, + comma_rect, + numeral_rects, + } + } - pub fn default() -> Self { - Self::new( - Texture::from_file(&crate::texture("numerals")).unwrap(), - IntRect::new(134, 0, 10, 16), - [ - IntRect::new(0, 0, 14, 16), - IntRect::new(14, 0, 8, 16), - IntRect::new(22, 0, 14, 16), - IntRect::new(36, 0, 14, 16), - IntRect::new(50, 0, 14, 16), - IntRect::new(64, 0, 14, 16), - IntRect::new(78, 0, 14, 16), - IntRect::new(92, 0, 14, 16), - IntRect::new(106, 0, 14, 16), - IntRect::new(120, 0, 14, 16) - ] - ) - } + pub fn default() -> Self { + Self::new( + Texture::from_file(&crate::texture("numerals")).unwrap(), + IntRect::new(134, 0, 10, 16), + [ + IntRect::new(0, 0, 14, 16), + IntRect::new(14, 0, 8, 16), + IntRect::new(22, 0, 14, 16), + IntRect::new(36, 0, 14, 16), + IntRect::new(50, 0, 14, 16), + IntRect::new(64, 0, 14, 16), + IntRect::new(78, 0, 14, 16), + IntRect::new(92, 0, 14, 16), + IntRect::new(106, 0, 14, 16), + IntRect::new(120, 0, 14, 16), + ], + ) + } - pub fn render(&self, window: &mut RenderWindow, number: u32, x: u32, y: u32) { - let number_string = number.to_string(); - let get_numeral_rect = |numeral: char| self.numeral_rects[numeral.to_digit(10).unwrap() as usize]; - let mut numeral_position = Vector2f::new({ - let numeral = number_string.chars().last().unwrap(); - let numeral_rect = get_numeral_rect(numeral); - x as f32 - numeral_rect.width as f32 - }, y as f32); - let digits = number_string.len(); - let mut sprite = Sprite::new(); - sprite.set_texture(&self.texture, false); - // can't reverse .chars() directly since it doesn't implement std::iter::DoubleEndedIterator - // Instead, we must collect it to a Vec then iterate over that. - // For more info, see https://users.rust-lang.org/t/43401/2 - for (i, numeral) in number_string.chars().collect::>().iter().enumerate().rev() { - let numeral_rect = get_numeral_rect(*numeral); - if (digits - i) % 3 == 1 && i != digits - 1 { - sprite.set_texture_rect(&self.comma_rect); - sprite.set_position(numeral_position); - window.draw(&sprite); - numeral_position.x -= numeral_rect.width as f32; - } - sprite.set_texture_rect(&numeral_rect); - sprite.set_position(numeral_position); - window.draw(&sprite); - if i == 0 { - break; - } - if (digits - i) % 3 == 0 { - numeral_position.x -= self.comma_rect.width as f32; - continue; - } - let numeral = number_string.as_bytes()[i - 1] as char; - let numeral_rect = get_numeral_rect(numeral); - numeral_position.x -= numeral_rect.width as f32; - } - } -} \ No newline at end of file + pub fn render(&self, window: &mut RenderWindow, number: u32, x: u32, y: u32) { + let number_string = number.to_string(); + let get_numeral_rect = + |numeral: char| self.numeral_rects[numeral.to_digit(10).unwrap() as usize]; + let mut numeral_position = Vector2f::new( + { + let numeral = number_string.chars().last().unwrap(); + let numeral_rect = get_numeral_rect(numeral); + x as f32 - numeral_rect.width as f32 + }, + y as f32, + ); + let digits = number_string.len(); + let mut sprite = Sprite::new(); + sprite.set_texture(&self.texture, false); + // can't reverse .chars() directly since it doesn't implement std::iter::DoubleEndedIterator + // Instead, we must collect it to a Vec then iterate over that. + // For more info, see https://users.rust-lang.org/t/43401/2 + for (i, numeral) in number_string + .chars() + .collect::>() + .iter() + .enumerate() + .rev() + { + let numeral_rect = get_numeral_rect(*numeral); + if (digits - i) % 3 == 1 && i != digits - 1 { + sprite.set_texture_rect(&self.comma_rect); + sprite.set_position(numeral_position); + window.draw(&sprite); + numeral_position.x -= numeral_rect.width as f32; + } + sprite.set_texture_rect(&numeral_rect); + sprite.set_position(numeral_position); + window.draw(&sprite); + if i == 0 { + break; + } + if (digits - i) % 3 == 0 { + numeral_position.x -= self.comma_rect.width as f32; + continue; + } + let numeral = number_string.as_bytes()[i - 1] as char; + let numeral_rect = get_numeral_rect(numeral); + numeral_position.x -= numeral_rect.width as f32; + } + } +} diff --git a/src/structs/tile_type.rs b/src/structs/tile_type.rs index 4ba7ead..8abbf7c 100644 --- a/src/structs/tile_type.rs +++ b/src/structs/tile_type.rs @@ -9,7 +9,7 @@ impl TileType { pub fn new(texture_rect: IntRect, ghost_texture_rect: IntRect) -> Self { Self { texture_rect, - ghost_texture_rect + ghost_texture_rect, } } -} \ No newline at end of file +}