diff options
-rw-r--r-- | src/main.rs | 118 |
1 files changed, 96 insertions, 22 deletions
diff --git a/src/main.rs b/src/main.rs index 0ce3299..33a369c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -17,6 +17,9 @@ const CELLS_B: [u8; FIGURE_SIZE] = [0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, const CELLS_S: [u8; FIGURE_SIZE] = [0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0]; const CELLS_T: [u8; FIGURE_SIZE] = [0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0]; const CELLS_Z: [u8; FIGURE_SIZE] = [0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0]; +const NEXT_COUNT: usize = 4; +const DISPLAY_NEXT_OFFSET_DOWN: usize = 4; +const DISPLAY_HOLD_OFFSET_DOWN: usize = 4; enum StepResult { StateChanged, @@ -27,9 +30,9 @@ enum StepResult { #[derive(Debug)] enum FigureKind { I, - L2, + J, L, - B, + O, S, T, Z, @@ -72,9 +75,9 @@ impl Figure { fn from_kind(kind: FigureKind) -> Self { match kind { FigureKind::I => Self{ cells: CELLS_I, kind }, - FigureKind::L2 => Self{ cells: CELLS_L2, kind }, + FigureKind::J => Self{ cells: CELLS_L2, kind }, FigureKind::L => Self{ cells: CELLS_L, kind }, - FigureKind::B => Self{ cells: CELLS_B, kind }, + FigureKind::O => Self{ cells: CELLS_B, kind }, FigureKind::S => Self{ cells: CELLS_S, kind }, FigureKind::T => Self{ cells: CELLS_T, kind }, FigureKind::Z => Self{ cells: CELLS_Z, kind }, @@ -105,9 +108,9 @@ impl Figure { fn rotate(&mut self) { match self.kind { FigureKind::I => self.rotate_cw_4x4(), - FigureKind::L2 => self.rotate_cw_3x3(), + FigureKind::J => self.rotate_cw_3x3(), FigureKind::L => self.rotate_cw_3x3(), - FigureKind::B => {}, + FigureKind::O => {}, FigureKind::S => self.rotate_cw_3x3(), FigureKind::T => self.rotate_cw_3x3(), FigureKind::Z => self.rotate_cw_3x3(), @@ -197,9 +200,9 @@ impl Bag { self.index += 1; match self.pieces[i as usize] { 0 => FigureKind::I, - 1 => FigureKind::L2, + 1 => FigureKind::J, 2 => FigureKind::L, - 4 => FigureKind::B, + 4 => FigureKind::O, 5 => FigureKind::S, 3 => FigureKind::T, 6 => FigureKind::Z, @@ -228,21 +231,32 @@ struct Game { fall_timeout: Timeout, place_timeout: Option<Timeout>, bag: Bag, + figure_next: [Figure; NEXT_COUNT], + figure_on_hold: Figure, } impl Default for Game { #[inline] fn default() -> Self { let mut bag = Bag::default(); - let kind = bag.next(); + let figure_on_hold = Figure::from_kind(bag.next()); + let figure = Figure::from_kind(bag.next()); + let figure_next = [ + Figure::from_kind(bag.next()), + Figure::from_kind(bag.next()), + Figure::from_kind(bag.next()), + Figure::from_kind(bag.next()), + ]; Self{ field: Field::default(), - figure: Figure::from_kind(kind), + figure, x: 3, y: 17, fall_timeout: Timeout::from_duration(std::time::Duration::from_millis(500)), place_timeout: None, bag, + figure_next, + figure_on_hold, } } } @@ -250,7 +264,11 @@ impl Default for Game { impl Game { fn place_figure(&mut self) { self.field.render(&self.figure, self.x, self.y); - self.figure = Figure::from_kind(self.bag.next()); + self.figure = self.figure_next[0].clone(); + for i in 0..NEXT_COUNT - 1 { + self.figure_next[i] = self.figure_next[i + 1].clone(); + } + self.figure_next[NEXT_COUNT - 1] = Figure::from_kind(self.bag.next()); (self.x, self.y) = (3, 17); self.stop_place_timeout(); for line in 0..FIELD_ROWS - 1 { @@ -259,6 +277,10 @@ impl Game { } } } + fn hold_figure(&mut self) { + (self.figure_on_hold, self.figure) = (Figure::from_kind(self.figure.kind.clone()), self.figure_on_hold.clone()); + (self.x, self.y) = (3, 17); + } fn reset_fall_timeout(&mut self) { self.fall_timeout = Timeout::from_duration(std::time::Duration::from_millis(500)); } @@ -282,12 +304,12 @@ impl Game { } self.place_figure() }, - 'h' => { + 'j' => { if !self.field.has_collision(&self.figure, self.x - 1, self.y) { self.x -= 1; } } - 'j' => { + 'k' => { if !self.field.has_collision(&self.figure, self.x, self.y - 1) { self.y -= 1; self.reset_fall_timeout(); @@ -295,7 +317,7 @@ impl Game { self.start_place_timeout(); } } - ';' | 'k' => { + ';' | 'i' => { let mut figure = self.figure.clone(); figure.rotate(); if !self.field.has_collision(&figure, self.x, self.y) { @@ -307,6 +329,10 @@ impl Game { self.x += 1; } } + 'h' => { + self.hold_figure(); + self.reset_fall_timeout(); + } _ => {}, } self.reset_place_timeout(); @@ -350,27 +376,75 @@ impl Game { } } -fn print_field(field: &Field) { - cursor_to_home(); - for y in 0..FIELD_ROWS_VISIBLE { - print!("|"); - for x in 0..FIELD_COLS { - let c = field.cells[(FIELD_ROWS_VISIBLE - 1 - y) * FIELD_COLS + x]; +fn print_hold(figure: &Figure, y_global: usize) { + let offset = DISPLAY_HOLD_OFFSET_DOWN; + let at_figure = y_global >= (1 + offset) && y_global < FIGURE_SIZE_ROWS + (1 + offset); + if y_global == offset { + print!(" Hold: "); + } else if at_figure { + print!(" "); + let y = FIGURE_SIZE_ROWS - 1 - (y_global - 1 - offset); + for x in 0..FIGURE_SIZE_COLS { + let c = figure.cells[y * FIGURE_SIZE_COLS + x]; if c == 0 { print!(" "); } else { print!("██"); } } - print!("|\r\x1b[1B"); + print!(" "); + } else { + print!(" "); + } +} + +fn print_next(figure: &[Figure; NEXT_COUNT], y_global: usize) { + let offset = DISPLAY_NEXT_OFFSET_DOWN; + if y_global == offset { + print!(" Next: "); + } else { + for i in 0..NEXT_COUNT { + let at_figure = y_global >= (1 + offset + FIGURE_SIZE_ROWS * i) && y_global < (1 + offset + FIGURE_SIZE_ROWS * (i + 1)); + if at_figure { + print!(" "); + let y = FIGURE_SIZE_ROWS - 1 - (y_global - 1 - offset - FIGURE_SIZE_ROWS * i); + for x in 0..FIGURE_SIZE_COLS { + let c = figure[i].cells[y * FIGURE_SIZE_COLS + x]; + if c == 0 { + print!(" "); + } else { + print!("██"); + } + } + break; + } + } } } +fn print_field(field: &Field, y: usize) { + print!("|"); + for x in 0..FIELD_COLS { + let c = field.cells[(FIELD_ROWS_VISIBLE - 1 - y) * FIELD_COLS + x]; + if c == 0 { + print!(" "); + } else { + print!("██"); + } + } + print!("|"); +} + fn display_game(game: &Game) { cursor_to_home(); let mut field = game.field.clone(); field.render(&game.figure, game.x, game.y); - print_field(&field); + for y in 0..FIELD_ROWS_VISIBLE { + print_hold(&game.figure_on_hold, y); + print_field(&field, y); + print_next(&game.figure_next, y); + print!("\r\x1b[1B"); + } if game.field.has_collision(&game.figure, game.x, game.y) { println!("Collision!"); } else { |