diff options
| -rw-r--r-- | src/main.rs | 65 |
1 files changed, 23 insertions, 42 deletions
diff --git a/src/main.rs b/src/main.rs index 0d73c83..3b36b2e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,7 +1,6 @@ use libc::termios; use std::error::Error; -use std::io::{stderr, stdout, Read, Write}; -use std::sync::mpsc::{Receiver, SyncSender, TryRecvError}; +use std::io::{stderr, stdin, stdout, Read, Write}; use std::time::{Duration, SystemTime}; fn rand(max: i32) -> i32 { @@ -50,8 +49,6 @@ impl Dir { struct Screen { old_attr: termios, - keys: Receiver<Dir>, - cancel: SyncSender<()>, } impl Screen { @@ -73,37 +70,12 @@ impl Screen { let mut raw = std::mem::zeroed(); libc::cfmakeraw(&mut raw); raw.c_cc[libc::VMIN] = 0; - raw.c_cc[libc::VTIME] = 1; // 100ms timeout + raw.c_cc[libc::VTIME] = 0; if libc::tcsetattr(1, libc::TCSANOW, &raw) < 0 { return Err(Box::from("tcsetattr failed")); } } - let (key_tx, key_rx) = std::sync::mpsc::sync_channel(4); - let (cancel_tx, cancel_rx) = std::sync::mpsc::sync_channel(0); - std::thread::spawn(move || { - let mut stdin = std::io::stdin().lock(); - let mut buf = [0; 3]; - while let Err(TryRecvError::Empty) = cancel_rx.try_recv() { - let Ok(n) = stdin.read(&mut buf) else { - continue; - }; - if n < 3 || buf[0] != 27 || buf[1] != b'[' { - continue; - } - let key = match buf[2] { - b'A' => Dir::Up, - b'B' => Dir::Down, - b'C' => Dir::Right, - b'D' => Dir::Left, - _ => { - continue; - } - }; - let _ = key_tx.try_send(key); - } - }); - clear()?; move_cursor(pos(0, 0))?; for _ in 0..Screen::COLS { @@ -120,27 +92,36 @@ impl Screen { write!(stdout(), "-")?; } - Ok(Screen { - old_attr: attr, - keys: key_rx, - cancel: cancel_tx, - }) - } - - fn read_key(&self) -> Option<Dir> { - self.keys.try_recv().ok() + Ok(Screen { old_attr: attr }) } } impl Drop for Screen { fn drop(&mut self) { - self.cancel.send(()).unwrap(); unsafe { libc::tcsetattr(1, libc::TCSANOW, &self.old_attr); } } } +fn read_key() -> Result<Dir, Box<dyn Error>> { + let mut buf = [0; 3]; + let n = stdin().read(&mut buf)?; + if n < 3 || buf[0] != 27 || buf[1] != b'[' { + return Err(Box::from("unexpected input")); + } + let key = match buf[2] { + b'A' => Dir::Up, + b'B' => Dir::Down, + b'C' => Dir::Right, + b'D' => Dir::Left, + _ => { + return Err(Box::from("unexpected input")); + } + }; + Ok(key) +} + fn in_bounds(pos: Pos) -> bool { (1..Screen::ROWS - 1).contains(&pos.row) && (1..Screen::COLS - 1).contains(&pos.col) } @@ -264,7 +245,7 @@ impl Fruit { } fn snake() -> Result<i64, Box<dyn Error>> { - let screen = Screen::init()?; + let _screen = Screen::init()?; let mut snake = Snake { body: vec![pos(Screen::ROWS / 2, Screen::COLS / 2)], direction: Dir::Right, @@ -287,7 +268,7 @@ fn snake() -> Result<i64, Box<dyn Error>> { std::thread::sleep(delay); snake.erase()?; - if let Some(dir) = screen.read_key() { + if let Ok(dir) = read_key() { if dir != snake.direction.opposite() || snake.body.len() == 1 { snake.direction = dir; } |
