From cde079a02908409bf0360e54ca235c478ca14852 Mon Sep 17 00:00:00 2001 From: Timothy Warren Date: Fri, 22 Oct 2021 14:50:04 -0400 Subject: [PATCH] Complete chapter 2.3 --- src/main.rs | 10 +++++-- src/map.rs | 82 +++++++++++++++++++++++++++++++++++++++++++++++++-- src/player.rs | 20 ++++++++++--- src/rect.rs | 26 ++++++++++++++++ 4 files changed, 129 insertions(+), 9 deletions(-) diff --git a/src/main.rs b/src/main.rs index e6d0f3c..ae71e34 100644 --- a/src/main.rs +++ b/src/main.rs @@ -8,7 +8,7 @@ pub use map::*; mod player; use player::*; mod rect; -// pub use rect::Rect; +pub use rect::Rect; pub struct State { ecs: World, @@ -52,11 +52,15 @@ fn main() -> rltk::BError { gs.ecs.register::(); gs.ecs.register::(); - gs.ecs.insert(new_map()); + let (rooms, map) = new_map_rooms_and_corridors(); + + gs.ecs.insert(map); + + let (player_x, player_y) = rooms[0].center(); gs.ecs .create_entity() - .with(Position { x: 40, y: 25 }) + .with(Position { x: player_x, y: player_y }) .with(Renderable { glyph: rltk::to_cp437('@'), fg: RGB::named(rltk::YELLOW), diff --git a/src/map.rs b/src/map.rs index 294efb4..d200e71 100644 --- a/src/map.rs +++ b/src/map.rs @@ -1,5 +1,5 @@ use rltk::{ RGB, Rltk, RandomNumberGenerator }; -// use super::{Rect}; +use super::{Rect}; use std::cmp::{min, max}; #[derive(PartialEq, Copy, Clone)] @@ -12,7 +12,9 @@ pub fn xy_idx(x: i32, y: i32) -> usize { (y as usize * 80) + x as usize } -pub fn new_map() -> Vec { +/// Makes a map with solid boundaries and 400 randomly placed walls. +/// No guarantees that it won't look awful. +pub fn new_map_text() -> Vec { let mut map = vec![TileType::Floor; 80 * 50]; // Make the boundary walls @@ -42,6 +44,82 @@ pub fn new_map() -> Vec { map } +pub fn new_map_rooms_and_corridors() -> (Vec, Vec) { + let mut map = vec![TileType::Wall; 80 * 50]; + + let mut rooms: Vec = Vec::new(); + const MAX_ROOMS :i32 = 30; + const MIN_SIZE :i32 = 6; + const MAX_SIZE :i32 = 10; + + let mut rng = RandomNumberGenerator::new(); + + for _ in 0..MAX_ROOMS { + let w = rng.range(MIN_SIZE, MAX_SIZE); + let h = rng.range(MIN_SIZE, MAX_SIZE); + let x = rng.roll_dice(1, 80 - w - 1) - 1; + let y = rng.roll_dice(1, 50 - h - 1) - 1; + + let new_room = Rect::new(x, y, w, h); + let mut ok = true; + + for other_room in rooms.iter() { + if new_room.intersect(other_room) { + ok = false; + } + } + + if ok { + apply_room_to_map(&new_room, &mut map); + + if ! rooms.is_empty() { + let (new_x, new_y) = new_room.center(); + let (prev_x, prev_y) = rooms[rooms.len()-1].center(); + + if rng.range(0, 2) == 1 { + apply_horizontal_tunnel(&mut map, prev_x, new_x, prev_y); + apply_vertical_tunnel(&mut map, prev_y, new_y, new_x); + } else { + apply_vertical_tunnel(&mut map, prev_y, new_y, prev_x); + apply_horizontal_tunnel(&mut map, prev_x, new_x, new_y); + } + } + + rooms.push(new_room); + } + } + + (rooms, map) +} + +fn apply_room_to_map(room: &Rect, map: &mut [TileType]) { + for y in room.y1+1 ..= room.y2 { + for x in room.x1+1 ..= room.x2 { + map[xy_idx(x, y)] = TileType::Floor; + } + } +} + +fn apply_horizontal_tunnel(map: &mut [TileType], x1: i32, x2: i32, y: i32) { + for x in min(x1, x2) ..= max(x1, x2) { + let idx = xy_idx(x, y); + + if idx > 0 && idx < 80*50 { + map[idx as usize] = TileType::Floor; + } + } +} + +fn apply_vertical_tunnel(map: &mut [TileType], y1: i32, y2: i32, x: i32) { + for y in min(y1, y2) ..= max(y1, y2) { + let idx = xy_idx(x, y); + + if idx > 0 && idx < 80*50 { + map[idx as usize] = TileType::Floor; + } + } +} + pub fn draw_map(map: &[TileType], ctx: &mut Rltk) { let mut y = 0; let mut x = 0; diff --git a/src/player.rs b/src/player.rs index 27487b3..dc90414 100644 --- a/src/player.rs +++ b/src/player.rs @@ -22,10 +22,22 @@ pub fn player_input(gs: &mut State, ctx: &mut Rltk) { match ctx.key { None => {} // Nothing happened Some(key) => match key { - VirtualKeyCode::Left => try_move_player(-1, 0, &mut gs.ecs), - VirtualKeyCode::Right => try_move_player(1, 0, &mut gs.ecs), - VirtualKeyCode::Up => try_move_player(0, -1, &mut gs.ecs), - VirtualKeyCode::Down => try_move_player(0, 1, &mut gs.ecs), + VirtualKeyCode::Left | + VirtualKeyCode::Numpad4 | + VirtualKeyCode::H => try_move_player(-1, 0, &mut gs.ecs), + + VirtualKeyCode::Right | + VirtualKeyCode::Numpad6 | + VirtualKeyCode::L=> try_move_player(1, 0, &mut gs.ecs), + + VirtualKeyCode::Up | + VirtualKeyCode::Numpad8 | + VirtualKeyCode::K => try_move_player(0, -1, &mut gs.ecs), + + VirtualKeyCode::Down | + VirtualKeyCode::Numpad2 | + VirtualKeyCode::J => try_move_player(0, 1, &mut gs.ecs), + _ => {} }, } diff --git a/src/rect.rs b/src/rect.rs index e69de29..a989d5f 100644 --- a/src/rect.rs +++ b/src/rect.rs @@ -0,0 +1,26 @@ +pub struct Rect { + pub x1: i32, + pub x2: i32, + pub y1: i32, + pub y2: i32, +} + +impl Rect { + pub fn new(x: i32, y: i32, w: i32, h: i32) -> Rect { + Rect{ + x1: x, + y1: y, + x2: x+w, + y2: y+h, + } + } + + /// Returns true if this overlaps with other + pub fn intersect(&self, other: &Rect) -> bool { + self.x1 <= other.x2 && self.x2 >= other.x1 && self.y1 <= other.y2 && self.y2 >= other.y1 + } + + pub fn center(&self) -> (i32, i32) { + ((self.x1 + self.x2) / 2, (self.y1 + self.y2) / 2) + } +} \ No newline at end of file