add a separate thread for input handling
This commit is contained in:
parent
e1ad59c8a6
commit
2f0e22c79c
2 changed files with 22 additions and 7 deletions
|
@ -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();
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
Loading…
Reference in a new issue