From 9971d9dee5fabd7a209cd9df728d21bb1ef624d6 Mon Sep 17 00:00:00 2001 From: Joachim Lusiardi Date: Sun, 19 Nov 2023 16:22:16 +0100 Subject: [PATCH] level generator works fixing imports and stuff --- src/level.rs | 2 +- src/level_generator.rs | 99 +++++++++++++++++++++++++++++++++++++++--- src/level_widget.rs | 8 ++-- src/main.rs | 2 +- 4 files changed, 99 insertions(+), 12 deletions(-) diff --git a/src/level.rs b/src/level.rs index 6f2913d..3246e65 100644 --- a/src/level.rs +++ b/src/level.rs @@ -28,7 +28,7 @@ pub struct Level { impl Level { pub fn new() -> Level { - let mut s = [[LevelElement::Wall; LEVEL_HEIGHT]; LEVEL_WIDTH]; + let s = [[LevelElement::Wall; LEVEL_HEIGHT]; LEVEL_WIDTH]; Level { structure: s, start_x: 1, diff --git a/src/level_generator.rs b/src/level_generator.rs index 3f8069b..6beb9fa 100644 --- a/src/level_generator.rs +++ b/src/level_generator.rs @@ -1,3 +1,5 @@ +use std::cmp::{max, min}; +use std::ops::Range; use rand::prelude::SliceRandom; use rand::Rng; use petgraph::graph::UnGraph; @@ -13,6 +15,12 @@ const ROOMS_HORIZONTAL: usize = 4; const ROOM_WIDTH: usize = 7; const ROOM_HEIGHT: usize = 6; +#[derive(Copy, Clone, Debug, PartialEq)] +struct ConnectionInfo { + offset: usize, + distance: usize, +} + #[derive(Copy, Clone, Debug, PartialEq)] struct Room { pub kind: RoomType, @@ -20,8 +28,8 @@ struct Room { pub offset_y: usize, pub width: usize, pub height: usize, - // pub connection_down: bool, - // pub connection_right: bool, + pub connection_down: Option, + pub connection_right: Option, // pub connected: bool, } @@ -33,8 +41,8 @@ impl Room { offset_y: 0, width: 0, height: 0, - // connection_down: false, - // connection_right: false, + connection_down: None, + connection_right: None, // connected: false, } } @@ -47,6 +55,12 @@ impl Room { self.offset_x = rng.gen_range(0..(ROOM_WIDTH - width)); self.offset_y = rng.gen_range(0..(ROOM_HEIGHT - height)); } + fn get_x_range(&self) -> Range { + self.offset_x..self.offset_x + self.width + } + fn get_y_range(&self) -> Range { + self.offset_y..self.offset_y + self.height + } } #[derive(Debug)] @@ -131,14 +145,58 @@ impl LevelGenerator { for edge in mst.raw_edges() { let src = mst[edge.source()]; let tgt = mst[edge.target()]; - println!("{:?} {:?}", src, tgt); + + let src_room = rooms[src.0][src.1]; + let mut tgt_room = rooms[tgt.0][tgt.1]; + + // cols are the same, either up or down + if src.0 == tgt.0 { + let range = LevelGenerator::range_overlap(src_room.get_x_range(), tgt_room.get_x_range()); + let position: usize; + if range.is_empty() { + position = range.start; + } else { + position = rng.gen_range(range); + } + if src.1 < tgt.1 { + // src to tgt + rooms[src.0][src.1].connection_down = Some(ConnectionInfo { offset: position, distance: tgt.1 - src.1 }); + } else { + // tgt to src + tgt_room.connection_down = Some(ConnectionInfo { offset: position, distance: src.1 - tgt.1 }); + } + } + // rows are the same, either left or right + if src.1 == tgt.1 { + let range = LevelGenerator::range_overlap(src_room.get_y_range(), tgt_room.get_y_range()); + let mut position: usize; + if range.is_empty() { + position = range.start; + } else { + position = rng.gen_range(range); + } + if src.1 == 0 && position == 0 { + position = 1; + } + if src.0 < tgt.0 { + // src to tgt + rooms[src.0][src.1].connection_right = Some(ConnectionInfo { offset: position, distance: tgt.0 - src.0 }); + } else { + // tgt to src + tgt_room.connection_right = Some(ConnectionInfo { offset: position, distance: src.1 - tgt.1 }); + } + } } - // println!("Level {}\n{}", level, Dot::new(&mst)); LevelGenerator { rooms } } + + fn range_overlap(r1: Range, r2: Range) -> Range { + max(r1.start, r2.start)..min(r1.end, r2.end) + } + /// Verifies that for a given matrix of rooms each room has at least one other room in the /// same row or column. fn rooms_connectable(rooms: &[[Room; ROOMS_HORIZONTAL]; ROOMS_VERTICAL]) -> bool { @@ -191,6 +249,35 @@ impl LevelGenerator { } } } + // + for c in 0..ROOMS_VERTICAL { + for r in 0..ROOMS_HORIZONTAL { + let src_room = self.rooms[c][r]; + if let Some(x_conn) = src_room.connection_down { + let tgt_room = self.rooms[c][r + x_conn.distance]; + let top = 1 + r * ROOM_HEIGHT + src_room.offset_y; + let left = 1 + c * ROOM_WIDTH + x_conn.offset; + let bottom = 1 + (r + x_conn.distance) * ROOM_HEIGHT + tgt_room.offset_y + tgt_room.height; + for i in top..bottom { + if s[left][i] == LevelElement::Wall { + s[left][i] = LevelElement::Floor; + } + } + } + if let Some(y_conn) = src_room.connection_right { + let tgt_room = self.rooms[c + y_conn.distance][r]; + + let top = 1 + r * ROOM_HEIGHT + src_room.offset_y + y_conn.offset - 1; + let left = 1 + c * ROOM_WIDTH + src_room.offset_x; + let right = 1 + (c + y_conn.distance) * ROOM_WIDTH + tgt_room.offset_x + tgt_room.width; + for i in left..right { + if s[i][top] == LevelElement::Wall { + s[i][top] = LevelElement::Floor; + } + } + } + } + } Level { structure: s, start_x, diff --git a/src/level_widget.rs b/src/level_widget.rs index c1d95c0..1f63915 100644 --- a/src/level_widget.rs +++ b/src/level_widget.rs @@ -1,8 +1,8 @@ use ratatui::prelude::*; use ratatui::widgets::Widget; + use crate::game::Game; -use crate::level::{Level, LevelElement}; -use crate::player::Player; +use crate::level::LevelElement; const FG_BROWN: Color = Color::Rgb(186, 74, 0); @@ -96,10 +96,10 @@ impl<'a> Widget for LevelWidget<'a> { self.set_cell(buf, x, y, " ", FG_BROWN, Color::Gray); } LevelElement::StairDown => { - self.set_cell(buf, x, y, ">", FG_BROWN, Color::Gray); + self.set_cell(buf, x, y, ">", Color::Yellow, Color::Gray); } LevelElement::StairUp => { - self.set_cell(buf, x, y, "<", FG_BROWN, Color::Gray); + self.set_cell(buf, x, y, "<", Color::Yellow, Color::Gray); } } } diff --git a/src/main.rs b/src/main.rs index b4240a8..1e43eb1 100644 --- a/src/main.rs +++ b/src/main.rs @@ -12,7 +12,7 @@ use ratatui::prelude::*; use ratatui::widgets::Block; use crate::game::Game; -use crate::level::{Level, LevelElement}; +use crate::level::Level; use crate::level_widget::LevelWidget; use crate::player::Player; use crate::level_generator::LevelGenerator;