2024-07-07 12:33:22 +02:00
|
|
|
use super::{furniture::Furniture, grid::Grid};
|
|
|
|
use crate::game;
|
2024-07-07 11:38:13 +02:00
|
|
|
use comfy::{
|
2024-07-07 12:33:22 +02:00
|
|
|
draw_rect, draw_rect_outline, draw_sprite, error, random_i32, vec2, EngineContext,
|
|
|
|
HashSet, RandomRange as _, Vec2, GREEN, PURPLE, RED, WHITE
|
2024-07-07 11:38:13 +02:00
|
|
|
};
|
2024-07-07 12:33:22 +02:00
|
|
|
use indexmap::IndexSet;
|
2024-07-07 00:01:46 +02:00
|
|
|
|
2024-07-07 10:04:29 +02:00
|
|
|
pub const SCALE: f32 = 4.0;
|
|
|
|
|
|
|
|
#[derive(Debug, PartialEq)]
|
2024-07-07 00:01:46 +02:00
|
|
|
enum RoomType {
|
|
|
|
Kitchen,
|
|
|
|
Bath,
|
|
|
|
Toilett,
|
|
|
|
LivingRoom,
|
|
|
|
SleepingRoom
|
|
|
|
}
|
|
|
|
|
2024-07-07 11:50:35 +02:00
|
|
|
type Tile = (Vec2, Vec2, Furniture); //(pos, size, furniture)
|
|
|
|
|
2024-07-07 00:01:46 +02:00
|
|
|
#[derive(Debug)]
|
|
|
|
pub struct Room {
|
|
|
|
room_type: RoomType,
|
2024-07-07 00:48:37 +02:00
|
|
|
pub size: (u8, u8), //(width, height)
|
2024-07-07 10:04:29 +02:00
|
|
|
pub grid: Grid,
|
2024-07-07 12:33:22 +02:00
|
|
|
furnitures: Vec<Tile>
|
2024-07-07 00:01:46 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
impl RoomType {
|
|
|
|
pub fn random() -> Self {
|
|
|
|
match random_i32(0, 4) {
|
|
|
|
0 => RoomType::Kitchen,
|
|
|
|
1 => RoomType::Bath,
|
|
|
|
2 => RoomType::Toilett,
|
|
|
|
3 => RoomType::LivingRoom,
|
|
|
|
4 => RoomType::SleepingRoom,
|
|
|
|
_ => panic!("Somehow you where unlucky and got a random number out of range")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Room {
|
2024-07-07 11:38:13 +02:00
|
|
|
pub fn new(ctx: &mut EngineContext<'_>) -> Self {
|
2024-07-07 00:01:46 +02:00
|
|
|
let room_type = RoomType::random();
|
|
|
|
let size = Self::random_size(&room_type);
|
|
|
|
|
2024-07-07 12:33:22 +02:00
|
|
|
let furnitures = Self::random_room_furniture(&room_type, size, ctx);
|
2024-07-07 10:04:29 +02:00
|
|
|
|
2024-07-07 11:38:13 +02:00
|
|
|
Room {
|
|
|
|
room_type,
|
|
|
|
size,
|
|
|
|
grid: Self::create_grid(size.0, size.1),
|
|
|
|
furnitures
|
|
|
|
}
|
|
|
|
}
|
2024-07-07 00:01:46 +02:00
|
|
|
|
|
|
|
fn random_size(room_type: &RoomType) -> (u8, u8) {
|
2024-07-07 11:50:35 +02:00
|
|
|
//Kitchen + Living Room 5-8
|
|
|
|
//Bath + sleepingroom 4-6
|
|
|
|
//Toilet 2-3
|
2024-07-07 00:01:46 +02:00
|
|
|
match room_type {
|
2024-07-07 11:38:13 +02:00
|
|
|
RoomType::Kitchen | RoomType::LivingRoom => (random_i32(5, 8) as u8, 3),
|
|
|
|
RoomType::Bath | RoomType::SleepingRoom => (random_i32(4, 6) as u8, 3),
|
|
|
|
RoomType::Toilett => (random_i32(2, 3) as u8, 3)
|
2024-07-07 00:01:46 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-07-07 12:33:22 +02:00
|
|
|
fn random_room_furniture(
|
|
|
|
room_type: &RoomType,
|
|
|
|
(width, _height): (u8, u8),
|
|
|
|
ctx: &mut EngineContext<'_>
|
|
|
|
) -> Vec<Tile> {
|
2024-07-07 11:50:35 +02:00
|
|
|
let mut furnitures = Vec::new();
|
|
|
|
|
2024-07-07 12:33:22 +02:00
|
|
|
let mut empty_spots: IndexSet<u8> = (0 .. width).collect();
|
|
|
|
let mut assets_used: HashSet<&'static str> = HashSet::new();
|
|
|
|
|
|
|
|
fn random_empty_spot(empty_spots: &mut IndexSet<u8>) -> Option<u8> {
|
|
|
|
if empty_spots.is_empty() {
|
|
|
|
return None;
|
|
|
|
}
|
|
|
|
let random_idx = usize::gen_range(0, empty_spots.len());
|
|
|
|
empty_spots.swap_remove_index(random_idx)
|
|
|
|
}
|
|
|
|
|
|
|
|
const SIDEBOARD_HEIGHT: f32 = 0.1;
|
|
|
|
const STOVE_HEIGHT: f32 = 0.025;
|
|
|
|
const SINK_HEIGHT: f32 = 0.5;
|
|
|
|
|
|
|
|
#[allow(clippy::single_match, unreachable_patterns)] // we'll add more stuff later
|
2024-07-07 11:50:35 +02:00
|
|
|
match room_type {
|
2024-07-07 12:33:22 +02:00
|
|
|
_ => {
|
|
|
|
// in a kitchen, we always add a fridge
|
|
|
|
let fridge_pos = u8::gen_range(0, 2) * (width - 1);
|
|
|
|
empty_spots.swap_remove(&fridge_pos);
|
2024-07-07 11:50:35 +02:00
|
|
|
furnitures.push((
|
2024-07-07 12:33:22 +02:00
|
|
|
vec2(fridge_pos as f32, 0.0),
|
2024-07-07 11:50:35 +02:00
|
|
|
vec2(1.0, 2.0),
|
|
|
|
Furniture::new("kitchen", "fridge", ctx)
|
|
|
|
));
|
2024-07-07 12:33:22 +02:00
|
|
|
|
|
|
|
// and we always add an oven
|
|
|
|
let Some(oven_pos) = random_empty_spot(&mut empty_spots) else {
|
|
|
|
error!("How can I not fit an oven in a kitchen?!?");
|
|
|
|
return furnitures;
|
|
|
|
};
|
2024-07-07 11:50:35 +02:00
|
|
|
furnitures.push((
|
2024-07-07 12:33:22 +02:00
|
|
|
vec2(oven_pos as f32, 0.0),
|
2024-07-07 11:50:35 +02:00
|
|
|
vec2(1.0, 1.0),
|
2024-07-07 12:33:22 +02:00
|
|
|
Furniture::new("kitchen", "oven", ctx)
|
|
|
|
));
|
|
|
|
|
|
|
|
// there's always sideboard above the oven with a stove
|
|
|
|
furnitures.push((
|
|
|
|
vec2(oven_pos as f32, 1.0),
|
|
|
|
vec2(1.0, SIDEBOARD_HEIGHT),
|
|
|
|
Furniture::new("kitchen", "sideboard_1", ctx)
|
2024-07-07 11:50:35 +02:00
|
|
|
));
|
|
|
|
furnitures.push((
|
2024-07-07 12:33:22 +02:00
|
|
|
vec2(oven_pos as f32, 1.0 + SIDEBOARD_HEIGHT),
|
|
|
|
vec2(1.0, STOVE_HEIGHT),
|
|
|
|
Furniture::new("kitchen", "stove", ctx)
|
|
|
|
));
|
|
|
|
|
|
|
|
// and we always add a drawer that houses a sink
|
|
|
|
let Some(sink_pos) = random_empty_spot(&mut empty_spots) else {
|
|
|
|
error!("How can I not fit a sink in a kitchen?!?");
|
|
|
|
return furnitures;
|
|
|
|
};
|
|
|
|
furnitures.push((
|
|
|
|
vec2(sink_pos as f32, 0.0),
|
2024-07-07 11:50:35 +02:00
|
|
|
vec2(1.0, 1.0),
|
2024-07-07 12:33:22 +02:00
|
|
|
Furniture::new("kitchen", "drawer_cupboard", ctx)
|
2024-07-07 11:50:35 +02:00
|
|
|
));
|
2024-07-07 12:33:22 +02:00
|
|
|
|
|
|
|
// there's always sideboard above that drawer with a sink **behind** it
|
|
|
|
furnitures.push((
|
|
|
|
vec2(sink_pos as f32, 1.0),
|
|
|
|
vec2(1.0, SINK_HEIGHT),
|
|
|
|
Furniture::new("kitchen", "sink", ctx)
|
|
|
|
));
|
|
|
|
furnitures.push((
|
|
|
|
vec2(sink_pos as f32, 1.0),
|
|
|
|
vec2(1.0, SIDEBOARD_HEIGHT),
|
|
|
|
Furniture::new("kitchen", "sideboard_1", ctx)
|
|
|
|
));
|
|
|
|
|
|
|
|
// let's add half of the remaining positions as drawers
|
|
|
|
for _ in 0 .. empty_spots.len() / 2 {
|
|
|
|
let asset = match u8::gen_range(0, 2) {
|
|
|
|
0 => "drawer",
|
|
|
|
1 => "drawer_cupboard",
|
|
|
|
_ => unreachable!()
|
|
|
|
};
|
|
|
|
let Some(spot) = random_empty_spot(&mut empty_spots) else {
|
|
|
|
error!("WTF I shouldn't've used more than half of the available spots");
|
|
|
|
return furnitures;
|
|
|
|
};
|
|
|
|
furnitures.push((
|
|
|
|
vec2(spot as f32, 0.0),
|
|
|
|
vec2(1.0, 1.0),
|
|
|
|
Furniture::new("kitchen", asset, ctx)
|
|
|
|
));
|
|
|
|
furnitures.push((
|
|
|
|
vec2(spot as f32, 1.0),
|
|
|
|
vec2(1.0, SIDEBOARD_HEIGHT),
|
|
|
|
Furniture::new("kitchen", "sideboard_1", ctx)
|
|
|
|
));
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
2024-07-07 11:50:35 +02:00
|
|
|
_ => {}
|
|
|
|
}
|
|
|
|
|
|
|
|
furnitures
|
|
|
|
}
|
|
|
|
|
2024-07-07 11:38:13 +02:00
|
|
|
fn create_grid(width: u8, height: u8) -> Grid {
|
2024-07-07 00:48:37 +02:00
|
|
|
error!("START GRID CREATION!");
|
2024-07-07 00:01:46 +02:00
|
|
|
let left_border = width as f32 / 2.0;
|
|
|
|
let lower_border = height as f32 / 2.0;
|
|
|
|
|
|
|
|
//Lower Cable
|
|
|
|
let lower_cable_y = height as f32 / 6.0;
|
|
|
|
let mut current_x = -0.5;
|
|
|
|
|
|
|
|
let mut nodes = Vec::new();
|
2024-07-07 00:48:37 +02:00
|
|
|
let max_offset = ((width / 2) as i32).max(1);
|
|
|
|
|
2024-07-07 00:01:46 +02:00
|
|
|
while current_x < width as f32 {
|
2024-07-07 11:38:13 +02:00
|
|
|
nodes.push(vec2(
|
|
|
|
(current_x - left_border) * SCALE,
|
|
|
|
(lower_cable_y - lower_border) * SCALE
|
|
|
|
));
|
2024-07-07 00:48:37 +02:00
|
|
|
current_x += random_i32(1, max_offset) as f32;
|
2024-07-07 00:01:46 +02:00
|
|
|
}
|
|
|
|
current_x = width as f32 + 0.5;
|
2024-07-07 11:38:13 +02:00
|
|
|
nodes.push(vec2(
|
|
|
|
(current_x - left_border) * SCALE,
|
|
|
|
(lower_cable_y - lower_border) * SCALE
|
|
|
|
));
|
2024-07-07 00:01:46 +02:00
|
|
|
|
|
|
|
let mut connections = Vec::new();
|
2024-07-07 11:38:13 +02:00
|
|
|
for i in 1 .. nodes.len() {
|
|
|
|
connections.push((i - 1, i));
|
2024-07-07 00:01:46 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//Lamps
|
|
|
|
let upper_cable_y = height as f32 - 0.25;
|
|
|
|
let max_lamps = (width as f32 / 2.5).round() as i32;
|
|
|
|
let lamp_amount = random_i32(1, max_lamps + 1);
|
2024-07-07 11:38:13 +02:00
|
|
|
let node_indices: HashSet<usize> = (0 .. lamp_amount)
|
|
|
|
.map(|_| random_i32(1, nodes.len() as i32 - 1) as usize)
|
|
|
|
.collect();
|
|
|
|
|
2024-07-07 00:01:46 +02:00
|
|
|
let last_lower_node_index = nodes.len();
|
|
|
|
for (i, index) in node_indices.iter().enumerate() {
|
2024-07-07 11:38:13 +02:00
|
|
|
nodes.push(vec2(
|
|
|
|
nodes.get(*index).unwrap().x,
|
|
|
|
(upper_cable_y - lower_border) * SCALE
|
|
|
|
));
|
2024-07-07 00:01:46 +02:00
|
|
|
connections.push((*index, last_lower_node_index + i));
|
|
|
|
}
|
|
|
|
|
|
|
|
Grid::new(nodes, connections)
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn draw(&self) {
|
|
|
|
let (width, height) = self.size;
|
|
|
|
|
2024-07-07 12:33:22 +02:00
|
|
|
draw_rect(
|
|
|
|
vec2(0.0, 0.0),
|
|
|
|
vec2(width as f32 * SCALE, height as f32 * SCALE),
|
|
|
|
PURPLE,
|
|
|
|
game::ZLayer::MapMax as i32 - 2
|
|
|
|
);
|
2024-07-07 11:38:13 +02:00
|
|
|
draw_rect_outline(
|
|
|
|
vec2(0.0, 0.0),
|
|
|
|
vec2(width as f32 * SCALE, height as f32 * SCALE),
|
|
|
|
0.3,
|
|
|
|
RED,
|
2024-07-07 12:33:22 +02:00
|
|
|
game::ZLayer::MapMax as i32 - 1
|
2024-07-07 11:38:13 +02:00
|
|
|
);
|
|
|
|
|
|
|
|
for (pos, size, furniture) in &self.furnitures {
|
|
|
|
let mut pos = *pos - vec2(width as f32 / 2.0, height as f32 / 2.0);
|
|
|
|
pos += *size * 0.5;
|
|
|
|
|
|
|
|
if let Some(texture) = furniture.get_human_texture_handle() {
|
|
|
|
draw_sprite(
|
|
|
|
texture,
|
|
|
|
pos * SCALE,
|
|
|
|
WHITE,
|
|
|
|
game::ZLayer::MapMax.into(),
|
|
|
|
*size * SCALE
|
|
|
|
);
|
|
|
|
} else {
|
|
|
|
draw_rect_outline(
|
|
|
|
pos * SCALE,
|
|
|
|
*size * SCALE,
|
|
|
|
0.3,
|
|
|
|
GREEN,
|
|
|
|
game::ZLayer::MapMax.into()
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
2024-07-07 00:01:46 +02:00
|
|
|
|
|
|
|
self.grid.draw();
|
|
|
|
}
|
|
|
|
}
|