summaryrefslogtreecommitdiffstats
path: root/src/game.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/game.rs')
-rw-r--r--src/game.rs98
1 files changed, 98 insertions, 0 deletions
diff --git a/src/game.rs b/src/game.rs
new file mode 100644
index 0000000..0358638
--- /dev/null
+++ b/src/game.rs
@@ -0,0 +1,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)
+ }
+ }
+}