Added random room and corridors generation :D

This commit is contained in:
2022-04-26 14:49:52 +02:00
parent ba6d63ff8e
commit d4f4ba9c93
4 changed files with 100 additions and 5 deletions

View File

@@ -5,3 +5,6 @@ First running programm with an empty map
Added Player movement and render
<img src="./screenshots/EmptyMap_and_Player.png" width="80%">
Added randomly generated rooms and tunnels :D
<img src="./screenshots/Map_Generated.png" width="80%">

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

View File

@@ -4,6 +4,7 @@
/// date : 26/04/2022
/// brief : Main game file
mod map;
mod map_builder;
mod player;
mod prelude {
@@ -12,6 +13,7 @@ mod prelude {
pub const SCREEN_HEIGHT: i32 = 50;
pub use crate::map::*;
pub use crate::player::*;
pub use crate::map_builder::*;
}
use prelude::*;
@@ -23,12 +25,11 @@ struct State {
}
impl State {
fn new() -> Self {
let mut rng = RandomNumberGenerator::new();
let map_builder = MapBuilder::new(&mut rng);
Self {
map: Map::new(),
player: Player::new(
//spawns the player in the middle of the map
Point::new(SCREEN_WIDTH / 2,SCREEN_HEIGHT / 2)
)
map: map_builder.map,
player: Player::new(map_builder.player_start),
}
}
}

91
src/map_builder.rs Normal file
View File

@@ -0,0 +1,91 @@
/// file : map_builder.rs
/// author : Maxime Rohmer (from Herbet Wolverson book)
/// version : 0.1.0
/// date : 26/04/2022
/// brief : File that contains all the map and dungeons generations stuff
use crate::prelude::*;
const NUM_ROOMS: usize = 20;
const ROOM_SIZE_REDUCTOR :i32 = 10;
pub struct MapBuilder {
pub map : Map,
pub rooms : Vec<Rect>,
pub player_start : Point,
}
//please dont ask me too much on how this EXACTLY works because my brain is likely going to shut down
impl MapBuilder{
pub fn new(rng: &mut RandomNumberGenerator) -> Self{
let mut mb = MapBuilder{
map : Map::new(),
rooms : Vec::new(),
player_start : Point::zero(),
};
mb.fill(TileType::Wall);
mb.build_random_rooms(rng);
mb.build_corridors(rng);
mb.player_start = mb.rooms[0].center();
mb
}
fn fill(& mut self, tile : TileType){
self.map.tiles.iter_mut().for_each(|t| *t = tile);
}
fn build_random_rooms(&mut self, rng : &mut RandomNumberGenerator){
while self.rooms.len() < NUM_ROOMS{
let room = Rect::with_size(
rng.range(1, SCREEN_WIDTH - ROOM_SIZE_REDUCTOR),
rng.range(1, SCREEN_HEIGHT - ROOM_SIZE_REDUCTOR),
rng.range(2,10),
rng.range(2,10),
);
let mut overlap = false;
for r in self.rooms.iter(){
if r.intersect(&room){
overlap = true;
}
}
if !overlap {
room.for_each(|p|{
if p.x > 0 && p.x < SCREEN_WIDTH && p.y > 0 && p.y < SCREEN_HEIGHT{
let idx = map_idx(p.x,p.y);
self.map.tiles[idx] = TileType::Floor;
}
});
self.rooms.push(room)
}
}
}
fn apply_vertical_tunnel(&mut self, y1:i32,y2:i32,x:i32){
use std::cmp::{min,max};
for y in min(y1,y2) ..= max(y1,y2){
if let Some(idx) = self.map.try_idx(Point::new(x,y)){
self.map.tiles[idx as usize] = TileType::Floor;
}
}
}
fn apply_horizontal_tunnel(&mut self,x1:i32,x2:i32,y:i32){
use std::cmp::{min,max};
for x in min(x1,x2) ..= max(x1,x2){
if let Some(idx) = self.map.try_idx(Point::new(x,y)){
self.map.tiles[idx as usize] = TileType::Floor;
}
}
}
fn build_corridors(&mut self, rng: &mut RandomNumberGenerator){
let mut rooms = self.rooms.clone();
rooms.sort_by(|a,b| a.center().x.cmp(&b.center().x));
for (i,room) in rooms.iter().enumerate().skip(1){
let prev = rooms[i-1].center();
let new = room.center();
if rng.range(0,2) == 1{
self.apply_horizontal_tunnel(prev.x,new.x,prev.y);
self.apply_vertical_tunnel(prev.y,new.y,new.x);
}else{
self.apply_vertical_tunnel(prev.y,new.y,prev.x);
self.apply_horizontal_tunnel(prev.x,new.x,new.y);
}
}
}
}