main
Elnu 2 years ago
parent 8b6387737c
commit d55773cdc5

@ -34,4 +34,4 @@ pub const RES_PATH: &str = "res";
pub const RES_PATH: &str = "/usr/games/septadrop"; pub const RES_PATH: &str = "/usr/games/septadrop";
pub const RES_AUDIO_PATH: &str = formatcp!("{RES_PATH}/audio"); pub const RES_AUDIO_PATH: &str = formatcp!("{RES_PATH}/audio");
pub const RES_TEXTURES_PATH: &str = formatcp!("{RES_PATH}/textures"); pub const RES_TEXTURES_PATH: &str = formatcp!("{RES_PATH}/textures");

@ -1,9 +1,9 @@
use gcd::Gcd;
use rand::seq::SliceRandom;
use sfml::audio::*;
use sfml::graphics::*; use sfml::graphics::*;
use sfml::window::*;
use sfml::system::*; use sfml::system::*;
use sfml::audio::*; use sfml::window::*;
use rand::seq::SliceRandom;
use gcd::Gcd;
use std::io::Write; use std::io::Write;
mod structs; mod structs;
@ -35,27 +35,31 @@ fn main() {
VideoMode::new(WINDOW_WIDTH, WINDOW_HEIGHT, 16), VideoMode::new(WINDOW_WIDTH, WINDOW_HEIGHT, 16),
"septadrop", "septadrop",
Style::TITLEBAR | Style::CLOSE, Style::TITLEBAR | Style::CLOSE,
&context_settings &context_settings,
); );
window.set_framerate_limit(FPS); window.set_framerate_limit(FPS);
window.set_key_repeat_enabled(false); window.set_key_repeat_enabled(false);
let icon = Image::from_file(&texture("icon")).unwrap(); 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()); window.set_icon(width, height, icon.pixel_data());
} }
let mut thread_rng = rand::thread_rng(); let mut thread_rng = rand::thread_rng();
let block_types = BlockType::init_list(); let block_types = BlockType::init_list();
let mut random_block = || Block::new(block_types.choose(&mut thread_rng).unwrap()); let mut random_block = || Block::new(block_types.choose(&mut thread_rng).unwrap());
let mut block = random_block(); let mut block = random_block();
let mut next_block = random_block(); let mut next_block = random_block();
// Default::default() initializes all array cells to None (no 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 blocks_texture = Texture::from_file(&texture("blocks")).unwrap();
let mut sprite = Sprite::with_texture(&blocks_texture); let mut sprite = Sprite::with_texture(&blocks_texture);
@ -73,8 +77,10 @@ fn main() {
let mut paused_text = Sprite::with_texture(&paused_texture); let mut paused_text = Sprite::with_texture(&paused_texture);
let paused_texture_size = paused_texture.size(); let paused_texture_size = paused_texture.size();
paused_text.set_position(Vector2f::new( 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_X as f32 + (GRID_WIDTH as f32 * TILE_SIZE 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_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 paused_text
}; };
@ -84,7 +90,11 @@ fn main() {
let mut highscore: u32; let mut highscore: u32;
if highscore_file_path.exists() { if highscore_file_path.exists() {
highscore = std::fs::read_to_string(&highscore_file_path).unwrap().trim().parse::<u32>().unwrap(); highscore = std::fs::read_to_string(&highscore_file_path)
.unwrap()
.trim()
.parse::<u32>()
.unwrap();
let point_gcd = POINTS_1_LINE let point_gcd = POINTS_1_LINE
.gcd(POINTS_2_LINES) .gcd(POINTS_2_LINES)
.gcd(POINTS_3_LINES) .gcd(POINTS_3_LINES)
@ -152,48 +162,56 @@ fn main() {
Event::Closed => { Event::Closed => {
window.close(); window.close();
break; break;
}, }
Event::GainedFocus => { Event::GainedFocus => {
if paused && paused_from_lost_focus { if paused && paused_from_lost_focus {
toggle_pause = true; toggle_pause = true;
} }
}, }
Event::LostFocus => { Event::LostFocus => {
if !paused { if !paused {
toggle_pause = true; toggle_pause = true;
paused_from_lost_focus = true; paused_from_lost_focus = true;
} }
}, }
Event::KeyPressed { code, alt: _, ctrl: _, shift: _, system: _ } => { Event::KeyPressed {
match code { code,
Key::ESCAPE => toggle_pause = true, alt: _,
Key::SPACE => snap = !paused, ctrl: _,
Key::UP => rotate = !paused, shift: _,
Key::DOWN => fast_forward = !paused, system: _,
Key::LEFT => { } => match code {
move_left = !paused; Key::ESCAPE => toggle_pause = true,
move_left_immediate = !paused; Key::SPACE => snap = !paused,
move_clock.restart(); Key::UP => rotate = !paused,
}, Key::DOWN => fast_forward = !paused,
Key::RIGHT => { Key::LEFT => {
move_right = !paused; move_left = !paused;
move_right_immediate = !paused; move_left_immediate = !paused;
move_clock.restart(); move_clock.restart();
}
_ => {}
} }
}, Key::RIGHT => {
Event::KeyReleased { code, alt: _, ctrl: _, shift: _, system: _ } => { move_right = !paused;
match code { move_right_immediate = !paused;
Key::DOWN => fast_forward = false, move_clock.restart();
Key::LEFT => move_left = false,
Key::RIGHT => move_right = false,
_ => {}
} }
} _ => {}
_ => {}, },
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; paused = !paused;
if paused { if paused {
pause_clock.restart(); pause_clock.restart();
paused_clear.set_position(Vector2f::new( paused_clear.set_position(Vector2f::new(PLAYFIELD_X as f32, PLAYFIELD_Y as f32));
PLAYFIELD_X as f32,
PLAYFIELD_Y as f32
));
paused_clear.set_size(Vector2f::new( paused_clear.set_size(Vector2f::new(
(GRID_WIDTH * TILE_SIZE) as f32, (GRID_WIDTH * TILE_SIZE) as f32,
(GRID_HEIGHT * TILE_SIZE) as f32 (GRID_HEIGHT * TILE_SIZE) as f32,
)); ));
window.draw(&paused_clear); window.draw(&paused_clear);
let size = Vector2f::new( let size = Vector2f::new(
(NEXT_WIDTH * TILE_SIZE) as f32, (NEXT_WIDTH * TILE_SIZE) as f32,
(NEXT_HEIGHT * TILE_SIZE) as f32 (NEXT_HEIGHT * TILE_SIZE) as f32,
); );
paused_clear.set_position(Vector2f::new( paused_clear.set_position(Vector2f::new(NEXT_X as f32, NEXT_Y as f32) - size / 2.0);
NEXT_X as f32,
NEXT_Y as f32
) - size / 2.0);
paused_clear.set_size(size); paused_clear.set_size(size);
window.draw(&paused_clear); window.draw(&paused_clear);
window.draw(&paused_text); window.draw(&paused_text);
@ -235,9 +247,8 @@ fn main() {
continue; continue;
} }
let is_update_frame = let is_update_frame = update_clock.elapsed_time().as_milliseconds() - pause_offset as i32
update_clock.elapsed_time().as_milliseconds() - pause_offset as i32 > > if fast_forward {
if fast_forward {
std::cmp::min(update_interval, MAX_FAST_FORWARD_INTERVAL) std::cmp::min(update_interval, MAX_FAST_FORWARD_INTERVAL)
} else { } else {
update_interval update_interval
@ -245,10 +256,9 @@ fn main() {
if is_update_frame { if is_update_frame {
update_clock.restart(); update_clock.restart();
} }
let is_move_frame = let is_move_frame = move_clock.elapsed_time().as_milliseconds() - pause_offset as i32
move_clock.elapsed_time().as_milliseconds() - pause_offset as i32 > > MOVE_FRAME_INTERVAL as i32;
MOVE_FRAME_INTERVAL as i32;
if is_move_frame { if is_move_frame {
move_clock.restart(); move_clock.restart();
} }
@ -296,7 +306,10 @@ fn main() {
} }
if movement != 0 { if movement != 0 {
for (i, tile) in block.get_tiles().iter().enumerate().rev() { 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; break;
} }
if i == 0 { if i == 0 {
@ -335,9 +348,12 @@ fn main() {
block.position.y += snap_offset; block.position.y += snap_offset;
snap = false; snap = false;
snap_sound.play(); snap_sound.play();
} else if is_update_frame { // Land checking } else if is_update_frame {
// Land checking
for tile in block.get_tiles().iter() { 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; landed = true;
break; break;
} }
@ -345,10 +361,10 @@ fn main() {
} }
let landed = landed; // remove mutability let landed = landed; // remove mutability
// Clear window // Clear window
// Normally, one would run window.clear(), // Normally, one would run window.clear(),
// but the background image covers the entire window. // but the background image covers the entire window.
window.draw(&background); window.draw(&background);
// Draw block // Draw block
if !landed { if !landed {
@ -357,13 +373,13 @@ fn main() {
sprite.set_texture_rect(&block.block_type.tile_type.texture_rect); sprite.set_texture_rect(&block.block_type.tile_type.texture_rect);
sprite.set_position(Vector2f::new( sprite.set_position(Vector2f::new(
(PLAYFIELD_X as i32 + tile.x * TILE_SIZE as i32) as f32, (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); window.draw(&sprite);
sprite.set_texture_rect(&block.block_type.tile_type.ghost_texture_rect); sprite.set_texture_rect(&block.block_type.tile_type.ghost_texture_rect);
sprite.set_position(Vector2f::new( sprite.set_position(Vector2f::new(
(PLAYFIELD_X as i32 + tile.x * TILE_SIZE as i32) as f32, (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); window.draw(&sprite);
} }
@ -375,12 +391,16 @@ fn main() {
// This is assuming the next block spawns unrotated. // This is assuming the next block spawns unrotated.
// Refactoring is needed if random rotations are added // Refactoring is needed if random rotations are added
let x_offset = next_block.block_type.width * TILE_SIZE / 2; 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() { for tile in next_block_tiles.iter() {
sprite.set_texture_rect(&next_block.block_type.tile_type.texture_rect); sprite.set_texture_rect(&next_block.block_type.tile_type.texture_rect);
sprite.set_position(Vector2f::new( sprite.set_position(Vector2f::new(
(NEXT_X + (tile.x - next_block.position.x) as u32 * TILE_SIZE - x_offset) as f32, (NEXT_X + (tile.x - next_block.position.x) as u32 * TILE_SIZE - x_offset)
(NEXT_Y + (tile.y - next_block.position.y) as u32 * TILE_SIZE - y_offset) as f32 as f32,
(NEXT_Y + (tile.y - next_block.position.y) as u32 * TILE_SIZE - y_offset)
as f32,
)); ));
window.draw(&sprite); window.draw(&sprite);
} }
@ -419,7 +439,7 @@ fn main() {
1 => POINTS_1_LINE, 1 => POINTS_1_LINE,
2 => POINTS_2_LINES, 2 => POINTS_2_LINES,
3 => POINTS_3_LINES, 3 => POINTS_3_LINES,
_ => POINTS_4_LINES _ => POINTS_4_LINES,
}; };
if scored > 0 { if scored > 0 {
let level = get_level(lines); let level = get_level(lines);
@ -475,7 +495,7 @@ fn main() {
sprite.set_texture_rect(&tile_type.texture_rect); sprite.set_texture_rect(&tile_type.texture_rect);
sprite.set_position(Vector2f::new( sprite.set_position(Vector2f::new(
(PLAYFIELD_X + x * TILE_SIZE) as f32, (PLAYFIELD_X + x * TILE_SIZE) as f32,
(PLAYFIELD_Y + y * TILE_SIZE) as f32 (PLAYFIELD_Y + y * TILE_SIZE) as f32,
)); ));
window.draw(&sprite); window.draw(&sprite);
} }

@ -1,61 +1,61 @@
use crate::structs::BlockType;
use crate::config::GRID_WIDTH; use crate::config::GRID_WIDTH;
use crate::structs::BlockType;
use sfml::system::Vector2i; use sfml::system::Vector2i;
pub struct Block<'a> { pub struct Block<'a> {
pub block_type: &'a BlockType, pub block_type: &'a BlockType,
pub position: Vector2i, pub position: Vector2i,
pub rotation_state: i32 pub rotation_state: i32,
} }
impl<'a> Block<'a> { impl<'a> Block<'a> {
pub fn new(block_type: &'a BlockType, ) -> Self { pub fn new(block_type: &'a BlockType) -> Self {
Self { Self {
block_type, block_type,
position: Vector2i::new( position: Vector2i::new(
GRID_WIDTH as i32 / 2 - block_type.grid[0].len() as i32 / 2, GRID_WIDTH as i32 / 2 - block_type.grid[0].len() as i32 / 2,
0 0,
), ),
rotation_state: 0 rotation_state: 0,
} }
} }
pub fn get_tiles(&mut self) -> Vec<Vector2i> { pub fn get_tiles(&mut self) -> Vec<Vector2i> {
let mut tiles: Vec<Vector2i> = Vec::new(); let mut tiles: Vec<Vector2i> = Vec::new();
for (y, row) in self.block_type.grid.iter().enumerate() { for (y, row) in self.block_type.grid.iter().enumerate() {
let y = y as i32; let y = y as i32;
for (x, cell) in row.iter().enumerate() { for (x, cell) in row.iter().enumerate() {
let x = x as i32; let x = x as i32;
if !cell { if !cell {
continue; continue;
} }
let mut rotated = Vector2i::new(x as i32, y as i32); let mut rotated = Vector2i::new(x as i32, y as i32);
if self.block_type.rotate { if self.block_type.rotate {
let center_x = row.len() as i32 / 2; let center_x = row.len() as i32 / 2;
let center_y = self.block_type.grid.len() as i32 / 2; let center_y = self.block_type.grid.len() as i32 / 2;
let offset_x = x - center_x; let offset_x = x - center_x;
let offset_y = y - center_y; let offset_y = y - center_y;
match self.rotation_state { match self.rotation_state {
0 => {}, 0 => {}
1 => { 1 => {
rotated.x = center_x + offset_y; rotated.x = center_x + offset_y;
rotated.y = center_y - offset_x; rotated.y = center_y - offset_x;
}, }
2 => { 2 => {
rotated.x = center_x - offset_x; rotated.x = center_x - offset_x;
rotated.y = center_y - offset_y; rotated.y = center_y - offset_y;
}, }
3 => { 3 => {
rotated.x = center_x - offset_y; rotated.x = center_x - offset_y;
rotated.y = center_y + offset_x; rotated.y = center_y + offset_x;
} }
_ => self.rotation_state %= 4 _ => self.rotation_state %= 4,
} }
} }
let global = self.position + rotated; let global = self.position + rotated;
tiles.push(global); tiles.push(global);
} }
} }
tiles tiles
} }
} }

@ -1,151 +1,128 @@
use crate::structs::TileType;
use crate::config::TILE_SIZE; use crate::config::TILE_SIZE;
use crate::structs::TileType;
use sfml::graphics::IntRect; use sfml::graphics::IntRect;
pub struct BlockType { pub struct BlockType {
pub tile_type: TileType, pub tile_type: TileType,
pub grid: Vec<Vec<bool>>, pub grid: Vec<Vec<bool>>,
pub width: u32, pub width: u32,
pub height: u32, pub height: u32,
pub starting_line: u32, pub starting_line: u32,
pub rotate: bool pub rotate: bool,
} }
impl BlockType { impl BlockType {
pub fn new(tile_type: TileType, grid: Vec<Vec<bool>>, rotate: bool) -> Self { pub fn new(tile_type: TileType, grid: Vec<Vec<bool>>, rotate: bool) -> Self {
let mut width: u32 = 0; let mut width: u32 = 0;
let mut height: u32 = 0; let mut height: u32 = 0;
let mut starting_line: u32 = 0; let mut starting_line: u32 = 0;
for (y, row) in grid.iter().enumerate() { for (y, row) in grid.iter().enumerate() {
let mut has_content = false; let mut has_content = false;
for (x, cell) in row.iter().enumerate() { for (x, cell) in row.iter().enumerate() {
if *cell { if *cell {
width = std::cmp::max(width, x as u32 + 1); width = std::cmp::max(width, x as u32 + 1);
has_content = true; has_content = true;
} }
} }
if has_content { if has_content {
if height == 0 { if height == 0 {
starting_line = y as u32; starting_line = y as u32;
} }
height = y as u32 + 1 - starting_line; height = y as u32 + 1 - starting_line;
} }
} }
Self { Self {
tile_type, tile_type,
grid, grid,
width, width,
height, height,
starting_line, starting_line,
rotate rotate,
} }
} }
pub fn init_list() -> Vec<Self> { pub fn init_list() -> Vec<Self> {
let mut list = Vec::new(); let mut list = Vec::new();
let tile_size = TILE_SIZE as i32; let tile_size = TILE_SIZE as i32;
const Y: bool = true; const Y: bool = true;
const N: bool = false; const N: bool = false;
// I block // I block
list.push(Self::new( list.push(Self::new(
TileType::new( TileType::new(
IntRect::new(0, 0, tile_size, tile_size), IntRect::new(0, 0, tile_size, tile_size),
IntRect::new(0, tile_size, tile_size, tile_size) IntRect::new(0, tile_size, tile_size, tile_size),
), ),
vec![ vec![
vec![N, N, N, N], vec![N, N, N, N],
vec![Y, Y, Y, Y], vec![Y, Y, Y, Y],
vec![N, N, N, N], vec![N, N, N, N],
vec![N, N, N, N] vec![N, N, N, N],
], ],
true true,
)); ));
// J Block // J Block
list.push(Self::new( list.push(Self::new(
TileType::new( TileType::new(
IntRect::new(tile_size, 0, tile_size, tile_size), IntRect::new(tile_size, 0, tile_size, tile_size),
IntRect::new(tile_size, tile_size, tile_size, tile_size), IntRect::new(tile_size, tile_size, tile_size, tile_size),
), ),
vec![ vec![vec![Y, N, N], vec![Y, Y, Y], vec![N, N, N]],
vec![Y, N, N], true,
vec![Y, Y, Y], ));
vec![N, N, N]
],
true
));
// L Block // L Block
list.push(Self::new( list.push(Self::new(
TileType::new( TileType::new(
IntRect::new(tile_size * 2, 0, tile_size, tile_size), IntRect::new(tile_size * 2, 0, tile_size, tile_size),
IntRect::new(tile_size * 2, tile_size, tile_size, tile_size), IntRect::new(tile_size * 2, tile_size, tile_size, tile_size),
), ),
vec![ vec![vec![N, N, Y], vec![Y, Y, Y], vec![N, N, N]],
vec![N, N, Y], true,
vec![Y, Y, Y], ));
vec![N, N, N]
],
true
));
// O Block // O Block
list.push(Self::new( list.push(Self::new(
TileType::new( TileType::new(
IntRect::new(tile_size * 3, 0, tile_size, tile_size), IntRect::new(tile_size * 3, 0, tile_size, tile_size),
IntRect::new(tile_size * 3, tile_size, tile_size, tile_size), IntRect::new(tile_size * 3, tile_size, tile_size, tile_size),
), ),
vec![ vec![vec![Y, Y], vec![Y, Y]],
vec![Y, Y], false,
vec![Y, Y] ));
],
false
));
// S Block // S Block
list.push(Self::new( list.push(Self::new(
TileType::new( TileType::new(
IntRect::new(tile_size * 4, 0, tile_size, tile_size), IntRect::new(tile_size * 4, 0, tile_size, tile_size),
IntRect::new(tile_size * 4, tile_size, tile_size, tile_size), IntRect::new(tile_size * 4, tile_size, tile_size, tile_size),
), ),
vec![ vec![vec![N, Y, Y], vec![Y, Y, N], vec![N, N, N]],
vec![N, Y, Y], true,
vec![Y, Y, N], ));
vec![N, N, N]
],
true
));
// T Block // T Block
list.push(Self::new( list.push(Self::new(
TileType::new( TileType::new(
IntRect::new(tile_size * 5, 0, tile_size, tile_size), IntRect::new(tile_size * 5, 0, tile_size, tile_size),
IntRect::new(tile_size * 5, tile_size, tile_size, tile_size), IntRect::new(tile_size * 5, tile_size, tile_size, tile_size),
), ),
vec![ vec![vec![N, Y, N], vec![Y, Y, Y], vec![N, N, N]],
vec![N, Y, N], true,
vec![Y, Y, Y], ));
vec![N, N, N]
],
true
));
// Z Block // Z Block
list.push(Self::new( list.push(Self::new(
TileType::new( TileType::new(
IntRect::new(tile_size * 6, 0, tile_size, tile_size), IntRect::new(tile_size * 6, 0, tile_size, tile_size),
IntRect::new(tile_size * 6, tile_size, tile_size, tile_size) IntRect::new(tile_size * 6, tile_size, tile_size, tile_size),
), ),
vec![ vec![vec![Y, Y, N], vec![N, Y, Y], vec![N, N, N]],
vec![Y, Y, N], true,
vec![N, Y, Y], ));
vec![N, N, N]
], list
true }
)); }
list
}
}

@ -8,4 +8,4 @@ mod tile_type;
pub use tile_type::TileType; pub use tile_type::TileType;
mod number_renderer; mod number_renderer;
pub use number_renderer::NumberRenderer; pub use number_renderer::NumberRenderer;

@ -3,74 +3,84 @@ use sfml::system::Vector2f;
use sfml::SfBox; use sfml::SfBox;
pub struct NumberRenderer { pub struct NumberRenderer {
texture: SfBox<Texture>, texture: SfBox<Texture>,
comma_rect: IntRect, comma_rect: IntRect,
numeral_rects: [IntRect; 10], numeral_rects: [IntRect; 10],
} }
impl NumberRenderer { impl NumberRenderer {
pub fn new(texture: SfBox<Texture>, comma_rect: IntRect, numeral_rects: [IntRect; 10]) -> Self { pub fn new(texture: SfBox<Texture>, comma_rect: IntRect, numeral_rects: [IntRect; 10]) -> Self {
Self { Self {
texture, texture,
comma_rect, comma_rect,
numeral_rects numeral_rects,
} }
} }
pub fn default() -> Self { pub fn default() -> Self {
Self::new( Self::new(
Texture::from_file(&crate::texture("numerals")).unwrap(), Texture::from_file(&crate::texture("numerals")).unwrap(),
IntRect::new(134, 0, 10, 16), IntRect::new(134, 0, 10, 16),
[ [
IntRect::new(0, 0, 14, 16), IntRect::new(0, 0, 14, 16),
IntRect::new(14, 0, 8, 16), IntRect::new(14, 0, 8, 16),
IntRect::new(22, 0, 14, 16), IntRect::new(22, 0, 14, 16),
IntRect::new(36, 0, 14, 16), IntRect::new(36, 0, 14, 16),
IntRect::new(50, 0, 14, 16), IntRect::new(50, 0, 14, 16),
IntRect::new(64, 0, 14, 16), IntRect::new(64, 0, 14, 16),
IntRect::new(78, 0, 14, 16), IntRect::new(78, 0, 14, 16),
IntRect::new(92, 0, 14, 16), IntRect::new(92, 0, 14, 16),
IntRect::new(106, 0, 14, 16), IntRect::new(106, 0, 14, 16),
IntRect::new(120, 0, 14, 16) IntRect::new(120, 0, 14, 16),
] ],
) )
} }
pub fn render(&self, window: &mut RenderWindow, number: u32, x: u32, y: u32) { pub fn render(&self, window: &mut RenderWindow, number: u32, x: u32, y: u32) {
let number_string = number.to_string(); let number_string = number.to_string();
let get_numeral_rect = |numeral: char| self.numeral_rects[numeral.to_digit(10).unwrap() as usize]; let get_numeral_rect =
let mut numeral_position = Vector2f::new({ |numeral: char| self.numeral_rects[numeral.to_digit(10).unwrap() as usize];
let numeral = number_string.chars().last().unwrap(); let mut numeral_position = Vector2f::new(
let numeral_rect = get_numeral_rect(numeral); {
x as f32 - numeral_rect.width as f32 let numeral = number_string.chars().last().unwrap();
}, y as f32); let numeral_rect = get_numeral_rect(numeral);
let digits = number_string.len(); x as f32 - numeral_rect.width as f32
let mut sprite = Sprite::new(); },
sprite.set_texture(&self.texture, false); y as f32,
// 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. let digits = number_string.len();
// For more info, see https://users.rust-lang.org/t/43401/2 let mut sprite = Sprite::new();
for (i, numeral) in number_string.chars().collect::<Vec<char>>().iter().enumerate().rev() { sprite.set_texture(&self.texture, false);
let numeral_rect = get_numeral_rect(*numeral); // can't reverse .chars() directly since it doesn't implement std::iter::DoubleEndedIterator
if (digits - i) % 3 == 1 && i != digits - 1 { // Instead, we must collect it to a Vec then iterate over that.
sprite.set_texture_rect(&self.comma_rect); // For more info, see https://users.rust-lang.org/t/43401/2
sprite.set_position(numeral_position); for (i, numeral) in number_string
window.draw(&sprite); .chars()
numeral_position.x -= numeral_rect.width as f32; .collect::<Vec<char>>()
} .iter()
sprite.set_texture_rect(&numeral_rect); .enumerate()
sprite.set_position(numeral_position); .rev()
window.draw(&sprite); {
if i == 0 { let numeral_rect = get_numeral_rect(*numeral);
break; if (digits - i) % 3 == 1 && i != digits - 1 {
} sprite.set_texture_rect(&self.comma_rect);
if (digits - i) % 3 == 0 { sprite.set_position(numeral_position);
numeral_position.x -= self.comma_rect.width as f32; window.draw(&sprite);
continue; numeral_position.x -= numeral_rect.width as f32;
} }
let numeral = number_string.as_bytes()[i - 1] as char; sprite.set_texture_rect(&numeral_rect);
let numeral_rect = get_numeral_rect(numeral); sprite.set_position(numeral_position);
numeral_position.x -= numeral_rect.width as f32; 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;
}
}
}

@ -9,7 +9,7 @@ impl TileType {
pub fn new(texture_rect: IntRect, ghost_texture_rect: IntRect) -> Self { pub fn new(texture_rect: IntRect, ghost_texture_rect: IntRect) -> Self {
Self { Self {
texture_rect, texture_rect,
ghost_texture_rect ghost_texture_rect,
} }
} }
} }

Loading…
Cancel
Save