aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/events.rs10
-rw-r--r--src/main.rs63
-rw-r--r--src/viewport.rs73
3 files changed, 93 insertions, 53 deletions
diff --git a/src/events.rs b/src/events.rs
new file mode 100644
index 0000000..0619b18
--- /dev/null
+++ b/src/events.rs
@@ -0,0 +1,10 @@
+use crate::world::Movement;
+
+#[derive(Copy, Clone, Debug)]
+pub enum ViewportEvent {
+ Quit,
+ Help,
+ MovePlayer(Movement),
+ DownStairs,
+ UpStairs,
+}
diff --git a/src/main.rs b/src/main.rs
index 6348757..3f7f81c 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,25 +1,24 @@
mod entities;
+mod events;
mod state;
mod tiling;
mod viewport;
mod world;
-use std::env;
-use std::fs::File;
-use std::io::{stdout, Write};
-
-use crossterm::cursor;
-use crossterm::execute;
-use crossterm::input::{input, InputEvent, KeyEvent};
-use crossterm::screen::{EnterAlternateScreen, LeaveAlternateScreen, RawScreen};
-use crossterm::terminal;
use ignore_result::Ignore;
use simplelog::*;
+use std::env;
+use std::fs::File;
use entities::Player;
+use events::ViewportEvent;
use state::State;
use viewport::{CrossTermViewPort, ViewPort};
-use world::{Dungeon, DOWN, LEFT, RIGHT, UP};
+use world::Dungeon;
+
+const DUNGEON_SIZE_X: usize = 20;
+const DUNGEON_SIZE_Y: usize = 20;
+const DUNGEON_DEPTH: usize = 5;
fn player_name() -> String {
match env::var_os("USER") {
@@ -39,62 +38,34 @@ fn main() {
.unwrap();
}
- // Initialise the terminal, the raw alternate mode allows direct character
- // seeking and hides the prompt.
- let term_size = terminal::size().unwrap();
- execute!(stdout(), EnterAlternateScreen).unwrap();
- execute!(stdout(), cursor::Hide).unwrap();
- let _raw = RawScreen::into_raw_mode();
-
- // Initialise state, create the player and dungeon
- let xsize = term_size.0 as usize;
- let ysize = (term_size.1 - 2) as usize;
let mut state = State::new(
Player::new(player_name(), String::from("Warrior"), 30, 10, 10, 20),
- Dungeon::new(xsize, ysize, 5),
+ Dungeon::new(DUNGEON_SIZE_X, DUNGEON_SIZE_Y, DUNGEON_DEPTH),
);
- let mut window = CrossTermViewPort::new(xsize, ysize);
+ let mut window = CrossTermViewPort::new();
state.init();
- let input = input();
- let mut reader = input.read_sync();
-
// Main loop, dispatches events and calls rendering routines. Don't
// add any game logic here.
loop {
window.render_state(&state);
- if let Some(event) = reader.next() {
+ if let Some(event) = window.wait_input() {
match event {
- InputEvent::Keyboard(KeyEvent::Char('q')) => break,
- InputEvent::Keyboard(KeyEvent::Char('?')) => {
- window.ui_help();
- }
- InputEvent::Keyboard(KeyEvent::Char('j')) => state.move_player(DOWN).ignore(),
- InputEvent::Keyboard(KeyEvent::Char('k')) => state.move_player(UP).ignore(),
- InputEvent::Keyboard(KeyEvent::Char('h')) => state.move_player(LEFT).ignore(),
- InputEvent::Keyboard(KeyEvent::Char('l')) => state.move_player(RIGHT).ignore(),
- // Arrow keys for noobs
- InputEvent::Keyboard(KeyEvent::Down) => state.move_player(DOWN).ignore(),
- InputEvent::Keyboard(KeyEvent::Up) => state.move_player(UP).ignore(),
- InputEvent::Keyboard(KeyEvent::Left) => state.move_player(LEFT).ignore(),
- InputEvent::Keyboard(KeyEvent::Right) => state.move_player(RIGHT).ignore(),
-
- // Stairs
- InputEvent::Keyboard(KeyEvent::Char('>')) => match state.down_stairs() {
+ ViewportEvent::Quit => break,
+ ViewportEvent::MovePlayer(direction) => state.move_player(direction).ignore(),
+ ViewportEvent::DownStairs => match state.down_stairs() {
Ok(()) => (),
Err(info) => window.notify(info),
},
- InputEvent::Keyboard(KeyEvent::Char('<')) => match state.up_stairs() {
+ ViewportEvent::UpStairs => match state.up_stairs() {
Ok(()) => (),
Err(info) => window.notify(info),
},
_ => (),
}
}
+
// actors actions (normally attack / interact if on same location as the character)
}
-
- execute!(stdout(), LeaveAlternateScreen).unwrap();
- execute!(stdout(), cursor::Show).unwrap();
}
diff --git a/src/viewport.rs b/src/viewport.rs
index 37dfd21..1fd13aa 100644
--- a/src/viewport.rs
+++ b/src/viewport.rs
@@ -1,12 +1,17 @@
+use crate::events::ViewportEvent;
+use crate::world::{DOWN, LEFT, RIGHT, UP};
+use crossterm::cursor;
use crossterm::cursor::MoveTo;
+use crossterm::input::{input, InputEvent, KeyEvent, SyncReader};
+use crossterm::screen::{EnterAlternateScreen, LeaveAlternateScreen, RawScreen};
+use crossterm::terminal;
use crossterm::{execute, queue, Output};
use log::debug;
use std::io::{stdout, Write};
-use crate::entities::{Character, Entity, Player};
+use crate::entities::{Entity, Player};
use crate::state::State;
-use crate::tiling::{tile_to_str, Tile, TileGrid, TileType};
-use crate::world::{apply_movement, Dungeon, Generatable, Level, Movement};
+use crate::tiling::tile_to_str;
pub trait ViewPort {
fn render_state(&mut self, state: &State);
@@ -15,13 +20,31 @@ pub trait ViewPort {
pub struct CrossTermViewPort {
xsize: usize,
ysize: usize,
- // Use below when switching to moveable window
- //start: (usize, usize)
+ reader: SyncReader,
+ start: (usize, usize),
}
impl CrossTermViewPort {
- pub fn new(xsize: usize, ysize: usize) -> CrossTermViewPort {
- CrossTermViewPort { xsize, ysize }
+ pub fn new() -> CrossTermViewPort {
+ // Initialise the terminal, the raw alternate mode allows direct character
+ // seeking and hides the prompt.
+ let term_size = terminal::size().unwrap();
+ execute!(stdout(), EnterAlternateScreen).unwrap();
+ execute!(stdout(), cursor::Hide).unwrap();
+ let _raw = RawScreen::into_raw_mode();
+
+ // Initialise state, create the player and dungeon
+ let xsize = term_size.0 as usize;
+ let ysize = (term_size.1 - 2) as usize;
+
+ let input = input();
+
+ CrossTermViewPort {
+ xsize,
+ ysize,
+ reader: input.read_sync(),
+ start: (0, 0),
+ }
}
fn draw_level(&self, state: &State) {
@@ -106,6 +129,35 @@ impl CrossTermViewPort {
"quit: q, movement{up(k), down(j), left(h), right(l)}",
))
}
+
+ pub fn wait_input(&mut self) -> Option<ViewportEvent> {
+ if let Some(event) = self.reader.next() {
+ return match event {
+ InputEvent::Keyboard(KeyEvent::Char('q')) => Some(ViewportEvent::Quit),
+ InputEvent::Keyboard(KeyEvent::Char('?')) => {
+ self.ui_help();
+ None
+ }
+ InputEvent::Keyboard(KeyEvent::Char('j')) => Some(ViewportEvent::MovePlayer(DOWN)),
+ InputEvent::Keyboard(KeyEvent::Char('k')) => Some(ViewportEvent::MovePlayer(UP)),
+ InputEvent::Keyboard(KeyEvent::Char('h')) => Some(ViewportEvent::MovePlayer(LEFT)),
+ InputEvent::Keyboard(KeyEvent::Char('l')) => Some(ViewportEvent::MovePlayer(RIGHT)),
+ // Arrow keys for noobs
+ InputEvent::Keyboard(KeyEvent::Down) => Some(ViewportEvent::MovePlayer(DOWN)),
+ InputEvent::Keyboard(KeyEvent::Up) => Some(ViewportEvent::MovePlayer(UP)),
+ InputEvent::Keyboard(KeyEvent::Left) => Some(ViewportEvent::MovePlayer(LEFT)),
+ InputEvent::Keyboard(KeyEvent::Right) => Some(ViewportEvent::MovePlayer(RIGHT)),
+
+ // Stairs
+ InputEvent::Keyboard(KeyEvent::Char('>')) => Some(ViewportEvent::DownStairs),
+ InputEvent::Keyboard(KeyEvent::Char('<')) => Some(ViewportEvent::UpStairs),
+
+ // No match
+ _ => None,
+ };
+ }
+ None
+ }
}
impl ViewPort for CrossTermViewPort {
@@ -116,3 +168,10 @@ impl ViewPort for CrossTermViewPort {
self.draw_ui(state);
}
}
+
+impl Drop for CrossTermViewPort {
+ fn drop(&mut self) {
+ execute!(stdout(), LeaveAlternateScreen).unwrap();
+ execute!(stdout(), cursor::Show).unwrap();
+ }
+}