diff options
author | Griffin Smith <root@gws.fyi> | 2019-07-06T02·45-0400 |
---|---|---|
committer | Griffin Smith <root@gws.fyi> | 2019-07-06T02·45-0400 |
commit | de081d7b1d0b791b2e61f9cde7369ea11647e0ae (patch) | |
tree | 687236ac6ca2d094053fa43112d967554531de86 /src/game.rs |
an @-sign in a box
Diffstat (limited to 'src/game.rs')
-rw-r--r-- | src/game.rs | 118 |
1 files changed, 118 insertions, 0 deletions
diff --git a/src/game.rs b/src/game.rs new file mode 100644 index 000000000000..a41d7f73fd75 --- /dev/null +++ b/src/game.rs @@ -0,0 +1,118 @@ +use std::thread; +use crate::settings::Settings; +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::types::command::Command; + +/// 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, + + /// An iterator on keypresses from the user + keys: Keys<StdinLock<'a>>, + + stdout: RawTerminal<StdoutLock<'a>>, + + /// The position of the character + character: Position, +} + +impl<'a> Game<'a> { + pub fn new( + settings: Settings, + stdout: RawTerminal<StdoutLock<'a>>, + stdin: StdinLock<'a>, + w: u16, + h: u16, + ) -> Game<'a> { + Game { + settings: settings, + viewport: BoundingBox::at_origin(Dimensions { w, h }), + keys: stdin.keys(), + stdout: stdout, + character: Position { x: 1, y: 1 }, + } + } + + /// 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()) + } + + /// Run the game + pub fn run(mut self) { + 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(); + loop { + let mut character_moved = false; + match Command::from_key(self.keys.next().unwrap().unwrap()) { + Some(Command::Quit) => { + info!("Quitting game due to user request"); + break; + } + + Some(Command::Move(direction)) => { + let new_pos = self.character + direction; + if !self.collision_at(new_pos) { + self.character = new_pos; + character_moved = true; + } + } + _ => (), + } + + if character_moved { + debug!("char: {:?}", self.character); + write!( + self, + " {}@{}", + cursor::Goto(self.character.x + 1, self.character.y + 1,), + cursor::Left(1) + ) + .unwrap(); + } + self.flush().unwrap(); + } + } +} + +impl<'a> Drop for Game<'a> { + fn drop(&mut self) { + display::clear(self).unwrap(); + } +} + +impl<'a> Write for Game<'a> { + fn write(&mut self, buf: &[u8]) -> io::Result<usize> { + self.stdout.write(buf) + } + + fn flush(&mut self) -> io::Result<()> { + self.stdout.flush() + } + + fn write_all(&mut self, buf: &[u8]) -> io::Result<()> { + self.stdout.write_all(buf) + } +} |