From 8351d474150215598241b5aabacb4db863d0cd87 Mon Sep 17 00:00:00 2001 From: Guillaume Pasquet Date: Tue, 12 Nov 2019 16:47:22 +0100 Subject: Some refactor, better render loop --- src/entities.rs | 39 +++++++++++++-------------------------- src/main.rs | 19 ++++++++----------- src/state.rs | 40 ++++++++++++++++++++++++++++++---------- src/tiling.rs | 9 +-------- src/world.rs | 16 ++-------------- 5 files changed, 54 insertions(+), 69 deletions(-) diff --git a/src/entities.rs b/src/entities.rs index a01d86a..50841ab 100644 --- a/src/entities.rs +++ b/src/entities.rs @@ -7,6 +7,8 @@ use crate::tiling::TileType; pub trait Entity { fn info(&self) -> String; fn place(&mut self, location: Point); + fn get_tiletype(&self) -> &TileType; + fn get_location(&self) -> &Point; } #[derive(Clone)] @@ -24,10 +26,6 @@ pub struct Character { tile_type: TileType } -pub trait Render { - fn render(&self, window: &Window); -} - pub trait Enemy { fn new( class: String, @@ -49,8 +47,7 @@ pub trait Player { attack: i32, dodge: i32, luck: i32, - level: i32, - location: Point + level: i32 ) -> Self; fn damage(&mut self, damage_amount: i32); fn heal(&mut self, heal_amount: i32); @@ -59,23 +56,6 @@ pub trait Player { fn stats(&self) -> String; } -impl Render for Character { - fn render(&self, window: &Window) { - // window.mv(window.get_max_y() - 2, 0); - // window.clrtoeol(); - - // window.refresh(); - - // window.addstr(self.character.info() + "\n"); - - // window.mv(self.character.location.1 as i32,self.character.location.0 as i32); - // window.refresh(); - // draw_block(&window, self.character.tile_type); - // window.refresh(); - - } -} - impl Entity for Character { fn place(&mut self, location: Point) { self.location = location; @@ -87,6 +67,14 @@ impl Entity for Character { self.class, self.health, self.attack, self.dodge, self.luck ) } + + fn get_tiletype(&self) -> &TileType { + &self.tile_type + } + + fn get_location(&self) -> &Point { + &self.location + } } impl Enemy for Character { @@ -126,8 +114,7 @@ impl Player for Character { attack: i32, dodge: i32, luck: i32, - level: i32, - location: Point + level: i32 ) -> Character { Character { name: name, @@ -139,7 +126,7 @@ impl Player for Character { luck: luck, xp: 0, level: 0, - location: location, + location: (0, 0), tile_type: TileType::Player } } diff --git a/src/main.rs b/src/main.rs index b59d587..599c65c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,7 +1,6 @@ extern crate rand; extern crate pancurses; -#[macro_use] extern crate text_io; mod state; @@ -31,28 +30,26 @@ fn main() { 10, 10, 20, - 1, - (0, 0) + 1 ), - Dungeon::new(window.get_max_x() as usize, window.get_max_y() as usize, 5), + Dungeon::new(window.get_max_x() as usize, (window.get_max_y() - 2) as usize, 5), ); state.init(); window.keypad(true); noecho(); - + + state.render_level(&window); + loop { - // update actors - - state.render_level(&window); + // update + state.render_entities(&window); - // update character - state.show_character(&window); + state.render_player(&window); // get input and execute it match window.getch() { - Some(Input::Character('h')) => { window.addstr("q: quit\n"); }, // Some(Input::KeyDown) => { window.addstr("down\n"); }, // Some(Input::KeyUp) => { window.addch('b'); }, diff --git a/src/state.rs b/src/state.rs index 1f50f1a..afc702d 100644 --- a/src/state.rs +++ b/src/state.rs @@ -1,38 +1,58 @@ use pancurses::Window; -use std::env; -use crate::entities::{Character, Entity, Render}; +use crate::tiling::{TileType, tile_to_str}; +use crate::entities::{Character, Entity}; use crate::world::{Dungeon, Generatable, Level}; pub struct State { - pub character: Character, + pub player: Character, pub dungeon: Dungeon, pub level: usize, } +pub fn draw_block(window: &Window, block: &TileType) { + window.printw(tile_to_str(block)); +} + impl State { pub fn new( - character: Character, + player: Character, dungeon: Dungeon, ) -> State { State { - character: character, - dungeon: dungeon, + player, + dungeon, level: 0, } } pub fn init(&mut self) { self.dungeon.generate(); - self.character.place(self.current_level().get_start_point()); + self.player.place(self.current_level().get_start_point()); } pub fn render_level(&self, window: &Window) { - self.current_level().render(window); + let grid = self.current_level().to_tilegrid().unwrap(); + + for (linenum, line) in grid.raw_data().iter().enumerate() { + for block in line.iter() { + draw_block(&window, &block); + } + window.mv(linenum as i32, 0); + } + } + + fn render_entity(&self, entity: &dyn Entity, window: &Window) { + window.mv(entity.get_location().1 as i32, entity.get_location().0 as i32); + draw_block(window, entity.get_tiletype()); + } + + pub fn render_entities(&self, window: &Window) { + // TODO } - pub fn show_character(&self, window: &Window) { - self.character.render(window); + pub fn render_player(&self, window: &Window) { + self.render_entity(&self.player, window) } fn current_level(&self) -> &Level { diff --git a/src/tiling.rs b/src/tiling.rs index d443fb6..bc1bd50 100644 --- a/src/tiling.rs +++ b/src/tiling.rs @@ -1,8 +1,5 @@ extern crate pancurses; -use pancurses::{Window}; - - pub struct TileGrid { grid: Vec> } @@ -41,7 +38,7 @@ impl<'a> TileGrid { } } -fn tile_to_str(tile: &TileType) -> &str { +pub fn tile_to_str(tile: &TileType) -> &str { match tile { TileType::Floor => ".", TileType::Wall => "#", @@ -53,10 +50,6 @@ fn tile_to_str(tile: &TileType) -> &str { } } -pub fn draw_block(window: &Window, block: &TileType) { - window.printw(tile_to_str(block)); -} - pub trait Tileable { fn tile(&self, grid: &mut TileGrid) -> Result<(), String>; } diff --git a/src/world.rs b/src/world.rs index 9f58030..7652157 100644 --- a/src/world.rs +++ b/src/world.rs @@ -1,7 +1,6 @@ use rand::Rng; -use pancurses::{Window}; use crate::entities::{Character, Entity, Enemy}; -use crate::tiling::{TileGrid, Tileable, TileType, draw_block}; +use crate::tiling::{TileGrid, Tileable, TileType}; pub type Point = (usize, usize); @@ -226,7 +225,7 @@ impl Level { } } - fn to_tilegrid(&self) -> Result { + pub fn to_tilegrid(&self) -> Result { let mut grid = TileGrid::new(self.xsize, self.ysize); for room in &self.rooms { @@ -250,17 +249,6 @@ impl Level { return (0,0) } - pub fn render(&self, window: &Window) { - let grid = self.to_tilegrid().unwrap(); - - for (linenum, line) in grid.raw_data().iter().enumerate() { - for block in line.iter() { - draw_block(&window, &block); - } - window.mv(linenum as i32, 0); - } - } - pub fn get_entrance(&self) -> Point { self.entrance } -- cgit v1.2.3 From 5881f4738175a32a4890ebf14d689ae0888a5701 Mon Sep 17 00:00:00 2001 From: Guillaume Pasquet Date: Tue, 12 Nov 2019 17:01:26 +0100 Subject: Place enemies --- src/state.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/state.rs b/src/state.rs index afc702d..0523442 100644 --- a/src/state.rs +++ b/src/state.rs @@ -48,7 +48,9 @@ impl State { } pub fn render_entities(&self, window: &Window) { - // TODO + for e in self.current_level().entities.iter() { + self.render_entity(&**e, window); + } } pub fn render_player(&self, window: &Window) { -- cgit v1.2.3 From 53e72c91a743b34eda2db77b69f593e15361623b Mon Sep 17 00:00:00 2001 From: Guillaume Pasquet Date: Wed, 13 Nov 2019 11:49:48 +0100 Subject: Updated screenshot --- img/screenshot.png | Bin 3212 -> 225307 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/img/screenshot.png b/img/screenshot.png index 2fe5cbd..ff8ae77 100644 Binary files a/img/screenshot.png and b/img/screenshot.png differ -- cgit v1.2.3 From d6bda2f1662c082b98ac5f05ac9acb5838c1db67 Mon Sep 17 00:00:00 2001 From: Guillaume Pasquet Date: Wed, 13 Nov 2019 13:46:46 +0100 Subject: Better entities --- src/entities.rs | 81 +++++++++++++++++++++++++++-------------- src/main.rs | 17 +++++---- src/world.rs | 110 ++++++++++++++++++++++++++++++++++---------------------- 3 files changed, 130 insertions(+), 78 deletions(-) diff --git a/src/entities.rs b/src/entities.rs index 50841ab..d462fa9 100644 --- a/src/entities.rs +++ b/src/entities.rs @@ -1,14 +1,27 @@ use std::cmp; -use pancurses::{Window}; -use crate::world::{Point}; use crate::tiling::TileType; +use crate::world::{apply_movement, Movement, Point}; pub trait Entity { + /// Get information about the entity fn info(&self) -> String; + /// Initial placement of the entity fn place(&mut self, location: Point); + /// Get the tiletype for the entity fn get_tiletype(&self) -> &TileType; + /// Get the entity's current location fn get_location(&self) -> &Point; + /// Get the entity's previous location (before it moved) + fn get_previous_location(&self) -> &Point; + /// Move the entity to another point + fn move_to(&mut self, location: Point); + /// Move the entity with a movement differential + fn move_by(&mut self, movement: Movement) -> Result<(), String>; + /// Know if the entity needs to be re-rendered + fn is_dirty(&self) -> bool; + /// Declare the entity clean + fn clean(&mut self); } #[derive(Clone)] @@ -17,38 +30,26 @@ pub struct Character { pub class: String, pub health: i32, pub level: i32, - pub location: Point, + location: Point, + previous_location: Point, + dirty: bool, max_health: i32, attack: i32, dodge: i32, luck: i32, xp: i32, - tile_type: TileType + tile_type: TileType, } pub trait Enemy { - fn new( - class: String, - health: i32, - attack: i32, - dodge: i32, - luck: i32, - location: Point - ) -> Self; + fn new(class: String, health: i32, attack: i32, dodge: i32, luck: i32, location: Point) + -> Self; fn set_tile_type(&mut self, tile_type: TileType); } pub trait Player { - fn new( - name: String, - class: String, - health: i32, - attack: i32, - dodge: i32, - luck: i32, - level: i32 - ) -> Self; + fn new(name: String, class: String, health: i32, attack: i32, dodge: i32, luck: i32) -> Self; fn damage(&mut self, damage_amount: i32); fn heal(&mut self, heal_amount: i32); fn attack(&self) -> i32; @@ -59,6 +60,8 @@ pub trait Player { impl Entity for Character { fn place(&mut self, location: Point) { self.location = location; + self.previous_location = location; + self.dirty = true; } fn info(&self) -> String { @@ -75,6 +78,29 @@ impl Entity for Character { fn get_location(&self) -> &Point { &self.location } + + fn get_previous_location(&self) -> &Point { + &self.previous_location + } + + fn move_to(&mut self, location: Point) { + self.previous_location = self.location; + self.location = location; + self.dirty = true; + } + + fn move_by(&mut self, movement: Movement) -> Result<(), String> { + self.previous_location = apply_movement(self.location, movement)?; + Ok(()) + } + + fn is_dirty(&self) -> bool { + self.dirty + } + + fn clean(&mut self) { + self.dirty = false; + } } impl Enemy for Character { @@ -84,7 +110,7 @@ impl Enemy for Character { attack: i32, dodge: i32, luck: i32, - location: Point + location: Point, ) -> Character { Character { name: class.clone(), @@ -97,7 +123,9 @@ impl Enemy for Character { level: 0, xp: 0, location: location, - tile_type: TileType::Character + previous_location: location, + tile_type: TileType::Character, + dirty: false, } } @@ -114,7 +142,6 @@ impl Player for Character { attack: i32, dodge: i32, luck: i32, - level: i32 ) -> Character { Character { name: name, @@ -127,7 +154,9 @@ impl Player for Character { xp: 0, level: 0, location: (0, 0), - tile_type: TileType::Player + previous_location: (0, 0), + tile_type: TileType::Player, + dirty: false, } } @@ -164,7 +193,7 @@ mod tests { use super::*; fn test_attack() { - let bob: Character = Enemy::new("Rogue".to_string(), 1, 4, 1, 4, (0, 0)); + let bob: Character = Enemy::new(String::from("Rogue"), 1, 4, 1, 4, (0, 0)); assert_eq!(bob.attack(), 6); } diff --git a/src/main.rs b/src/main.rs index 599c65c..9f5a432 100644 --- a/src/main.rs +++ b/src/main.rs @@ -24,13 +24,12 @@ fn main() { let mut state = State::new( Player::new( - "Kshar".to_string(), - "Warrior".to_string(), + String::from("Kshar"), + String::from("Warrior"), 30, 10, 10, - 20, - 1 + 20 ), Dungeon::new(window.get_max_x() as usize, (window.get_max_y() - 2) as usize, 5), ); @@ -50,11 +49,11 @@ fn main() { // get input and execute it match window.getch() { - Some(Input::Character('h')) => { window.addstr("q: quit\n"); }, - // Some(Input::KeyDown) => { window.addstr("down\n"); }, - // Some(Input::KeyUp) => { window.addch('b'); }, - // Some(Input::KeyLeft) => { window.addch('c'); }, - // Some(Input::KeyRight) => { window.addch('d'); }, + Some(Input::Character('?')) => { window.addstr("q: quit\n"); }, + Some(Input::Character('j')) => { window.addstr("down\n"); }, + Some(Input::Character('k')) => { window.addstr("up\n"); }, + Some(Input::Character('h')) => { window.addstr("left\n"); }, + Some(Input::Character('l')) => { window.addstr("right\n"); }, Some(Input::Character('q')) => break, Some(_) => (), None => (), diff --git a/src/world.rs b/src/world.rs index 7652157..73fc802 100644 --- a/src/world.rs +++ b/src/world.rs @@ -1,40 +1,50 @@ +use crate::entities::{Character, Enemy, Entity}; +use crate::tiling::{TileGrid, TileType, Tileable}; use rand::Rng; -use crate::entities::{Character, Entity, Enemy}; -use crate::tiling::{TileGrid, Tileable, TileType}; pub type Point = (usize, usize); +pub type Movement = (i8, i8); pub enum Direction { North, South, East, - West + West, } enum CorridorType { Horizontal, - Vertical + Vertical, } -const LEFT: (i8, i8) = (-1i8, 0); -const RIGHT: (i8, i8) = (1i8, 0); -const UP: (i8, i8) = (0, -1i8); -const DOWN: (i8, i8) = (0, 1i8); +const LEFT: Movement = (-1, 0); +const RIGHT: Movement = (1, 0); +const UP: Movement = (0, -1); +const DOWN: Movement = (0, 1); + +pub fn apply_movement(point: Point, movement: Movement) -> Result { + let x = point.0 as i32 + movement.0 as i32; + let y = point.1 as i32 + movement.1 as i32; + if x < 0 || y < 0 { + return Err(String::from("Can't move point off screen")); + } + Ok((x as usize, y as usize)) +} struct RoomEdge { start: Point, mid_point: Point, end: Point, - corridor_dir: (i8, i8) + corridor_dir: Movement, } impl RoomEdge { - pub fn new(start: Point, end: Point, corridor_dir: (i8, i8)) -> RoomEdge { + pub fn new(start: Point, end: Point, corridor_dir: Movement) -> RoomEdge { RoomEdge { start, end, mid_point: (end.0 - start.0 / 2, end.1 - start.1 / 2), - corridor_dir + corridor_dir, } } } @@ -44,7 +54,7 @@ struct Room { center: Point, width: usize, height: usize, - edges: [RoomEdge; 4] + edges: [RoomEdge; 4], } impl Room { @@ -53,13 +63,24 @@ impl Room { start, width, height, - center: (start.0 + (width as f32 / 2.0) as usize, start.1 + (height as f32 / 2.0) as usize), + center: ( + start.0 + (width as f32 / 2.0) as usize, + start.1 + (height as f32 / 2.0) as usize, + ), edges: [ RoomEdge::new(start, (start.0 + width, start.1), UP), RoomEdge::new(start, (start.0, start.1 + height), LEFT), - RoomEdge::new((start.0, start.1 + height), (start.0 + width, start.1 + height), DOWN), - RoomEdge::new((start.0 + width, start.1), (start.0 + width, start.1), RIGHT) - ] + RoomEdge::new( + (start.0, start.1 + height), + (start.0 + width, start.1 + height), + DOWN, + ), + RoomEdge::new( + (start.0 + width, start.1), + (start.0 + width, start.1), + RIGHT, + ), + ], } } } @@ -95,7 +116,7 @@ impl Tileable for Room { struct Corridor { start: Point, length: usize, - direction: CorridorType + direction: CorridorType, } impl Corridor { @@ -103,7 +124,7 @@ impl Corridor { Corridor { start, length, - direction + direction, } } @@ -133,7 +154,7 @@ impl Tileable for Corridor { // TODO: ensure the corridor isn't leaving the grid. match self.direction { CorridorType::Horizontal => self.tile_horizontal(grid), - CorridorType::Vertical => self.tile_vertical(grid) + CorridorType::Vertical => self.tile_vertical(grid), } Ok(()) } @@ -147,14 +168,14 @@ pub struct Level { corridors: Vec, pub entities: Vec>, entrance: Point, - exit: Point + exit: Point, } pub struct Dungeon { xsize: usize, ysize: usize, depth: usize, - pub levels: Vec + pub levels: Vec, } pub trait Generatable { @@ -171,11 +192,7 @@ fn ver_dist(point1: Point, point2: Point) -> f32 { /// The distance between 2 points fn distance(point1: Point, point2: Point) -> f32 { - ( - hor_dist(point1, point2).powf(2.0) - + - ver_dist(point1, point2).powf(2.0) - ).sqrt() + (hor_dist(point1, point2).powf(2.0) + ver_dist(point1, point2).powf(2.0)).sqrt() } impl Dungeon { @@ -184,7 +201,7 @@ impl Dungeon { xsize, ysize, depth, - levels: vec![] + levels: vec![], } } } @@ -218,10 +235,10 @@ impl Level { entities: vec![], entrance: match start { Some(st) => st, - None => (0, 0) + None => (0, 0), }, exit: (0, 0), - depth + depth, } } @@ -246,7 +263,7 @@ impl Level { if self.rooms.len() > 0 { return self.rooms[0].center; } - return (0,0) + return (0, 0); } pub fn get_entrance(&self) -> Point { @@ -259,10 +276,11 @@ impl Level { fn overlaps(&self, start: Point, width: usize, height: usize, padding: usize) -> bool { for room in &self.rooms { - if room.start.0 < start.0 + width + padding && - room.start.0 + room.width + padding > start.0 && - room.start.1 < start.1 + height + padding && - room.start.1 + room.height + padding > start.1 { + if room.start.0 < start.0 + width + padding + && room.start.0 + room.width + padding > start.0 + && room.start.1 < start.1 + height + padding + && room.start.1 + room.height + padding > start.1 + { return true; } } @@ -271,14 +289,17 @@ impl Level { } fn room_distances(&self, point: Point) -> Vec<(usize, f32)> { - let mut dists: Vec<(usize, f32)> = self.rooms + let mut dists: Vec<(usize, f32)> = self + .rooms .iter() .enumerate() .map(|(room_num, room): (usize, &Room)| -> (usize, f32) { (room_num, distance(point, room.center)) }) .collect(); - dists.sort_by(|(_, dista): &(usize, f32), (_, distb): &(usize, f32)| dista.partial_cmp(&distb).unwrap()); + dists.sort_by(|(_, dista): &(usize, f32), (_, distb): &(usize, f32)| { + dista.partial_cmp(&distb).unwrap() + }); dists } @@ -291,13 +312,13 @@ impl Level { // TODO: Find a way to write a lambda to generate the start point. let mut start: Point = ( rng.gen_range(0, self.xsize - room_width), - rng.gen_range(0, self.ysize - room_height) + rng.gen_range(0, self.ysize - room_height), ); while self.overlaps(start, room_width, room_height, 2) { start = ( rng.gen_range(0, self.xsize - room_width), - rng.gen_range(0, self.ysize - room_height) + rng.gen_range(0, self.ysize - room_height), ); } @@ -311,7 +332,7 @@ impl Level { let start = ( (center.0 as f32 - (room_width as f32 / 2f32)).round() as usize, - (center.1 as f32 - (room_height as f32 / 2f32)).round() as usize + (center.1 as f32 - (room_height as f32 / 2f32)).round() as usize, ); Room::new(start, room_width, room_height) @@ -347,7 +368,7 @@ impl Generatable for Level { self.corridors.push(Corridor::new( xorigin, xlength.abs() as usize, - CorridorType::Horizontal + CorridorType::Horizontal, )); let angle_point = (xorigin.0 + xlength.abs() as usize, xorigin.1); @@ -364,7 +385,7 @@ impl Generatable for Level { self.corridors.push(Corridor::new( yorigin, ylength.abs() as usize, - CorridorType::Vertical + CorridorType::Vertical, )); } @@ -383,12 +404,15 @@ impl Generatable for Level { // Create the enemy self.entities.push(Box::::new(Enemy::new( - "snake".to_string(), + String::from("snake"), 2 * self.depth as i32, (2.0 * self.depth as f32 * 0.6).round() as i32, (20.0 * self.depth as f32 * 0.2).max(80.0).round() as i32, 0, - (room.start.0 + rng.gen_range(0, room.width), room.start.1 + rng.gen_range(0, room.height)) + ( + room.start.0 + rng.gen_range(0, room.width), + room.start.1 + rng.gen_range(0, room.height), + ), ))); } } -- cgit v1.2.3 From 3fb8f5651144ef21338c09c14cd3db03c6416136 Mon Sep 17 00:00:00 2001 From: Guillaume Pasquet Date: Wed, 13 Nov 2019 14:19:45 +0100 Subject: Move the player around! --- src/entities.rs | 3 ++- src/main.rs | 21 +++++++++++++++------ src/state.rs | 35 ++++++++++++++++++++++++----------- src/tiling.rs | 4 ++++ src/world.rs | 8 ++++---- 5 files changed, 49 insertions(+), 22 deletions(-) diff --git a/src/entities.rs b/src/entities.rs index d462fa9..80e1235 100644 --- a/src/entities.rs +++ b/src/entities.rs @@ -90,7 +90,8 @@ impl Entity for Character { } fn move_by(&mut self, movement: Movement) -> Result<(), String> { - self.previous_location = apply_movement(self.location, movement)?; + self.previous_location = self.location; + self.location = apply_movement(self.location, movement)?; Ok(()) } diff --git a/src/main.rs b/src/main.rs index 9f5a432..2c9e611 100644 --- a/src/main.rs +++ b/src/main.rs @@ -8,7 +8,7 @@ mod entities; mod world; mod tiling; -use entities::Player; +use entities::{Player, Character, Entity}; use pancurses::{ initscr, endwin, @@ -16,7 +16,7 @@ use pancurses::{ noecho }; use state::State; -use world::{Dungeon}; +use world::{Dungeon, LEFT, RIGHT, UP, DOWN}; fn main() { @@ -50,10 +50,19 @@ fn main() { // get input and execute it match window.getch() { Some(Input::Character('?')) => { window.addstr("q: quit\n"); }, - Some(Input::Character('j')) => { window.addstr("down\n"); }, - Some(Input::Character('k')) => { window.addstr("up\n"); }, - Some(Input::Character('h')) => { window.addstr("left\n"); }, - Some(Input::Character('l')) => { window.addstr("right\n"); }, + Some(Input::Character('j')) => { + state.player.move_by(DOWN).unwrap(); + // state.get_player_mut().move_by(DOWN).unwrap(); + }, + Some(Input::Character('k')) => { + state.get_player_mut().move_by(UP).unwrap(); + }, + Some(Input::Character('h')) => { + state.get_player_mut().move_by(LEFT).unwrap(); + }, + Some(Input::Character('l')) => { + state.get_player_mut().move_by(RIGHT).unwrap(); + }, Some(Input::Character('q')) => break, Some(_) => (), None => (), diff --git a/src/state.rs b/src/state.rs index 0523442..2f09d1e 100644 --- a/src/state.rs +++ b/src/state.rs @@ -1,13 +1,14 @@ use pancurses::Window; -use crate::tiling::{TileType, tile_to_str}; +use crate::tiling::{TileType, TileGrid, tile_to_str}; use crate::entities::{Character, Entity}; use crate::world::{Dungeon, Generatable, Level}; pub struct State { pub player: Character, - pub dungeon: Dungeon, - pub level: usize, + dungeon: Dungeon, + level: usize, + grid: Option } pub fn draw_block(window: &Window, block: &TileType) { @@ -15,26 +16,28 @@ pub fn draw_block(window: &Window, block: &TileType) { } impl State { - pub fn new( - player: Character, - dungeon: Dungeon, - ) -> State { + pub fn new(player: Character, dungeon: Dungeon) -> State { State { player, dungeon, level: 0, + grid: None } } pub fn init(&mut self) { self.dungeon.generate(); self.player.place(self.current_level().get_start_point()); + self.switch_level(0); } - pub fn render_level(&self, window: &Window) { - let grid = self.current_level().to_tilegrid().unwrap(); + pub fn switch_level(&mut self, num_level: usize) { + self.level = num_level; + self.grid = Some(self.current_level().to_tilegrid().unwrap()); + } - for (linenum, line) in grid.raw_data().iter().enumerate() { + pub fn render_level(&self, window: &Window) { + for (linenum, line) in self.grid.as_ref().unwrap().raw_data().iter().enumerate() { for block in line.iter() { draw_block(&window, &block); } @@ -43,6 +46,12 @@ impl State { } fn render_entity(&self, entity: &dyn Entity, window: &Window) { + if !entity.is_dirty() { + return; + } + let dirt = entity.get_previous_location(); + window.mv(dirt.1 as i32, dirt.0 as i32); + draw_block(window, self.grid.as_ref().unwrap().get_block_at(dirt.0, dirt.1)); window.mv(entity.get_location().1 as i32, entity.get_location().0 as i32); draw_block(window, entity.get_tiletype()); } @@ -57,7 +66,11 @@ impl State { self.render_entity(&self.player, window) } - fn current_level(&self) -> &Level { + pub fn current_level(&self) -> &Level { &self.dungeon.levels[self.level] } + + pub fn get_player_mut(&mut self) -> &mut Character { + &mut self.player + } } \ No newline at end of file diff --git a/src/tiling.rs b/src/tiling.rs index bc1bd50..3bad119 100644 --- a/src/tiling.rs +++ b/src/tiling.rs @@ -36,6 +36,10 @@ impl<'a> TileGrid { pub fn raw_data(&'a self) -> &'a Vec> { &self.grid } + + pub fn get_block_at(&self, x: usize, y: usize) -> &TileType { + &self.grid[y + 1][x] + } } pub fn tile_to_str(tile: &TileType) -> &str { diff --git a/src/world.rs b/src/world.rs index 73fc802..c6f0912 100644 --- a/src/world.rs +++ b/src/world.rs @@ -17,10 +17,10 @@ enum CorridorType { Vertical, } -const LEFT: Movement = (-1, 0); -const RIGHT: Movement = (1, 0); -const UP: Movement = (0, -1); -const DOWN: Movement = (0, 1); +pub const LEFT: Movement = (-1, 0); +pub const RIGHT: Movement = (1, 0); +pub const UP: Movement = (0, -1); +pub const DOWN: Movement = (0, 1); pub fn apply_movement(point: Point, movement: Movement) -> Result { let x = point.0 as i32 + movement.0 as i32; -- cgit v1.2.3