diff --git a/Cargo.lock b/Cargo.lock index b45ae10..0813c91 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2129,6 +2129,7 @@ version = "0.1.0" dependencies = [ "comfy", "heck", + "indexmap", "resvg", ] diff --git a/Cargo.toml b/Cargo.toml index 38a2d18..585ce2b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,6 +16,7 @@ opt-level = 3 [dependencies] comfy = { version = "0.4.0", features = ["wayland"] } +indexmap = "2" [build-dependencies] heck = "0.5" diff --git a/assets/furniture/blender.png b/assets/furniture/blender.png new file mode 100644 index 0000000..bfe9e9c Binary files /dev/null and b/assets/furniture/blender.png differ diff --git a/assets/furniture/cupboard.png b/assets/furniture/cupboard.png new file mode 100644 index 0000000..f35cf2b Binary files /dev/null and b/assets/furniture/cupboard.png differ diff --git a/assets/furniture/dishwasher.png b/assets/furniture/dishwasher.png new file mode 100644 index 0000000..e804519 Binary files /dev/null and b/assets/furniture/dishwasher.png differ diff --git a/assets/furniture/drawer.png b/assets/furniture/drawer.png new file mode 100644 index 0000000..fa924d2 Binary files /dev/null and b/assets/furniture/drawer.png differ diff --git a/assets/furniture/drawer_cupboard.png b/assets/furniture/drawer_cupboard.png new file mode 100644 index 0000000..42887b6 Binary files /dev/null and b/assets/furniture/drawer_cupboard.png differ diff --git a/assets/furniture/dryer.png b/assets/furniture/dryer.png new file mode 100644 index 0000000..e798a8b Binary files /dev/null and b/assets/furniture/dryer.png differ diff --git a/assets/furniture/elec/blender.png b/assets/furniture/elec/blender.png new file mode 100644 index 0000000..f0f3a90 Binary files /dev/null and b/assets/furniture/elec/blender.png differ diff --git a/assets/furniture/elec/dishwasher.png b/assets/furniture/elec/dishwasher.png new file mode 100644 index 0000000..6fd60a1 Binary files /dev/null and b/assets/furniture/elec/dishwasher.png differ diff --git a/assets/furniture/elec/dryer.png b/assets/furniture/elec/dryer.png new file mode 100644 index 0000000..30c97a7 Binary files /dev/null and b/assets/furniture/elec/dryer.png differ diff --git a/assets/furniture/elec/fridge.png b/assets/furniture/elec/fridge.png new file mode 100644 index 0000000..8878c75 Binary files /dev/null and b/assets/furniture/elec/fridge.png differ diff --git a/assets/furniture/elec/kettle.png b/assets/furniture/elec/kettle.png new file mode 100644 index 0000000..29b9e3c Binary files /dev/null and b/assets/furniture/elec/kettle.png differ diff --git a/assets/furniture/elec/minifridge.png b/assets/furniture/elec/minifridge.png new file mode 100644 index 0000000..fefb063 Binary files /dev/null and b/assets/furniture/elec/minifridge.png differ diff --git a/assets/furniture/elec/oven.png b/assets/furniture/elec/oven.png new file mode 100644 index 0000000..c2e501b Binary files /dev/null and b/assets/furniture/elec/oven.png differ diff --git a/assets/furniture/elec/stove.png b/assets/furniture/elec/stove.png new file mode 100644 index 0000000..e07dc22 Binary files /dev/null and b/assets/furniture/elec/stove.png differ diff --git a/assets/furniture/elec/toaster.png b/assets/furniture/elec/toaster.png new file mode 100644 index 0000000..67fd14f Binary files /dev/null and b/assets/furniture/elec/toaster.png differ diff --git a/assets/furniture/elec/washing_machine.png b/assets/furniture/elec/washing_machine.png new file mode 100644 index 0000000..24c3b5a Binary files /dev/null and b/assets/furniture/elec/washing_machine.png differ diff --git a/assets/furniture/fridge.png b/assets/furniture/fridge.png new file mode 100644 index 0000000..889dd29 Binary files /dev/null and b/assets/furniture/fridge.png differ diff --git a/assets/furniture/hanging_cupboard.png b/assets/furniture/hanging_cupboard.png new file mode 100644 index 0000000..2028555 Binary files /dev/null and b/assets/furniture/hanging_cupboard.png differ diff --git a/assets/furniture/kettle.png b/assets/furniture/kettle.png new file mode 100644 index 0000000..3fc8cb8 Binary files /dev/null and b/assets/furniture/kettle.png differ diff --git a/assets/furniture/metal/blender.png b/assets/furniture/metal/blender.png new file mode 100644 index 0000000..84cde50 Binary files /dev/null and b/assets/furniture/metal/blender.png differ diff --git a/assets/furniture/metal/cupboard.png b/assets/furniture/metal/cupboard.png new file mode 100644 index 0000000..7a8f88f Binary files /dev/null and b/assets/furniture/metal/cupboard.png differ diff --git a/assets/furniture/metal/dishwasher.png b/assets/furniture/metal/dishwasher.png new file mode 100644 index 0000000..2dbde95 Binary files /dev/null and b/assets/furniture/metal/dishwasher.png differ diff --git a/assets/furniture/metal/drawer.png b/assets/furniture/metal/drawer.png new file mode 100644 index 0000000..06c33cb Binary files /dev/null and b/assets/furniture/metal/drawer.png differ diff --git a/assets/furniture/metal/drawer_cupboard.png b/assets/furniture/metal/drawer_cupboard.png new file mode 100644 index 0000000..18f28bc Binary files /dev/null and b/assets/furniture/metal/drawer_cupboard.png differ diff --git a/assets/furniture/metal/dryer.png b/assets/furniture/metal/dryer.png new file mode 100644 index 0000000..6614123 Binary files /dev/null and b/assets/furniture/metal/dryer.png differ diff --git a/assets/furniture/metal/fridge.png b/assets/furniture/metal/fridge.png new file mode 100644 index 0000000..13beb26 Binary files /dev/null and b/assets/furniture/metal/fridge.png differ diff --git a/assets/furniture/metal/hanging_cupboard.png b/assets/furniture/metal/hanging_cupboard.png new file mode 100644 index 0000000..2375c23 Binary files /dev/null and b/assets/furniture/metal/hanging_cupboard.png differ diff --git a/assets/furniture/metal/kettle.png b/assets/furniture/metal/kettle.png new file mode 100644 index 0000000..3131431 Binary files /dev/null and b/assets/furniture/metal/kettle.png differ diff --git a/assets/furniture/metal/minifridge.png b/assets/furniture/metal/minifridge.png new file mode 100644 index 0000000..db315f8 Binary files /dev/null and b/assets/furniture/metal/minifridge.png differ diff --git a/assets/furniture/metal/oven.png b/assets/furniture/metal/oven.png new file mode 100644 index 0000000..446c166 Binary files /dev/null and b/assets/furniture/metal/oven.png differ diff --git a/assets/furniture/metal/sink.png b/assets/furniture/metal/sink.png new file mode 100644 index 0000000..3f1356e Binary files /dev/null and b/assets/furniture/metal/sink.png differ diff --git a/assets/furniture/metal/stove.png b/assets/furniture/metal/stove.png new file mode 100644 index 0000000..318c288 Binary files /dev/null and b/assets/furniture/metal/stove.png differ diff --git a/assets/furniture/metal/toaster.png b/assets/furniture/metal/toaster.png new file mode 100644 index 0000000..9a0532d Binary files /dev/null and b/assets/furniture/metal/toaster.png differ diff --git a/assets/furniture/metal/washing_machine.png b/assets/furniture/metal/washing_machine.png new file mode 100644 index 0000000..a7ad67f Binary files /dev/null and b/assets/furniture/metal/washing_machine.png differ diff --git a/assets/furniture/minifridge.png b/assets/furniture/minifridge.png new file mode 100644 index 0000000..c9a73dd Binary files /dev/null and b/assets/furniture/minifridge.png differ diff --git a/assets/furniture/oven.png b/assets/furniture/oven.png new file mode 100644 index 0000000..189570c Binary files /dev/null and b/assets/furniture/oven.png differ diff --git a/assets/furniture/sideboard_1.png b/assets/furniture/sideboard_1.png new file mode 100644 index 0000000..68767cb Binary files /dev/null and b/assets/furniture/sideboard_1.png differ diff --git a/assets/furniture/sideboard_2.png b/assets/furniture/sideboard_2.png new file mode 100644 index 0000000..227b266 Binary files /dev/null and b/assets/furniture/sideboard_2.png differ diff --git a/assets/furniture/sideboard_3.png b/assets/furniture/sideboard_3.png new file mode 100644 index 0000000..6c65a5c Binary files /dev/null and b/assets/furniture/sideboard_3.png differ diff --git a/assets/furniture/sideboard_3.png.png b/assets/furniture/sideboard_3.png.png new file mode 100644 index 0000000..98d6c7c Binary files /dev/null and b/assets/furniture/sideboard_3.png.png differ diff --git a/assets/furniture/sink.png b/assets/furniture/sink.png new file mode 100644 index 0000000..a6c5edf Binary files /dev/null and b/assets/furniture/sink.png differ diff --git a/assets/furniture/stove.png b/assets/furniture/stove.png new file mode 100644 index 0000000..f724460 Binary files /dev/null and b/assets/furniture/stove.png differ diff --git a/assets/furniture/toaster.png b/assets/furniture/toaster.png new file mode 100644 index 0000000..e263173 Binary files /dev/null and b/assets/furniture/toaster.png differ diff --git a/assets/furniture/washing_machine.png b/assets/furniture/washing_machine.png new file mode 100644 index 0000000..8c75234 Binary files /dev/null and b/assets/furniture/washing_machine.png differ diff --git a/src/activities/house/furniture.rs b/src/activities/house/furniture.rs new file mode 100644 index 0000000..f66811e --- /dev/null +++ b/src/activities/house/furniture.rs @@ -0,0 +1,113 @@ +use comfy::{error, texture_id, EngineContext, HashSet, Lazy, Mutex, TextureHandle}; +use std::{fmt::Debug, fs, io, sync::Arc}; + +static ASSETS_LOADED: Lazy>>> = + Lazy::new(|| Arc::new(Mutex::new(HashSet::new()))); + +#[derive(Debug)] +struct FurnitureAsset { + folder: String, + name: String +} + +#[derive(Debug)] +struct FurnitureTextureHandles { + human: Option, + magnet: Option, + elec: Option +} + +impl FurnitureAsset { + fn asset_path(&self) -> String { + format!("{}/{}.png", self.folder, self.name) + } + + fn asset_path_magnet(&self) -> String { + format!("{}/magnet/{}.png", self.folder, self.name) + } + + fn asset_path_elec(&self) -> String { + format!("{}/elec/{}.png", self.folder, self.name) + } + + fn load_asset_path( + &self, + path: String, + ctx: &mut EngineContext<'_> + ) -> Option { + let mut loaded = ASSETS_LOADED.lock(); + if loaded.contains(&path) { + return Some(texture_id(&path)); + } + let bytes = match fs::read(format!( + "{}/assets/furniture/{path}", + env!("CARGO_MANIFEST_DIR") + )) { + Ok(bytes) => bytes, + Err(err) if err.kind() == io::ErrorKind::NotFound => return None, + Err(err) => { + error!("Failed to load asset {path:?}: {err}"); + return None; + } + }; + ctx.load_texture_from_bytes(&path, &bytes); + let handle = texture_id(&path); + loaded.insert(path); + Some(handle) + } + + /// Attempt to load the assets. Silently ignore missing assets. + fn load_assets(&self, ctx: &mut EngineContext<'_>) -> FurnitureTextureHandles { + FurnitureTextureHandles { + human: self.load_asset_path(self.asset_path(), ctx), + magnet: self.load_asset_path(self.asset_path_magnet(), ctx), + elec: self.load_asset_path(self.asset_path_elec(), ctx) + } + } +} + +pub struct Furniture { + asset: FurnitureAsset, + handles: FurnitureTextureHandles, + on: Box bool> +} + +impl Debug for Furniture { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("Furniture") + .field("asset", &self.asset) + .field("handles", &self.handles) + .finish_non_exhaustive() + } +} + +impl Furniture { + pub fn new, N: Into>( + folder: F, + name: N, + ctx: &mut EngineContext<'_> + ) -> Self { + let asset = FurnitureAsset { + folder: folder.into(), + name: name.into() + }; + let handles = asset.load_assets(ctx); + Self { + asset, + handles, + on: Box::new(|| false) + } + } + + pub fn get_human_texture_handle(&self) -> Option { + self.handles.human + } + + pub fn get_elec_texture_handle(&self) -> Option { + self.handles.elec + } + + pub fn get_magnet_texture_handle(&self) -> Option { + self.handles.magnet + } +} diff --git a/src/activities/house/grid.rs b/src/activities/house/grid.rs index 5922fd9..9cf5752 100644 --- a/src/activities/house/grid.rs +++ b/src/activities/house/grid.rs @@ -13,6 +13,13 @@ impl Default for Grid { } impl Grid { + pub fn new(nodes: Vec, connections: Vec<(usize, usize)>) -> Self { + let mut grid = Grid { nodes, connections }; + grid.sanitize(); + + grid + } + fn load() -> Self { let mut grid = Self { nodes: vec![ diff --git a/src/activities/house/mod.rs b/src/activities/house/mod.rs index c856690..7d43dc3 100644 --- a/src/activities/house/mod.rs +++ b/src/activities/house/mod.rs @@ -1,26 +1,52 @@ +mod furniture; mod grid; mod player; +mod room; -use grid::Grid; -use player::Player; +use self::{grid::Grid, player::Player, room::Room}; +use crate::State; +use comfy::{error, EngineContext}; -#[derive(Debug, Default)] +#[derive(Debug)] pub struct HouseState { - grid: Grid, + room: Room, + //grid: Grid, player: Player } -pub fn draw(state: &crate::State, _engine: &comfy::EngineContext<'_>) { - if let Some(house) = state.house() { - //Draw Grid - house.grid.draw(); - - //Draw Player - house.player.draw(); +impl HouseState { + pub fn generate_new_house(ctx: &mut EngineContext<'_>) -> Self { + let room = Room::new(ctx); + let player = Player::new(&room); + HouseState { room, player } } } -pub fn update(state: &mut crate::State, _engine: &mut comfy::EngineContext<'_>) { - let house = state.house_mut(); - house.player.update(&house.grid); +pub fn draw(state: &State, _ctx: &comfy::EngineContext<'_>) { + let Some(house) = state.house() else { + error!("How can I render a house when I'm not in one?!?"); + return; + }; + + //Draw House + house.room.draw(); + + //Draw Grid + //state.house.grid.draw(); + + //Draw Player + house.player.draw(); +} + +pub fn update(state: &mut State, ctx: &mut comfy::EngineContext<'_>) { + let house = state.house_mut(ctx); + house.player.update(&house.room.grid); + + if house.player.is_moving_to_right_room(&house.room) { + house.room = Room::new(ctx); + house.player.reset_on_room(&house.room, true); + } else if house.player.is_moving_to_left_room(&house.room) { + house.room = Room::new(ctx); + house.player.reset_on_room(&house.room, false); + } } diff --git a/src/activities/house/player.rs b/src/activities/house/player.rs index e7bc726..23389fb 100644 --- a/src/activities/house/player.rs +++ b/src/activities/house/player.rs @@ -1,4 +1,7 @@ -use super::Grid; +use super::{ + room::{Room, SCALE}, + Grid +}; use comfy::{delta, draw_circle, is_key_down, vec2, KeyCode, Vec2, RED}; use std::collections::HashSet; @@ -10,20 +13,23 @@ pub struct Player { next_connections: Vec } -impl Default for Player { - fn default() -> Self { - Self { - position: Default::default(), +impl Player { + pub fn new(room: &Room) -> Self { + Player { + position: vec2( + ((0.25) - room.size.0 as f32 / 2.0) * SCALE, + room.grid.nodes.first().unwrap().y + ), speed: 10.0, connection: 0, - next_connections: vec![1, 2, 3] + next_connections: vec![1] } } -} -impl Player { + pub fn draw(&self) { draw_circle(self.position, 0.5, RED, 0); } + pub fn update(&mut self, grid: &Grid) { let allowed_movement = get_allowed_movement(self, grid); @@ -33,6 +39,27 @@ impl Player { snap_to_closest_node(self, grid); } } + + pub fn is_moving_to_right_room(&self, room: &Room) -> bool { + self.position.x > (room.size.0 as f32 / 2.0) * SCALE + } + + pub fn is_moving_to_left_room(&self, room: &Room) -> bool { + self.position.x < -(room.size.0 as f32 / 2.0) * SCALE + } + + pub fn reset_on_room(&mut self, room: &Room, place_left: bool) { + let offset = 0.1; + let x = if place_left { + (offset - room.size.0 as f32 / 2.0) * SCALE + } else { + (room.size.0 as f32 / 2.0 - offset) * SCALE + }; + + self.position = vec2(x, room.grid.nodes.first().unwrap().y); + self.connection = 0; + self.next_connections = vec![1]; + } } fn move_player(player: &mut Player, allowed_movement: (bool, bool, bool, bool)) { diff --git a/src/activities/house/room.rs b/src/activities/house/room.rs new file mode 100644 index 0000000..e3cecb8 --- /dev/null +++ b/src/activities/house/room.rs @@ -0,0 +1,355 @@ +use super::{furniture::Furniture, grid::Grid}; +use crate::game; +use comfy::{ + draw_rect, draw_rect_outline, draw_sprite, error, random_i32, vec2, EngineContext, + HashSet, RandomRange as _, Vec2, GREEN, PURPLE, RED, WHITE +}; +use indexmap::IndexSet; + +pub const SCALE: f32 = 4.0; + +#[derive(Debug, PartialEq)] +enum RoomType { + Kitchen, + Bath, + Toilett, + LivingRoom, + SleepingRoom +} + +#[derive(Debug)] +struct Tile { + pos: Vec2, + size: Vec2, + f: Furniture, + z: i32 +} + +#[derive(Debug)] +pub struct Room { + _room_type: RoomType, + pub size: (u8, u8), //(width, height) + pub grid: Grid, + furnitures: Vec +} + +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 { + pub fn new(ctx: &mut EngineContext<'_>) -> Self { + let room_type = RoomType::random(); + let size = Self::random_size(&room_type); + + let furnitures = Self::random_room_furniture(&room_type, size, ctx); + + Room { + _room_type: room_type, + size, + grid: Self::create_grid(size.0, size.1), + furnitures + } + } + + fn random_size(room_type: &RoomType) -> (u8, u8) { + //Kitchen + Living Room 5-8 + //Bath + sleepingroom 4-6 + //Toilet 2-3 + match room_type { + 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) + } + } + + fn random_room_furniture( + room_type: &RoomType, + (width, _height): (u8, u8), + ctx: &mut EngineContext<'_> + ) -> Vec { + let mut furnitures = Vec::new(); + + let mut empty_spots: IndexSet = (0 .. width).collect(); + + fn random_empty_spot(empty_spots: &mut IndexSet) -> Option { + if empty_spots.is_empty() { + return None; + } + let random_idx = usize::gen_range(0, empty_spots.len()); + empty_spots.swap_remove_index(random_idx) + } + fn random_appliance(empty_spots: &mut Vec) -> Option { + if empty_spots.is_empty() { + return None; + } + let random_idx = usize::gen_range(0, empty_spots.len()); + Some(empty_spots.swap_remove(random_idx)) + } + + const SIDEBOARD_HEIGHT: f32 = 0.1; + const STOVE_HEIGHT: f32 = 0.025; + const SINK_HEIGHT: f32 = 0.5; + + #[allow(clippy::single_match)] // we'll add more stuff later + match room_type { + RoomType::Kitchen => { + // in a kitchen, we always add a fridge + let fridge_pos = u8::gen_range(0, 2) * (width - 1); + empty_spots.swap_remove(&fridge_pos); + furnitures.push(Tile { + pos: vec2(fridge_pos as f32, 0.0), + size: vec2(1.0, 2.0), + f: Furniture::new("kitchen", "fridge", ctx), + z: 0 + }); + + // 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; + }; + furnitures.push(Tile { + pos: vec2(oven_pos as f32, 0.0), + size: vec2(1.0, 1.0), + f: Furniture::new("kitchen", "oven", ctx), + z: 0 + }); + + // there's always sideboard above the oven with a stove + furnitures.push(Tile { + pos: vec2(oven_pos as f32, 1.0), + size: vec2(1.0, SIDEBOARD_HEIGHT), + f: Furniture::new("kitchen", "sideboard_1", ctx), + z: 1 + }); + furnitures.push(Tile { + pos: vec2(oven_pos as f32, 1.0 + SIDEBOARD_HEIGHT), + size: vec2(1.0, STOVE_HEIGHT), + f: Furniture::new("kitchen", "stove", ctx), + z: 0 + }); + + // 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(Tile { + pos: vec2(sink_pos as f32, 0.0), + size: vec2(1.0, 1.0), + f: Furniture::new("kitchen", "drawer_cupboard", ctx), + z: 0 + }); + + // there's always sideboard above that drawer with a sink **behind** it + furnitures.push(Tile { + pos: vec2(sink_pos as f32, 1.0), + size: vec2(1.0, SINK_HEIGHT), + f: Furniture::new("kitchen", "sink", ctx), + z: 0 + }); + furnitures.push(Tile { + pos: vec2(sink_pos as f32, 1.0), + size: vec2(1.0, SIDEBOARD_HEIGHT), + f: Furniture::new("kitchen", "sideboard_1", ctx), + z: 1 + }); + + // the current list of empty spots is the same list we can use to place + // on-the-counter appliances later + let mut empty_spots_clone = empty_spots.clone(); + + // build a list of the remaining kitchen appliances. we only want them + // included once, most kitchens don't contain two washing machines etc + let mut remaining_appliances: IndexSet<&'static str> = + ["dishwasher", "dryer", "minifridge", "washing_machine"] + .into_iter() + .collect(); + + // let's add at most half of the remaining positions as big appliances + for _ in 0 .. empty_spots.len() / 2 { + let Some(asset) = random_empty_spot(&mut remaining_appliances) else { + break; + }; + 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(Tile { + pos: vec2(spot as f32, 0.0), + size: vec2(1.0, 1.0), + f: Furniture::new("kitchen", asset, ctx), + z: 0 + }); + furnitures.push(Tile { + pos: vec2(spot as f32, 1.0), + size: vec2(1.0, SIDEBOARD_HEIGHT), + f: Furniture::new("kitchen", "sideboard_1", ctx), + z: 1 + }); + } + + // and fill the remainder with drawers + while !empty_spots.is_empty() { + 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 should still have spots available"); + return furnitures; + }; + furnitures.push(Tile { + pos: vec2(spot as f32, 0.0), + size: vec2(1.0, 1.0), + f: Furniture::new("kitchen", asset, ctx), + z: 0 + }); + furnitures.push(Tile { + pos: vec2(spot as f32, 1.0), + size: vec2(1.0, SIDEBOARD_HEIGHT), + f: Furniture::new("kitchen", "sideboard_1", ctx), + z: 1 + }); + } + + // build a list of on-the-counter kitchen appliances. we only want them + // included once, most kitchens don't contain two toasters etc + let mut remaining_appliances: Vec<(&'static str, f32, f32)> = [ + ("blender", 0.3, 0.45), + ("kettle", 0.3, 0.4), + ("toaster", 0.5, 0.25) + ] + .into_iter() + .collect(); + + // and then we fill like half the counter with appliances + for _ in 0 .. empty_spots_clone.len() / 2 { + let Some((asset, asset_w, asset_h)) = + random_appliance(&mut remaining_appliances) + else { + break; + }; + let Some(spot) = random_empty_spot(&mut empty_spots_clone) else { + error!("WTF I shouldn't've used more than half of the available spots"); + return furnitures; + }; + furnitures.push(Tile { + pos: vec2(spot as f32 + 0.5, 1.0 + SIDEBOARD_HEIGHT), + size: vec2(asset_w, asset_h), + f: Furniture::new("kitchen", asset, ctx), + z: 0 + }); + } + }, + + _ => {} + } + + furnitures + } + + fn create_grid(width: u8, height: u8) -> Grid { + error!("START GRID CREATION!"); + 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(); + let max_offset = ((width / 2) as i32).max(1); + + while current_x < width as f32 { + nodes.push(vec2( + (current_x - left_border) * SCALE, + (lower_cable_y - lower_border) * SCALE + )); + current_x += random_i32(1, max_offset) as f32; + } + current_x = width as f32 + 0.5; + nodes.push(vec2( + (current_x - left_border) * SCALE, + (lower_cable_y - lower_border) * SCALE + )); + + let mut connections = Vec::new(); + for i in 1 .. nodes.len() { + connections.push((i - 1, i)); + } + + //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); + let node_indices: HashSet = (0 .. lamp_amount) + .map(|_| random_i32(1, nodes.len() as i32 - 1) as usize) + .collect(); + + let last_lower_node_index = nodes.len(); + for (i, index) in node_indices.iter().enumerate() { + nodes.push(vec2( + nodes.get(*index).unwrap().x, + (upper_cable_y - lower_border) * SCALE + )); + connections.push((*index, last_lower_node_index + i)); + } + + Grid::new(nodes, connections) + } + + pub fn draw(&self) { + let (width, height) = self.size; + + draw_rect( + vec2(0.0, 0.0), + vec2(width as f32 * SCALE, height as f32 * SCALE), + PURPLE, + game::ZLayer::MapMax as i32 - 2 + ); + draw_rect_outline( + vec2(0.0, 0.0), + vec2(width as f32 * SCALE, height as f32 * SCALE), + 0.3, + RED, + game::ZLayer::MapMax as i32 - 1 + ); + + for tile in &self.furnitures { + let mut pos = tile.pos - vec2(width as f32 / 2.0, height as f32 / 2.0); + pos += tile.size * 0.5; + + if let Some(texture) = tile.f.get_human_texture_handle() { + draw_sprite( + texture, + pos * SCALE, + WHITE, + game::ZLayer::MapMax as i32 + tile.z, + tile.size * SCALE + ); + } else { + draw_rect_outline( + pos * SCALE, + tile.size * SCALE, + 0.3, + GREEN, + game::ZLayer::MapMax as i32 + tile.z + ); + } + } + + self.grid.draw(); + } +} diff --git a/src/activities/overworld/mod.rs b/src/activities/overworld/mod.rs index d2e1613..90ea09f 100644 --- a/src/activities/overworld/mod.rs +++ b/src/activities/overworld/mod.rs @@ -1,11 +1,4 @@ -use crate::{ - activities::{ - house::{self, HouseState}, - Activity - }, - game::ZLayer, - State -}; +use crate::{activities::Activity, game::ZLayer, State}; use comfy::{ draw_circle, draw_rect_outline, draw_sprite, error, info, is_key_down, main_camera_mut, EngineContext, IVec2, KeyCode, Vec2, RED, WHITE @@ -32,7 +25,7 @@ pub fn draw(state: &crate::State, _engine: &comfy::EngineContext<'_>) { draw_circle(state.ghost.overworld_pos, 0.5, RED, ZLayer::Ghost.into()); } -fn update_move_player(state: &mut State) { +fn update_move_player(state: &mut State, ctx: &mut EngineContext<'_>) { let now = Instant::now(); // Are there any pending position updates? If so, we ignore all user input and execute @@ -160,18 +153,18 @@ fn update_move_player(state: &mut State) { if current_tile.can_enter_house() { info!("enter house at {tile_pos}"); state.activity = Activity::House(tile_pos); - state.house_mut(); // gen new house + state.house_mut(ctx); // gen new house } } } -pub fn update(state: &mut State, _ctx: &mut EngineContext<'_>) { +pub fn update(state: &mut State, ctx: &mut EngineContext<'_>) { let mut camera = main_camera_mut(); camera.center = Vec2::ZERO; camera.zoom = 30.0; // move player - update_move_player(state); + update_move_player(state, ctx); // generate more chunks if needed { diff --git a/src/game.rs b/src/game.rs index 1939bfe..b39886c 100644 --- a/src/game.rs +++ b/src/game.rs @@ -1,5 +1,6 @@ use crate::{ activities::{house, overworld, Activity}, + assets::Assets, State }; use comfy::{EngineContext, Vec2}; @@ -85,6 +86,10 @@ impl Sub for ZLayer { } } +pub fn setup(_state: &mut State, ctx: &mut EngineContext<'_>) { + Assets::load(ctx); +} + pub fn update(state: &mut State, engine: &mut EngineContext<'_>) { state.score += engine.delta * 10.0; match state.activity { diff --git a/src/main.rs b/src/main.rs index f7b6e87..a84ee9b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -12,7 +12,6 @@ mod ui; use self::{ activities::{house::HouseState, overworld::worldgen::Overworld, Activity}, - assets::Assets, game::Ghost }; use comfy::{ @@ -41,13 +40,13 @@ impl State { } fn house(&self) -> Option<&HouseState> { - self.houses.get(&self.get_house_pos().unwrap()) + self.houses.get(&self.get_house_pos()?) } - fn house_mut(&mut self) -> &mut HouseState { + fn house_mut(&mut self, ctx: &mut EngineContext<'_>) -> &mut HouseState { self.houses .entry(self.get_house_pos().unwrap()) - .or_insert_with(HouseState::default) + .or_insert_with(|| HouseState::generate_new_house(ctx)) } } @@ -56,14 +55,14 @@ impl GameLoop for State { Self::default() } - fn update(&mut self, engine: &mut EngineContext<'_>) { + fn update(&mut self, ctx: &mut EngineContext<'_>) { if !self.setup_called { - setup(engine); + game::setup(self, ctx); self.setup_called = true; } - game::update(self, engine); - game::draw(self, engine); + game::update(self, ctx); + game::draw(self, ctx); } } @@ -71,10 +70,6 @@ fn config(config: GameConfig) -> GameConfig { config } -fn setup(ctx: &mut EngineContext<'_>) { - Assets::load(ctx); -} - async fn run() { init_game_config(GAME_NAME.to_string(), env!("CARGO_PKG_VERSION"), config); let mut engine = EngineState::new();