89 lines
2.7 KiB
Rust
89 lines
2.7 KiB
Rust
use std::cmp::{max, min};
|
|
|
|
use rand::Rng;
|
|
|
|
use crate::Direction;
|
|
use crate::Direction::{Left, Right};
|
|
use crate::movable::Movable;
|
|
use crate::terminal::{clear_pos, MAX_UFO_ROW, MIN_UFO_ROW, print_str_at, WIDTH};
|
|
|
|
const UFO_STR: &str = "<=000=>";
|
|
|
|
pub struct Ufo {
|
|
row: u16,
|
|
column: i16,
|
|
direction: Direction,
|
|
}
|
|
|
|
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),
|
|
// If the UFO is moving left, we will initially place it just at the right edge.
|
|
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.")
|
|
};
|
|
let ufo = Ufo { row, column, direction };
|
|
ufo.draw();
|
|
ufo
|
|
}
|
|
|
|
fn mov(&mut self, _direction: Direction) {
|
|
clear(self);
|
|
|
|
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 {
|
|
self.column += 1;
|
|
}
|
|
}
|
|
_ => { /* Ignore, this can't be the case. */ }
|
|
};
|
|
|
|
self.draw();
|
|
}
|
|
|
|
fn draw(&self) {
|
|
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;
|
|
|
|
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)
|
|
}
|
|
}
|
|
|
|
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);
|
|
}
|
|
}
|
|
_ => {}
|
|
};
|
|
}
|