aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/main.rs20
-rw-r--r--src/state.rs21
-rw-r--r--src/viewport.rs62
3 files changed, 70 insertions, 33 deletions
diff --git a/src/main.rs b/src/main.rs
index d00db53..6348757 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,6 +1,7 @@
mod entities;
mod state;
mod tiling;
+mod viewport;
mod world;
use std::env;
@@ -17,6 +18,7 @@ use simplelog::*;
use entities::Player;
use state::State;
+use viewport::{CrossTermViewPort, ViewPort};
use world::{Dungeon, DOWN, LEFT, RIGHT, UP};
fn player_name() -> String {
@@ -45,10 +47,13 @@ fn main() {
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(term_size.0 as usize, (term_size.1 - 2) as usize, 5),
+ Dungeon::new(xsize, ysize, 5),
);
+ let mut window = CrossTermViewPort::new(xsize, ysize);
state.init();
let input = input();
@@ -57,18 +62,13 @@ fn main() {
// Main loop, dispatches events and calls rendering routines. Don't
// add any game logic here.
loop {
- state.render_player();
- state.render_level();
- state.render_entities();
- state.render_player();
-
- state.render_ui();
+ window.render_state(&state);
if let Some(event) = reader.next() {
match event {
InputEvent::Keyboard(KeyEvent::Char('q')) => break,
InputEvent::Keyboard(KeyEvent::Char('?')) => {
- state.ui_help();
+ window.ui_help();
}
InputEvent::Keyboard(KeyEvent::Char('j')) => state.move_player(DOWN).ignore(),
InputEvent::Keyboard(KeyEvent::Char('k')) => state.move_player(UP).ignore(),
@@ -83,11 +83,11 @@ fn main() {
// Stairs
InputEvent::Keyboard(KeyEvent::Char('>')) => match state.down_stairs() {
Ok(()) => (),
- Err(info) => state.notify(info),
+ Err(info) => window.notify(info),
},
InputEvent::Keyboard(KeyEvent::Char('<')) => match state.up_stairs() {
Ok(()) => (),
- Err(info) => state.notify(info),
+ Err(info) => window.notify(info),
},
_ => (),
}
diff --git a/src/state.rs b/src/state.rs
index 542f822..776f2bf 100644
--- a/src/state.rs
+++ b/src/state.rs
@@ -25,11 +25,21 @@ impl State {
self.dungeon.generate();
self.switch_level(0);
self.player.place(self.current_level().start_point());
+ self.fog_of_war();
+ }
+
+ pub fn get_grid(&self) -> Option<&TileGrid> {
+ self.grid.as_ref()
+ }
+
+ pub fn get_player(&self) -> &Character {
+ &self.player
}
pub fn switch_level(&mut self, num_level: usize) {
self.level = num_level;
self.grid = Some(self.current_level().to_tilegrid().unwrap());
+ self.fog_of_war();
}
pub fn current_level(&self) -> &Level {
@@ -56,7 +66,9 @@ impl State {
if !State::can_step_on(grid.block_at(loc.0, loc.1)) {
return Err(String::from("Can't move entity!"));
}
- self.player.move_by(dir)
+ let ret = self.player.move_by(dir);
+ self.fog_of_war();
+ ret
}
pub fn down_stairs(&mut self) -> Result<(), String> {
@@ -98,4 +110,11 @@ impl State {
_ => Err(String::from("Not on stairs!")),
}
}
+
+ pub fn fog_of_war(&mut self) {
+ self.grid
+ .as_mut()
+ .unwrap()
+ .clear_fog_of_war(self.player.location(), PLAYER_SIGHT);
+ }
}
diff --git a/src/viewport.rs b/src/viewport.rs
index afd11c1..37dfd21 100644
--- a/src/viewport.rs
+++ b/src/viewport.rs
@@ -1,5 +1,6 @@
use crossterm::cursor::MoveTo;
use crossterm::{execute, queue, Output};
+use log::debug;
use std::io::{stdout, Write};
use crate::entities::{Character, Entity, Player};
@@ -7,21 +8,28 @@ use crate::state::State;
use crate::tiling::{tile_to_str, Tile, TileGrid, TileType};
use crate::world::{apply_movement, Dungeon, Generatable, Level, Movement};
-
pub trait ViewPort {
- fn render_state(&mut self, &State);
+ fn render_state(&mut self, state: &State);
}
pub struct CrossTermViewPort {
xsize: usize,
- ysize: usize
+ ysize: usize,
+ // Use below when switching to moveable window
+ //start: (usize, usize)
}
impl CrossTermViewPort {
- pub fn render_level(&self) {
+ pub fn new(xsize: usize, ysize: usize) -> CrossTermViewPort {
+ CrossTermViewPort { xsize, ysize }
+ }
+
+ fn draw_level(&self, state: &State) {
let mut sout = stdout();
+ let grid = state.get_grid().unwrap();
execute!(sout, MoveTo(0, 0)).unwrap();
- for (linenum, line) in self.grid.as_ref().unwrap().raw_data().iter().enumerate() {
+ for (linenum, line) in grid.raw_data().iter().enumerate() {
+ debug!("Drawing linenum {} -- {:?}", linenum, line);
let linestr = line.iter().map(tile_to_str).collect::<Vec<&str>>();
let mut linestr2 = String::from("");
for chr in linestr {
@@ -32,12 +40,13 @@ impl CrossTermViewPort {
}
}
- fn render_entity(&self, entity: &dyn Entity) {
+ fn draw_entity(&self, state: &State, entity: &dyn Entity) {
if !entity.is_visible() || !entity.is_dirty() {
return;
}
+ let grid = state.get_grid().unwrap();
let dirt = entity.previous_location();
- let background = self.grid.as_ref().unwrap().block_at(dirt.0, dirt.1);
+ let background = grid.block_at(dirt.0, dirt.1);
let mut sout = stdout();
queue!(
sout,
@@ -50,32 +59,32 @@ impl CrossTermViewPort {
sout.flush().unwrap();
}
- pub fn render_entities(&self) {
- for e in self.current_level().entities.iter() {
- self.render_entity(&**e);
+ fn draw_entities(&self, state: &State) {
+ for e in state.current_level().entities.iter() {
+ self.draw_entity(state, &**e);
}
}
- pub fn render_player(&mut self) {
- self.render_entity(&self.player);
-
- self.grid
- .as_mut()
- .unwrap()
- .clear_fog_of_war(self.player.location(), PLAYER_SIGHT);
+ fn draw_player(&mut self, state: &State) {
+ self.draw_entity(state, state.get_player());
}
fn ui_state_position(&self) -> MoveTo {
- MoveTo(0, (self.dungeon.ysize()) as u16)
+ MoveTo(0, (self.ysize) as u16)
}
fn ui_notification_position(&self) -> MoveTo {
- MoveTo(0, (self.dungeon.ysize() + 1) as u16)
+ MoveTo(0, (self.ysize + 1) as u16)
}
- pub fn render_ui(&self) {
+ fn draw_ui(&self, state: &State) {
let mut sout = stdout();
- queue!(sout, self.ui_state_position(), Output(self.player.stats())).unwrap();
+ queue!(
+ sout,
+ self.ui_state_position(),
+ Output(state.get_player().stats())
+ )
+ .unwrap();
sout.flush().unwrap();
}
@@ -84,7 +93,7 @@ impl CrossTermViewPort {
queue!(
sout,
self.ui_notification_position(),
- Output(" ".repeat(self.dungeon.xsize())),
+ Output(" ".repeat(self.xsize)),
self.ui_notification_position(),
Output(message)
)
@@ -98,3 +107,12 @@ impl CrossTermViewPort {
))
}
}
+
+impl ViewPort for CrossTermViewPort {
+ fn render_state(&mut self, state: &State) {
+ self.draw_level(state);
+ self.draw_entities(state);
+ self.draw_player(state);
+ self.draw_ui(state);
+ }
+}