diff --git a/src/main.rs b/src/main.rs index 6ad1c8f..0d4ef8a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,9 +3,9 @@ use std::time::Duration; use rand::Rng; -use ufo::Ufo; - +use crate::Direction::Left; use crate::movable::Movable; +use crate::ufo::Ufo; mod movable; mod terminal; @@ -27,14 +27,14 @@ const VERSION: &str = env!("CARGO_PKG_VERSION"); fn main() { let terminal = terminal::setup(); + const MAX_UFOS: u8 = 100; let mut ufos = vec![Ufo::create(), Ufo::create(), Ufo::create(), Ufo::create(), Ufo::create()]; let mut n_ufos = ufos.len() as u8; loop { let iter_mut = ufos.iter_mut(); for x in iter_mut { - x.mov(Direction::Left); - x.draw(); + x.mov(Left); } if rand::thread_rng().gen_bool(0.1) && n_ufos < MAX_UFOS { ufos.push(Ufo::create()); @@ -50,10 +50,7 @@ fn main() { terminal::restore(terminal); } -fn tank_at(col: u16) { - terminal::print_str_at(col, TANK_ROW, TANK_STR); -} - +#[derive(PartialEq)] pub enum Direction { Left, Right, diff --git a/src/ufo.rs b/src/ufo.rs index bc10ad1..df1f02a 100644 --- a/src/ufo.rs +++ b/src/ufo.rs @@ -1,8 +1,11 @@ +use std::cmp::{max, min}; + use rand::Rng; + use crate::{Direction, MAX_UFO_ROW, MIN_UFO_ROW, UFO_STR, WIDTH}; use crate::Direction::{Down, Left, Right}; use crate::movable::Movable; -use crate::terminal::print_str_at; +use crate::terminal::{clear_pos, print_str_at}; pub struct Ufo { row: u16, @@ -17,29 +20,32 @@ impl Movable for Ufo { let row = rng.gen_range(MIN_UFO_ROW..=MAX_UFO_ROW); let column = match direction { // If the UFO is moving right, we will initially place it just at the left edge. - Right => -(UFO_STR.len() as i16) + 1, + Right => -(UFO_STR.len() as i16), // If the UFO is moving left, we will initially place it just at the right edge. - Left => WIDTH as i16 - 1, + Left => WIDTH as i16, // Above, we're creating either a Left or a Right direction value. So, we CANNOT get here. Hence: PANIC! _ => panic!("Programming error. We're not supposed to get here.") }; - Ufo { row, column, direction } + let ufo = Ufo { row, column, direction }; + ufo.draw(); + ufo } fn mov(&mut self, direction: Direction) { - let ufo_str_len = UFO_STR.len() as i16; + clear(self); match direction { Down => { todo!("Implement crash movement (down + direction)") } _ => { match self.direction { Left => { + let ufo_str_len = UFO_STR.len() as i16; if self.column >= -ufo_str_len { self.column -= 1; } } Right => { - if self.column < WIDTH as i16 { + if self.column <= WIDTH as i16 { self.column += 1; } } @@ -47,40 +53,39 @@ impl Movable for Ufo { }; } }; + + self.draw(); } fn draw(&self) { - let mut body: String; let ufo_str_len = UFO_STR.len() as i16; + let left_cutoff = min(max(0, -self.column), ufo_str_len) as usize; + let right_cutoff = max(0, min(ufo_str_len, WIDTH as i16 - self.column)) as usize; - if self.column < -ufo_str_len { - // left outside - body = String::new(); - } else if self.column < 0 { - // left transitioning in/out - body = String::new(); - } else if self.column < (WIDTH as i16 - ufo_str_len) { - // normal range - body = String::from(UFO_STR); - match self.direction { - Left => { body.push(' ') } - Right => { body = String::from(" ") + body.as_str() } - Down => { todo!("How do we handle the downward movement?") } - _ => {} - } - let max_len = WIDTH as i16 - self.column; - body.truncate(max_len as usize) - } else if self.column < WIDTH as i16 { - // right transitioning in/out - body = String::new(); - } else { - // right outside - body = String::new(); - } - print_str_at(if self.column < 0 { 0 } else { self.column as u16 }, self.row, body.as_str()) + let ufo_str_slice = &UFO_STR[left_cutoff..right_cutoff]; + let col = max(0, min(self.column, (WIDTH as i16) - (right_cutoff as i16))) as u16; + print_str_at(col, self.row, ufo_str_slice); } fn is_on_screen(&self) -> bool { - self.column > -(UFO_STR.len() as i16) && self.column < WIDTH as i16 + self.column >= -(UFO_STR.len() as i16) + && self.column <= (WIDTH as i16) } } + +fn clear(ufo: &Ufo) { + match ufo.direction { + Right => { + if ufo.column >= 0 { + clear_pos(ufo.column as u16, ufo.row); + } + } + Left => { + let current_right = ufo.column + (UFO_STR.len() as i16) - 1; + if current_right >= 0 && current_right < (WIDTH as i16) { + clear_pos(current_right as u16, ufo.row); + } + } + _ => {} + }; +}