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
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
|
use std::io::{Read, Write};
use termion::{
cursor::HideCursor, event::Key, input::TermRead, raw::IntoRawMode, screen::AlternateScreen,
};
use crate::{
entity::{Controllable, Player},
error::Result,
physics::Vector,
structure::Building,
Render, Velocity,
};
#[derive(Debug)]
pub(crate) enum Command {
Quit,
UpdatePlayer,
}
#[derive(Debug, Default)]
pub struct Game {
pub player: Player,
pub structures: Vec<Building>,
}
impl Game {
pub fn run_loop<R: Read, W: IntoRawMode>(&mut self, reader: R, writer: W) -> Result<()> {
let mut screen = AlternateScreen::from(HideCursor::from(writer).into_raw_mode().unwrap());
self.write_screen(&mut screen)?;
for key in reader.keys() {
match self.handle_input(key?) {
Some(Command::Quit) => break,
Some(Command::UpdatePlayer) => &mut self.update()?,
None => continue,
};
self.write_screen(&mut screen)?;
}
write!(screen, "{}", termion::cursor::Show).map_err(From::from)
}
fn write_screen(&self, writer: &mut impl Write) -> Result<()> {
write!(writer, "{}", termion::clear::All)?;
self.player.render(writer)?;
for entity in &self.structures {
entity.render(writer)?;
}
writer.flush().map_err(From::from)
}
fn handle_input(&mut self, key: Key) -> Option<Command> {
match key {
Key::Char('q') => Some(Command::Quit),
_ => self.player.handle_input(key),
}
}
fn update(&mut self) -> Result<()> {
self.player.tick_time()?;
self.player.set_velocity(Vector::default())
}
}
#[cfg(test)]
mod tests {
use std::io::stdout;
use crate::{structure::Building, Game, Position};
#[test]
fn run_game() {
let stdin = "q".as_bytes();
let stdout = stdout();
let mut game = Game::default();
if let Err(err) = game.run_loop(stdin, stdout) {
eprintln!("{}", err)
}
}
#[test]
fn move_player() {
let stdin = "sssdddq".as_bytes();
let stdout = stdout();
let mut game = Game::default();
if let Err(err) = game.run_loop(stdin, stdout) {
eprintln!("{}", err)
}
}
}
|