about summary refs log tree commit diff
path: root/src/game.rs
diff options
context:
space:
mode:
authorGriffin Smith <root@gws.fyi>2019-07-06T19·32-0400
committerGriffin Smith <root@gws.fyi>2019-07-06T19·32-0400
commit78a52142d191d25a74cb2124d5cca8a69d51ba7f (patch)
treedd023a823bae6cc427e32a497bd68db85bbfab4b /src/game.rs
parentde081d7b1d0b791b2e61f9cde7369ea11647e0ae (diff)
Make all drawing happen to a viewport
We now have an inner and outer viewport, and entity positions are
relative to the inner one while drawing happens to the outer one.
Diffstat (limited to 'src/game.rs')
-rw-r--r--src/game.rs94
1 files changed, 49 insertions, 45 deletions
diff --git a/src/game.rs b/src/game.rs
index a41d7f73fd75..6274ef573f58 100644
--- a/src/game.rs
+++ b/src/game.rs
@@ -1,30 +1,28 @@
-use std::thread;
 use crate::settings::Settings;
+use crate::types::Positioned;
 use crate::types::{BoundingBox, Dimensions, Position};
 use std::io::{self, StdinLock, StdoutLock, Write};
-use termion::cursor;
 use termion::input::Keys;
 use termion::input::TermRead;
 use termion::raw::RawTerminal;
 
-use crate::display;
+use crate::display::{self, Viewport};
+use crate::entities::Character;
 use crate::types::command::Command;
 
+type Stdout<'a> = RawTerminal<StdoutLock<'a>>;
+
 /// The full state of a running Game
 pub struct Game<'a> {
     settings: Settings,
 
-    /// The box describing the viewport. Generally the size of the terminal, and
-    /// positioned at 0, 0
-    viewport: BoundingBox,
+    viewport: Viewport<Stdout<'a>>,
 
     /// An iterator on keypresses from the user
     keys: Keys<StdinLock<'a>>,
 
-    stdout: RawTerminal<StdoutLock<'a>>,
-
-    /// The position of the character
-    character: Position,
+    /// The player character
+    character: Character,
 }
 
 impl<'a> Game<'a> {
@@ -37,35 +35,36 @@ impl<'a> Game<'a> {
     ) -> Game<'a> {
         Game {
             settings: settings,
-            viewport: BoundingBox::at_origin(Dimensions { w, h }),
+            viewport: Viewport {
+                outer: BoundingBox::at_origin(Dimensions { w, h }),
+                inner: BoundingBox::at_origin(Dimensions {
+                    w: w - 2,
+                    h: h - 2,
+                }),
+                out: stdout,
+            },
             keys: stdin.keys(),
-            stdout: stdout,
-            character: Position { x: 1, y: 1 },
+            character: Character::new(),
         }
     }
 
     /// Returns true if there's a collision in the game at the given Position
     fn collision_at(&self, pos: Position) -> bool {
-        !pos.within(self.viewport.inner())
+        !pos.within(self.viewport.inner)
+    }
+
+    fn draw_entities(&mut self) -> io::Result<()> {
+        self.viewport.draw(&self.character)
     }
 
     /// Run the game
-    pub fn run(mut self) {
+    pub fn run(mut self) -> io::Result<()> {
         info!("Running game");
-        write!(
-            self,
-            "{}{}@{}",
-            display::make_box(
-                display::BoxStyle::Thin,
-                self.viewport.dimensions
-            ),
-            cursor::Goto(2, 2),
-            cursor::Left(1),
-        )
-        .unwrap();
-        self.flush().unwrap();
+        self.viewport.init()?;
+        self.draw_entities()?;
+        self.flush()?;
         loop {
-            let mut character_moved = false;
+            let mut old_position = None;
             match Command::from_key(self.keys.next().unwrap().unwrap()) {
                 Some(Command::Quit) => {
                     info!("Quitting game due to user request");
@@ -73,46 +72,51 @@ impl<'a> Game<'a> {
                 }
 
                 Some(Command::Move(direction)) => {
-                    let new_pos = self.character + direction;
+                    let new_pos = self.character.position + direction;
                     if !self.collision_at(new_pos) {
-                        self.character = new_pos;
-                        character_moved = true;
+                        old_position = Some(self.character.position);
+                        self.character.position = new_pos;
                     }
                 }
                 _ => (),
             }
 
-            if character_moved {
-                debug!("char: {:?}", self.character);
-                write!(
-                    self,
-                    " {}@{}",
-                    cursor::Goto(self.character.x + 1, self.character.y + 1,),
-                    cursor::Left(1)
-                )
-                .unwrap();
+            match old_position {
+                Some(old_pos) => {
+                    self.viewport.clear(old_pos)?;
+                    self.viewport.draw(&self.character)?;
+                }
+                None => ()
             }
-            self.flush().unwrap();
+            self.flush()?;
+            debug!("{:?}", self.character);
         }
+        Ok(())
     }
 }
 
 impl<'a> Drop for Game<'a> {
     fn drop(&mut self) {
-        display::clear(self).unwrap();
+        display::clear(self).unwrap_or(());
     }
 }
 
 impl<'a> Write for Game<'a> {
     fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
-        self.stdout.write(buf)
+        self.viewport.write(buf)
     }
 
     fn flush(&mut self) -> io::Result<()> {
-        self.stdout.flush()
+        self.viewport.flush()
     }
 
     fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
-        self.stdout.write_all(buf)
+        self.viewport.write_all(buf)
+    }
+}
+
+impl<'a> Positioned for Game<'a> {
+    fn position(&self) -> Position {
+        Position { x: 0, y: 0 }
     }
 }