input improvemnts

This commit is contained in:
Andrei Stoica 2024-11-15 08:21:05 -05:00
parent fffd504a3c
commit 504c882787
1 changed files with 81 additions and 10 deletions

View File

@ -3,7 +3,7 @@ use std::io::stdout;
use std::sync::mpsc::{self, Receiver}; use std::sync::mpsc::{self, Receiver};
use std::thread; use std::thread;
use crossterm::cursor::MoveTo; use crossterm::cursor::{self, MoveTo};
use crossterm::event::{read, Event, KeyCode}; use crossterm::event::{read, Event, KeyCode};
use crossterm::execute; use crossterm::execute;
use crossterm::style::{Print, Stylize}; use crossterm::style::{Print, Stylize};
@ -17,23 +17,39 @@ use rand::random;
fn main() { fn main() {
let g = Game::new(); let g = Game::new();
execute!(stdout(), EnterAlternateScreen); execute!(stdout(), EnterAlternateScreen, cursor::Hide);
enable_raw_mode(); enable_raw_mode();
g.render_board(); g.render_board();
let game = game_loop( let game = game_loop(
g, g,
2, 4,
2.0, 0.16,
|g| { |g| {
let mut inputQueue = Vec::<Direction>::new();
while let Ok(input) = g.game.input.try_recv() { while let Ok(input) = g.game.input.try_recv() {
if let Ok(direction) = input.try_into() { if let Ok(direction) = Direction::try_from(input) {
g.game.direction = direction; inputQueue.push(direction.clone());
match direction {
Direction::Up if !matches!(g.game.direction, Direction::Down) => {
g.game.direction = direction
}
Direction::Down if !matches!(g.game.direction, Direction::Up) => {
g.game.direction = direction
}
Direction::Right if !matches!(g.game.direction, Direction::Left) => {
g.game.direction = direction
}
Direction::Left if !matches!(g.game.direction, Direction::Right) => {
g.game.direction = direction
}
_ => {}
};
} else { } else {
g.exit(); g.exit();
} }
} }
if let Err(gg) = g.game.update() { let update_step = g.game.get_step(&mut inputQueue);
if let Err(gg) = g.game.update(update_step) {
g.exit(); g.exit();
} }
}, },
@ -42,7 +58,7 @@ fn main() {
}, },
); );
disable_raw_mode(); disable_raw_mode();
execute!(stdout(), LeaveAlternateScreen); execute!(stdout(), LeaveAlternateScreen, cursor::Show);
} }
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
@ -69,6 +85,15 @@ enum Input {
Exit, Exit,
} }
#[derive(Debug, Clone, Copy)]
enum Step {
Turn(Direction),
MoveAndTurn {
step_direction: Direction,
new_direction: Direction,
},
}
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]
enum GameOverState { enum GameOverState {
SnakeBite, SnakeBite,
@ -94,6 +119,18 @@ impl TryFrom<Input> for Direction {
} }
} }
impl Direction {
fn valid_direction(cur_direction: &Direction, new_direction: &Direction) -> bool {
match new_direction {
Direction::Up if matches!(cur_direction, Direction::Down) => false,
Direction::Down if matches!(cur_direction, Direction::Up) => false,
Direction::Right if matches!(cur_direction, Direction::Left) => false,
Direction::Left if matches!(cur_direction, Direction::Right) => false,
_ => true,
}
}
}
#[derive(Debug)] #[derive(Debug)]
struct Game { struct Game {
apple_pos: (usize, usize), apple_pos: (usize, usize),
@ -156,7 +193,22 @@ impl Game {
} }
} }
fn update(&mut self) -> Result<(), GameOverState> { fn get_step(&self, input: &Vec<Direction>) -> Step {
match input.len() {
1 if Direction::valid_direction(&self.direction, &input[0]) => Step::Turn(input[0]),
2.. if Direction::valid_direction(&self.direction, &input[input.len() - 2])
&& Direction::valid_direction(&input[input.len() - 2], &input[input.len() - 1]) =>
{
Step::MoveAndTurn {
step_direction: input[input.len() - 2],
new_direction: input[input.len() - 1],
}
}
_ => Step::Turn(self.direction),
}
}
fn advance(&mut self) -> Result<(), GameOverState> {
let next_pos = self.next_pos()?; let next_pos = self.next_pos()?;
match self.check_pos(next_pos)? { match self.check_pos(next_pos)? {
@ -174,6 +226,25 @@ impl Game {
Ok(()) Ok(())
} }
fn update(&mut self, step: Step) -> Result<(), GameOverState> {
match step {
Step::Turn(direction) => {
self.direction = direction;
self.advance()?;
}
Step::MoveAndTurn {
step_direction,
new_direction,
} => {
self.direction = step_direction;
self.advance()?;
self.direction = new_direction;
}
}
std::thread::sleep(std::time::Duration::from_millis(250));
Ok(())
}
fn gen_apple(max_x: usize, max_y: usize) -> (usize, usize) { fn gen_apple(max_x: usize, max_y: usize) -> (usize, usize) {
let x = random::<usize>() % max_x; let x = random::<usize>() % max_x;
let y = random::<usize>() % max_y; let y = random::<usize>() % max_y;