1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
use crate::keyboard::{KeyPosition, KeyState, VirtualKey};
use crate::platform::{Platform, PlatformProvider, SyncPlatform, WindowConfig};
use crate::systems::System;
use crate::time::FixedTimeStep;
use instant::Duration;
use rand;
use std::io::Write;
use std::sync::Arc;

use super::JoystickState;

/// Represents a platform which exclusively operates over text mode,
/// without any visible graphical output. This reads from and writes to the
/// terminal.
/// This platform runs synchronously.
pub struct TextPlatform;

impl TextPlatform {
  pub fn new() -> Self {
    Self {}
  }
}

impl Platform for TextPlatform {
  fn provider(&self) -> Arc<dyn PlatformProvider> {
    Arc::new(TextPlatformProvider::new())
  }
}

impl SyncPlatform for TextPlatform {
  fn run(&mut self, mut system: Box<dyn System>) {
    let mut timer = FixedTimeStep::new(60.0, Duration::from_secs_f64(1.0 / 60.0));

    loop {
      timer.do_update(&mut || system.tick());
    }
  }
}

pub struct TextPlatformProvider;

impl TextPlatformProvider {
  pub fn new() -> Self {
    Self {}
  }
}

impl PlatformProvider for TextPlatformProvider {
  fn request_window(&self, _config: WindowConfig) {}

  fn get_key_state(&self) -> KeyState<KeyPosition> {
    KeyState::new()
  }

  fn get_virtual_key_state(&self) -> KeyState<VirtualKey> {
    KeyState::new()
  }

  fn get_joystick_state(&self) -> JoystickState {
    JoystickState::empty()
  }

  fn print(&self, text: &str) {
    print!("{text}");
  }

  fn input(&self) -> String {
    let mut input = String::new();
    print!("> ");
    std::io::stdout().flush().unwrap();
    std::io::stdin()
      .read_line(&mut input)
      .expect("Failed to read line");
    input
  }

  fn random(&self) -> u8 {
    rand::random()
  }
}