summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRose Hogenson <rosehogenson@posteo.net>2024-01-19 23:29:31 -0800
committerRose Hogenson <rosehogenson@posteo.net>2024-01-19 23:29:31 -0800
commit93c437d0708705395638fc832d2f85d0829d33c1 (patch)
tree01c15858bea66ef8bf5377d62a2d440d43d72b49
parent3af41c3bfd38e6a8d2c8509f48a7691f45678fbb (diff)
downloadsnake-93c437d0708705395638fc832d2f85d0829d33c1.tar.zst
Read directly in the main game loop.
Turns out this is just fine and doesn't cause any issue at all.
-rw-r--r--src/main.rs65
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;
}