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