parent
91160edb3f
commit
9971d9dee5
|
@ -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,
|
||||
|
|
|
@ -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<ConnectionInfo>,
|
||||
pub connection_right: Option<ConnectionInfo>,
|
||||
// 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<usize> {
|
||||
self.offset_x..self.offset_x + self.width
|
||||
}
|
||||
fn get_y_range(&self) -> Range<usize> {
|
||||
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<usize>, r2: Range<usize>) -> Range<usize> {
|
||||
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,
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue