add a separate thread for input handling

This commit is contained in:
Denis-Cosmin Nutiu 2024-12-10 18:35:04 +02:00
parent e1ad59c8a6
commit 2f0e22c79c
2 changed files with 22 additions and 7 deletions

View file

@ -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<D, S, I> Emulator<D, S, I>
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<T>(&mut self) -> Result<(), anyhow::Error> {
let mut tick_timer = Instant::now();
let target_fps: u128 = 60;
let (tx, rx): (Sender<u16>, Receiver<u16>) = 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<u16>) {
let received_input = receiver.try_recv();
if let Ok(key_pressed) = received_input {
if key_pressed == 0xFF {
// Exit requested
self.display.clear();

View file

@ -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();