diff --git a/src/emulator.rs b/src/emulator.rs index 6248357..f8a852f 100644 --- a/src/emulator.rs +++ b/src/emulator.rs @@ -10,6 +10,9 @@ use rand::Rng; use std::fs::File; use std::io::Read; use std::path::Path; +use std::sync::mpsc; +use std::sync::mpsc::{Receiver, Sender}; +use std::thread; use std::thread::sleep; use std::time::{Duration, Instant}; @@ -72,9 +75,9 @@ where impl Emulator where - D: Display, - S: SoundModule, - I: InputModule, + D: Display + 'static, + S: SoundModule + 'static, + I: InputModule + Clone + Send + 'static, { /// Creates a new `Emulator` instance. /// @@ -123,12 +126,21 @@ where fn emulation_loop(&mut self) -> Result<(), anyhow::Error> { let mut tick_timer = Instant::now(); let target_fps: u128 = 60; + + let (tx, rx): (Sender, Receiver) = mpsc::channel(); + let mut input_module_clone = self.input_module.clone(); + thread::spawn(move || loop { + let key = input_module_clone.get_key_pressed(); + if let Some(some_key) = key { + let _ = tx.send(some_key); + } + }); loop { let now = Instant::now(); let elapsed_time = now.duration_since(tick_timer); let elapsed_ms = elapsed_time.as_millis(); if elapsed_ms >= (1000 / target_fps) { - self.handle_input(); + self.handle_input(&rx); // Handle sound and delay timer. self.handle_timers(); @@ -163,8 +175,9 @@ where } /// Handle the input - fn handle_input(&mut self) { - if let Some(key_pressed) = self.input_module.get_key_pressed() { + fn handle_input(&mut self, receiver: &Receiver) { + let received_input = receiver.try_recv(); + if let Ok(key_pressed) = received_input { if key_pressed == 0xFF { // Exit requested self.display.clear(); diff --git a/src/input.rs b/src/input.rs index ec039e8..9c3e56c 100644 --- a/src/input.rs +++ b/src/input.rs @@ -10,6 +10,7 @@ pub trait InputModule { } /// NoInput always returns none when queried for input. +#[derive(Clone)] pub struct NoInput; impl InputModule for NoInput { @@ -19,6 +20,7 @@ impl InputModule for NoInput { } /// CrossTermInput implements input events via the crossterm crate. +#[derive(Clone)] pub struct CrossTermInput { initialized: bool, } @@ -41,7 +43,7 @@ impl InputModule for CrossTermInput { if !self.initialized { panic!("CrossTermInput needs to be constructed using ::new") } - if let Ok(true) = poll(Duration::from_millis(1)) { + if let Ok(true) = poll(Duration::from_millis(100)) { // It's guaranteed that read() won't block if `poll` returns `Ok(true)` let read_result = read();