work on level generator
This commit is contained in:
parent
7f288dbcd1
commit
c6492c28c2
|
@ -73,7 +73,8 @@ pub fn get_room_type_per_level() -> Vec<HashMap<RoomType, std::ops::RangeInclusi
|
|||
let tmp = [
|
||||
// level 1
|
||||
vec![
|
||||
(RoomType::EmptyRoom, 75),
|
||||
(RoomType::EmptyRoom, 50),
|
||||
(RoomType::ArtifactRoom, 25),
|
||||
(RoomType::MonsterRoom, 5),
|
||||
(RoomType::BasicRoom, 20),
|
||||
],
|
||||
|
|
|
@ -57,6 +57,7 @@ impl Level {
|
|||
return (None, None, None);
|
||||
}
|
||||
if !self.discovered[x][y] {
|
||||
#[cfg(test)]
|
||||
return (Some(StructureElement::Unknown), None, None);
|
||||
}
|
||||
let search_pos = &Position::new(self.level, x, y);
|
||||
|
|
|
@ -2,15 +2,19 @@ use petgraph::algo::min_spanning_tree;
|
|||
use petgraph::data::*;
|
||||
use petgraph::graph::Graph;
|
||||
use petgraph::graph::UnGraph;
|
||||
use std::cmp::max;
|
||||
use std::cmp::min;
|
||||
use std::ops::Range;
|
||||
|
||||
use rand::Rng;
|
||||
use rand::{rngs::ThreadRng, seq::SliceRandom};
|
||||
|
||||
use crate::artifacts::Artifact;
|
||||
use crate::artifacts::Chest;
|
||||
use crate::artifacts::Potion;
|
||||
use crate::constants::get_monsters_per_level;
|
||||
use crate::constants::ROOM_HEIGHT;
|
||||
use crate::constants::ROOM_WIDTH;
|
||||
use crate::monster::create_monster_by_type;
|
||||
use crate::monster::Monster;
|
||||
use crate::position::Position;
|
||||
use crate::room::Connection;
|
||||
use crate::{
|
||||
constants::{
|
||||
|
@ -23,6 +27,7 @@ use crate::{
|
|||
pub struct LevelGenerator {
|
||||
level: usize,
|
||||
rooms: [[Room; ROOMS_VERTICAL]; ROOMS_HORIZONAL],
|
||||
rng: ThreadRng,
|
||||
}
|
||||
enum Direction {
|
||||
Horizontal,
|
||||
|
@ -103,7 +108,7 @@ impl LevelGenerator {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
// debug print a text view of the dungeon
|
||||
println!(" 0 1 2 3 4 5 6 7");
|
||||
for r in 0..ROOMS_VERTICAL {
|
||||
print!("{} ", r);
|
||||
|
@ -174,20 +179,20 @@ impl LevelGenerator {
|
|||
|
||||
if src_node_col == tgt_node_col {
|
||||
// println!("Down");
|
||||
let start_col = src_node_col * ROOM_WIDTH+ROOM_WIDTH/2;
|
||||
let start_row = src_node_row * ROOM_HEIGHT+ROOM_HEIGHT;
|
||||
let end_col = tgt_node_col * ROOM_WIDTH+ROOM_WIDTH/2;
|
||||
let end_row = tgt_node_row * ROOM_HEIGHT;
|
||||
let start_col = src_node_col * ROOM_WIDTH + ROOM_WIDTH / 2;
|
||||
let start_row = src_node_row * ROOM_HEIGHT + ROOM_HEIGHT;
|
||||
let end_col = tgt_node_col * ROOM_WIDTH + ROOM_WIDTH / 2;
|
||||
let end_row = tgt_node_row * ROOM_HEIGHT;
|
||||
rooms[src_node_col][src_node_row].connection_down = Some(Connection {
|
||||
start_pos: (start_col, start_row),
|
||||
end_pos: (end_col, end_row),
|
||||
});
|
||||
} else {
|
||||
// println!("Right");
|
||||
let start_col = src_node_col * ROOM_WIDTH+ROOM_WIDTH;
|
||||
let start_row = src_node_row * ROOM_HEIGHT+ROOM_HEIGHT/2;
|
||||
let start_col = src_node_col * ROOM_WIDTH + ROOM_WIDTH;
|
||||
let start_row = src_node_row * ROOM_HEIGHT + ROOM_HEIGHT / 2;
|
||||
let end_col = tgt_node_col * ROOM_WIDTH;
|
||||
let end_row = tgt_node_row * ROOM_HEIGHT+ROOM_HEIGHT/2;
|
||||
let end_row = tgt_node_row * ROOM_HEIGHT + ROOM_HEIGHT / 2;
|
||||
rooms[src_node_col][src_node_row].connection_right = Some(Connection {
|
||||
start_pos: (start_col, start_row),
|
||||
end_pos: (end_col, end_row),
|
||||
|
@ -195,7 +200,26 @@ impl LevelGenerator {
|
|||
}
|
||||
}
|
||||
|
||||
LevelGenerator { level, rooms }
|
||||
LevelGenerator {
|
||||
level,
|
||||
rooms,
|
||||
rng,
|
||||
}
|
||||
}
|
||||
|
||||
fn select_monster(position: Position, rng: &mut ThreadRng) -> Box<dyn Monster> {
|
||||
let level = position.get_level();
|
||||
let value = rng.gen_range(1..=100);
|
||||
|
||||
let t = get_monsters_per_level();
|
||||
if level < t.len() {
|
||||
for (mtype, range) in &t[level] {
|
||||
if range.contains(&value) {
|
||||
return create_monster_by_type(mtype, position);
|
||||
}
|
||||
}
|
||||
}
|
||||
panic!("no monster selectable!");
|
||||
}
|
||||
|
||||
fn select_room_type(level: usize, rng: &mut ThreadRng) -> RoomType {
|
||||
|
@ -216,18 +240,37 @@ impl LevelGenerator {
|
|||
let mut structure = [[StructureElement::Wall; LEVEL_HEIGHT]; LEVEL_WIDTH];
|
||||
let mut start_pos = (0, 0);
|
||||
let mut end_pos = (0, 0);
|
||||
let mut monsters: Vec<Box<dyn Monster>> = Vec::with_capacity(10);
|
||||
let mut artifacts: Vec<Box<dyn Artifact>> = Vec::with_capacity(10);
|
||||
for col in 0..ROOMS_HORIZONAL {
|
||||
for row in 0..ROOMS_VERTICAL {
|
||||
let position = self.rooms[col][row].render(&mut structure, col, row);
|
||||
if self.rooms[col][row].kind == RoomType::Start
|
||||
|| self.rooms[col][row].kind == RoomType::StairUp
|
||||
{
|
||||
start_pos = position;
|
||||
}
|
||||
if self.rooms[col][row].kind == RoomType::End
|
||||
|| self.rooms[col][row].kind == RoomType::StairDown
|
||||
{
|
||||
end_pos = position;
|
||||
let room = self.rooms[col][row];
|
||||
let position = room.render(&mut structure, col, row);
|
||||
match room.kind {
|
||||
RoomType::Start => {start_pos=position},
|
||||
RoomType::End => {end_pos=position},
|
||||
RoomType::StairUp => {start_pos=position},
|
||||
RoomType::StairDown => {end_pos=position},
|
||||
RoomType::BasicRoom => {},
|
||||
RoomType::ArtifactRoom => {
|
||||
match self.rng.gen_range(1..=100) {
|
||||
1..=50 => {
|
||||
artifacts
|
||||
.push(Box::new(Chest::new(Position::new(self.level, position.0, position.1))));
|
||||
}
|
||||
_ => {
|
||||
artifacts
|
||||
.push(Box::new(Potion::new(Position::new(self.level, position.0, position.1))));
|
||||
}
|
||||
};
|
||||
},
|
||||
RoomType::MonsterRoom => {
|
||||
monsters.push(LevelGenerator::select_monster(
|
||||
Position::new(self.level, position.0, position.1),
|
||||
&mut self.rng,
|
||||
));
|
||||
},
|
||||
RoomType::EmptyRoom => {},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -247,8 +290,8 @@ impl LevelGenerator {
|
|||
level: self.level,
|
||||
structure,
|
||||
discovered: [[false; LEVEL_HEIGHT]; LEVEL_WIDTH],
|
||||
monsters: vec![],
|
||||
artifacts: vec![],
|
||||
monsters,
|
||||
artifacts,
|
||||
start: start_pos,
|
||||
end: end_pos,
|
||||
rng: rand::thread_rng(),
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use ratatui::buffer::Buffer;
|
||||
use ratatui::layout::Rect;
|
||||
use ratatui::style::Color;
|
||||
use ratatui::style::{Color, Modifier, Style};
|
||||
use ratatui::widgets::{StatefulWidget, Widget};
|
||||
|
||||
use crate::game::Game;
|
||||
|
@ -15,6 +15,9 @@ impl LevelWidget {
|
|||
fn set_cell(&self, buf: &mut Buffer, x: u16, y: u16, symbol: &str, fg: Color, bg: Color) {
|
||||
buf[(x, y)].set_symbol(symbol).set_bg(bg).set_fg(fg);
|
||||
}
|
||||
fn set_bold_cell(&self, buf: &mut Buffer, x: u16, y: u16, symbol: &str, fg: Color, bg: Color) {
|
||||
buf[(x, y)].set_symbol(symbol).set_bg(bg).set_fg(fg).set_style(Style::new().add_modifier(Modifier::BOLD));
|
||||
}
|
||||
}
|
||||
|
||||
impl StatefulWidget for LevelWidget {
|
||||
|
@ -46,7 +49,7 @@ impl StatefulWidget for LevelWidget {
|
|||
}
|
||||
StructureElement::Wall => {
|
||||
// TODO add fancy walls with https://en.wikipedia.org/wiki/Box-drawing_characters
|
||||
self.set_cell(buf, x, y, "#", FG_BROWN, Color::Gray);
|
||||
self.set_cell(buf, x, y, "#", FG_BROWN, FG_BROWN);
|
||||
}
|
||||
StructureElement::Floor => {
|
||||
self.set_cell(buf, x, y, " ", FG_BROWN, Color::Gray);
|
||||
|
@ -68,7 +71,7 @@ impl StatefulWidget for LevelWidget {
|
|||
}
|
||||
(_, _, Some(t)) => {
|
||||
let (s, c) = t.get_representation();
|
||||
self.set_cell(buf, x, y, s, c, Color::Gray);
|
||||
self.set_bold_cell(buf, x, y, s, c, Color::Gray);
|
||||
}
|
||||
(None, None, None) => {}
|
||||
};
|
||||
|
|
12
src/room.rs
12
src/room.rs
|
@ -119,25 +119,19 @@ impl Room {
|
|||
match self.kind {
|
||||
RoomType::Start => {
|
||||
tgt[left + self.special.0][top + self.special.1] = StructureElement::Start;
|
||||
(left + self.special.0, top + self.special.1)
|
||||
}
|
||||
RoomType::End => {
|
||||
tgt[left + self.special.0][top + self.special.1] = StructureElement::End;
|
||||
(left + self.special.0, top + self.special.1)
|
||||
}
|
||||
RoomType::StairUp => {
|
||||
tgt[left + self.special.0][top + self.special.1] = StructureElement::StairUp;
|
||||
(left + self.special.0, top + self.special.1)
|
||||
}
|
||||
RoomType::StairDown => {
|
||||
tgt[left + self.special.0][top + self.special.1] = StructureElement::StairDown;
|
||||
(left + self.special.0, top + self.special.1)
|
||||
}
|
||||
RoomType::BasicRoom => (0, 0),
|
||||
RoomType::ArtifactRoom => (0, 0),
|
||||
RoomType::MonsterRoom => (0, 0),
|
||||
RoomType::EmptyRoom => (0, 0),
|
||||
}
|
||||
_ => {}
|
||||
};
|
||||
(left + self.special.0, top + self.special.1)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue