117 lines
3.5 KiB
Rust
117 lines
3.5 KiB
Rust
use rand::Rng;
|
|
|
|
use crate::{Direction, MAX_UFO_ROW, MIN_UFO_ROW, TANK_STR, UFO_STR, WIDTH};
|
|
use crate::Direction::{Down, Left, Right};
|
|
use crate::terminal::print_str_at;
|
|
|
|
pub trait Movable<T> {
|
|
fn create() -> T;
|
|
fn mov(&mut self, direction: Direction);
|
|
fn draw(&self);
|
|
fn is_on_screen(&self) -> bool;
|
|
}
|
|
|
|
impl Movable<Ufo> for Ufo {
|
|
fn create() -> Ufo {
|
|
let mut rng = rand::thread_rng();
|
|
let direction: Direction = if rng.gen() { Left } else { Right };
|
|
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,
|
|
// If the UFO is moving left, we will initially place it just at the right edge.
|
|
Left => WIDTH as i16 - 1,
|
|
// 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 }
|
|
}
|
|
|
|
fn mov(&mut self, direction: Direction) {
|
|
let ufo_str_len = UFO_STR.len() as i16;
|
|
|
|
match direction {
|
|
Down => { todo!("Implement crash movement (down + direction)") }
|
|
_ => {
|
|
match self.direction {
|
|
Left => {
|
|
if self.column >= -ufo_str_len {
|
|
self.column -= 1;
|
|
}
|
|
}
|
|
Right => {
|
|
if self.column < WIDTH as i16 {
|
|
self.column += 1;
|
|
}
|
|
}
|
|
_ => { /* Ignore, this can't be the case. */ }
|
|
};
|
|
}
|
|
};
|
|
}
|
|
|
|
fn draw(&self) {
|
|
let mut body: String;
|
|
let ufo_str_len = UFO_STR.len() as i16;
|
|
|
|
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())
|
|
}
|
|
|
|
fn is_on_screen(&self) -> bool {
|
|
self.column > -(UFO_STR.len() as i16) && self.column < WIDTH as i16
|
|
}
|
|
}
|
|
|
|
impl Movable<Tank> for Tank {
|
|
fn create() -> Tank {
|
|
let column = (WIDTH - TANK_STR.len() as u16) / 2;
|
|
Tank { column }
|
|
}
|
|
|
|
fn mov(&mut self, direction: Direction) {
|
|
todo!("Implement tank movement")
|
|
}
|
|
|
|
fn draw(&self) {
|
|
todo!("Implement drawing tank")
|
|
}
|
|
|
|
fn is_on_screen(&self) -> bool {
|
|
todo!("Implement tank visibility check")
|
|
}
|
|
}
|
|
|
|
pub struct Ufo {
|
|
row: u16,
|
|
column: i16,
|
|
direction: Direction,
|
|
}
|
|
|
|
pub struct Tank {
|
|
column: u16,
|
|
}
|