diff --git a/Cargo.lock b/Cargo.lock index c22856b..0813c91 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2130,7 +2130,6 @@ dependencies = [ "comfy", "heck", "indexmap", - "log", "resvg", ] diff --git a/Cargo.toml b/Cargo.toml index 49f8e70..585ce2b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,7 +17,6 @@ opt-level = 3 [dependencies] comfy = { version = "0.4.0", features = ["wayland"] } indexmap = "2" -log = "0.4.22" [build-dependencies] heck = "0.5" diff --git a/assets/entities/ghost.png b/assets/entities/ghost.png new file mode 100644 index 0000000..065843a Binary files /dev/null and b/assets/entities/ghost.png differ diff --git a/assets/furniture/bedroom/ac.png b/assets/furniture/bedroom/ac.png new file mode 100644 index 0000000..6afd96f Binary files /dev/null and b/assets/furniture/bedroom/ac.png differ diff --git a/assets/furniture/bedroom/bed.png b/assets/furniture/bedroom/bed.png new file mode 100644 index 0000000..31a6971 Binary files /dev/null and b/assets/furniture/bedroom/bed.png differ diff --git a/assets/furniture/bedroom/bookshelf.png b/assets/furniture/bedroom/bookshelf.png new file mode 100644 index 0000000..aa1f8c6 Binary files /dev/null and b/assets/furniture/bedroom/bookshelf.png differ diff --git a/assets/furniture/bedroom/couch.png b/assets/furniture/bedroom/couch.png new file mode 100644 index 0000000..5be07ee Binary files /dev/null and b/assets/furniture/bedroom/couch.png differ diff --git a/assets/furniture/bedroom/cupboard.png b/assets/furniture/bedroom/cupboard.png new file mode 100644 index 0000000..a04685f Binary files /dev/null and b/assets/furniture/bedroom/cupboard.png differ diff --git a/assets/furniture/bedroom/display_off.png b/assets/furniture/bedroom/display_off.png new file mode 100644 index 0000000..167d216 Binary files /dev/null and b/assets/furniture/bedroom/display_off.png differ diff --git a/assets/furniture/bedroom/display_on.png b/assets/furniture/bedroom/display_on.png new file mode 100644 index 0000000..63caaa8 Binary files /dev/null and b/assets/furniture/bedroom/display_on.png differ diff --git a/assets/furniture/bedroom/drawer.png b/assets/furniture/bedroom/drawer.png new file mode 100644 index 0000000..3dc372e Binary files /dev/null and b/assets/furniture/bedroom/drawer.png differ diff --git a/assets/furniture/bedroom/elec/ac.png b/assets/furniture/bedroom/elec/ac.png new file mode 100644 index 0000000..b06c68f Binary files /dev/null and b/assets/furniture/bedroom/elec/ac.png differ diff --git a/assets/furniture/bedroom/elec/display_off.png b/assets/furniture/bedroom/elec/display_off.png new file mode 100644 index 0000000..b9c337b Binary files /dev/null and b/assets/furniture/bedroom/elec/display_off.png differ diff --git a/assets/furniture/bedroom/elec/display_on.png b/assets/furniture/bedroom/elec/display_on.png new file mode 100644 index 0000000..203edd3 Binary files /dev/null and b/assets/furniture/bedroom/elec/display_on.png differ diff --git a/assets/furniture/bedroom/elec/keyboard.png b/assets/furniture/bedroom/elec/keyboard.png new file mode 100644 index 0000000..467c6d1 Binary files /dev/null and b/assets/furniture/bedroom/elec/keyboard.png differ diff --git a/assets/furniture/bedroom/elec/laptop_off.png b/assets/furniture/bedroom/elec/laptop_off.png new file mode 100644 index 0000000..ef2125b Binary files /dev/null and b/assets/furniture/bedroom/elec/laptop_off.png differ diff --git a/assets/furniture/bedroom/elec/laptop_on.png b/assets/furniture/bedroom/elec/laptop_on.png new file mode 100644 index 0000000..0dafdfa Binary files /dev/null and b/assets/furniture/bedroom/elec/laptop_on.png differ diff --git a/assets/furniture/bedroom/elec/mini_ac.png b/assets/furniture/bedroom/elec/mini_ac.png new file mode 100644 index 0000000..72bb3e5 Binary files /dev/null and b/assets/furniture/bedroom/elec/mini_ac.png differ diff --git a/assets/furniture/bedroom/elec/mouse.png b/assets/furniture/bedroom/elec/mouse.png new file mode 100644 index 0000000..a52559f Binary files /dev/null and b/assets/furniture/bedroom/elec/mouse.png differ diff --git a/assets/furniture/bedroom/elec/nightlight.png b/assets/furniture/bedroom/elec/nightlight.png new file mode 100644 index 0000000..0453cbc Binary files /dev/null and b/assets/furniture/bedroom/elec/nightlight.png differ diff --git a/assets/furniture/bedroom/elec/pc.png b/assets/furniture/bedroom/elec/pc.png new file mode 100644 index 0000000..6dd2087 Binary files /dev/null and b/assets/furniture/bedroom/elec/pc.png differ diff --git a/assets/furniture/bedroom/elec/phone.png b/assets/furniture/bedroom/elec/phone.png new file mode 100644 index 0000000..8209f0d Binary files /dev/null and b/assets/furniture/bedroom/elec/phone.png differ diff --git a/assets/furniture/bedroom/elec/receiver.png b/assets/furniture/bedroom/elec/receiver.png new file mode 100644 index 0000000..af14a3e Binary files /dev/null and b/assets/furniture/bedroom/elec/receiver.png differ diff --git a/assets/furniture/bedroom/elec/tv.png b/assets/furniture/bedroom/elec/tv.png new file mode 100644 index 0000000..a0717a8 Binary files /dev/null and b/assets/furniture/bedroom/elec/tv.png differ diff --git a/assets/furniture/bedroom/elec/window_ac.png b/assets/furniture/bedroom/elec/window_ac.png new file mode 100644 index 0000000..de76c65 Binary files /dev/null and b/assets/furniture/bedroom/elec/window_ac.png differ diff --git a/assets/furniture/bedroom/keyboard.png b/assets/furniture/bedroom/keyboard.png new file mode 100644 index 0000000..66f9605 Binary files /dev/null and b/assets/furniture/bedroom/keyboard.png differ diff --git a/assets/furniture/bedroom/laptop_off.png b/assets/furniture/bedroom/laptop_off.png new file mode 100644 index 0000000..422ebdf Binary files /dev/null and b/assets/furniture/bedroom/laptop_off.png differ diff --git a/assets/furniture/bedroom/laptop_on.png b/assets/furniture/bedroom/laptop_on.png new file mode 100644 index 0000000..dacd39b Binary files /dev/null and b/assets/furniture/bedroom/laptop_on.png differ diff --git a/assets/furniture/bedroom/metal/ac.png b/assets/furniture/bedroom/metal/ac.png new file mode 100644 index 0000000..64331a0 Binary files /dev/null and b/assets/furniture/bedroom/metal/ac.png differ diff --git a/assets/furniture/bedroom/metal/bed.png b/assets/furniture/bedroom/metal/bed.png new file mode 100644 index 0000000..6240803 Binary files /dev/null and b/assets/furniture/bedroom/metal/bed.png differ diff --git a/assets/furniture/bedroom/metal/cupboard.png b/assets/furniture/bedroom/metal/cupboard.png new file mode 100644 index 0000000..5d456ae Binary files /dev/null and b/assets/furniture/bedroom/metal/cupboard.png differ diff --git a/assets/furniture/bedroom/metal/display_off.png b/assets/furniture/bedroom/metal/display_off.png new file mode 100644 index 0000000..317414c Binary files /dev/null and b/assets/furniture/bedroom/metal/display_off.png differ diff --git a/assets/furniture/bedroom/metal/display_on.png b/assets/furniture/bedroom/metal/display_on.png new file mode 100644 index 0000000..2911755 Binary files /dev/null and b/assets/furniture/bedroom/metal/display_on.png differ diff --git a/assets/furniture/bedroom/metal/drawer.png b/assets/furniture/bedroom/metal/drawer.png new file mode 100644 index 0000000..b3f1b0d Binary files /dev/null and b/assets/furniture/bedroom/metal/drawer.png differ diff --git a/assets/furniture/bedroom/metal/keyboard.png b/assets/furniture/bedroom/metal/keyboard.png new file mode 100644 index 0000000..16ee085 Binary files /dev/null and b/assets/furniture/bedroom/metal/keyboard.png differ diff --git a/assets/furniture/bedroom/metal/laptop_off.png b/assets/furniture/bedroom/metal/laptop_off.png new file mode 100644 index 0000000..125ec32 Binary files /dev/null and b/assets/furniture/bedroom/metal/laptop_off.png differ diff --git a/assets/furniture/bedroom/metal/laptop_on.png b/assets/furniture/bedroom/metal/laptop_on.png new file mode 100644 index 0000000..6e965a1 Binary files /dev/null and b/assets/furniture/bedroom/metal/laptop_on.png differ diff --git a/assets/furniture/bedroom/metal/mini_ac.png b/assets/furniture/bedroom/metal/mini_ac.png new file mode 100644 index 0000000..684c1d6 Binary files /dev/null and b/assets/furniture/bedroom/metal/mini_ac.png differ diff --git a/assets/furniture/bedroom/metal/mouse.png b/assets/furniture/bedroom/metal/mouse.png new file mode 100644 index 0000000..5ea958d Binary files /dev/null and b/assets/furniture/bedroom/metal/mouse.png differ diff --git a/assets/furniture/bedroom/metal/nightlight.png b/assets/furniture/bedroom/metal/nightlight.png new file mode 100644 index 0000000..68ab2bc Binary files /dev/null and b/assets/furniture/bedroom/metal/nightlight.png differ diff --git a/assets/furniture/bedroom/metal/nightstand.png b/assets/furniture/bedroom/metal/nightstand.png new file mode 100644 index 0000000..34feb95 Binary files /dev/null and b/assets/furniture/bedroom/metal/nightstand.png differ diff --git a/assets/furniture/bedroom/metal/pc.png b/assets/furniture/bedroom/metal/pc.png new file mode 100644 index 0000000..c188052 Binary files /dev/null and b/assets/furniture/bedroom/metal/pc.png differ diff --git a/assets/furniture/bedroom/metal/phone.png b/assets/furniture/bedroom/metal/phone.png new file mode 100644 index 0000000..e5dfee0 Binary files /dev/null and b/assets/furniture/bedroom/metal/phone.png differ diff --git a/assets/furniture/bedroom/metal/receiver.png b/assets/furniture/bedroom/metal/receiver.png new file mode 100644 index 0000000..85998ee Binary files /dev/null and b/assets/furniture/bedroom/metal/receiver.png differ diff --git a/assets/furniture/bedroom/metal/tv.png b/assets/furniture/bedroom/metal/tv.png new file mode 100644 index 0000000..db327b1 Binary files /dev/null and b/assets/furniture/bedroom/metal/tv.png differ diff --git a/assets/furniture/bedroom/metal/wardrobe.png b/assets/furniture/bedroom/metal/wardrobe.png new file mode 100644 index 0000000..f62a89c Binary files /dev/null and b/assets/furniture/bedroom/metal/wardrobe.png differ diff --git a/assets/furniture/bedroom/metal/window_ac.png b/assets/furniture/bedroom/metal/window_ac.png new file mode 100644 index 0000000..d05c464 Binary files /dev/null and b/assets/furniture/bedroom/metal/window_ac.png differ diff --git a/assets/furniture/bedroom/mini_ac.png b/assets/furniture/bedroom/mini_ac.png new file mode 100644 index 0000000..8cff862 Binary files /dev/null and b/assets/furniture/bedroom/mini_ac.png differ diff --git a/assets/furniture/bedroom/mouse.png b/assets/furniture/bedroom/mouse.png new file mode 100644 index 0000000..f46605b Binary files /dev/null and b/assets/furniture/bedroom/mouse.png differ diff --git a/assets/furniture/bedroom/nightlight.png b/assets/furniture/bedroom/nightlight.png new file mode 100644 index 0000000..2bfa186 Binary files /dev/null and b/assets/furniture/bedroom/nightlight.png differ diff --git a/assets/furniture/bedroom/nightstand.png b/assets/furniture/bedroom/nightstand.png new file mode 100644 index 0000000..508d115 Binary files /dev/null and b/assets/furniture/bedroom/nightstand.png differ diff --git a/assets/furniture/bedroom/pc.png b/assets/furniture/bedroom/pc.png new file mode 100644 index 0000000..3a6736f Binary files /dev/null and b/assets/furniture/bedroom/pc.png differ diff --git a/assets/furniture/bedroom/phone.png b/assets/furniture/bedroom/phone.png new file mode 100644 index 0000000..dd913e5 Binary files /dev/null and b/assets/furniture/bedroom/phone.png differ diff --git a/assets/furniture/bedroom/receiver.png b/assets/furniture/bedroom/receiver.png new file mode 100644 index 0000000..dde1fec Binary files /dev/null and b/assets/furniture/bedroom/receiver.png differ diff --git a/assets/furniture/bedroom/tv.png b/assets/furniture/bedroom/tv.png new file mode 100644 index 0000000..fb79085 Binary files /dev/null and b/assets/furniture/bedroom/tv.png differ diff --git a/assets/furniture/bedroom/tv_stand.png b/assets/furniture/bedroom/tv_stand.png new file mode 100644 index 0000000..e71737d Binary files /dev/null and b/assets/furniture/bedroom/tv_stand.png differ diff --git a/assets/furniture/bedroom/wardrobe.png b/assets/furniture/bedroom/wardrobe.png new file mode 100644 index 0000000..4914c80 Binary files /dev/null and b/assets/furniture/bedroom/wardrobe.png differ diff --git a/assets/furniture/bedroom/window.png b/assets/furniture/bedroom/window.png new file mode 100644 index 0000000..ab76274 Binary files /dev/null and b/assets/furniture/bedroom/window.png differ diff --git a/assets/furniture/bedroom/window_ac.png b/assets/furniture/bedroom/window_ac.png new file mode 100644 index 0000000..86e3d8b Binary files /dev/null and b/assets/furniture/bedroom/window_ac.png differ diff --git a/assets/sounds/bzz.mp3 b/assets/sounds/bzz.mp3 new file mode 100644 index 0000000..bde2f73 Binary files /dev/null and b/assets/sounds/bzz.mp3 differ diff --git a/src/activities/house/mod.rs b/src/activities/house/mod.rs index b6f34ed..e3ffdc0 100644 --- a/src/activities/house/mod.rs +++ b/src/activities/house/mod.rs @@ -16,7 +16,7 @@ pub struct HouseState { } pub fn setup(state: &mut crate::State, ctx: &mut EngineContext<'_>) { - let house = { + if let Some(house) = state.house() { let room = Room::new(ctx); let player = Player::new(&room); HouseState { room, player } @@ -39,8 +39,8 @@ pub fn draw(state: &crate::State, _ctx: &comfy::EngineContext<'_>) { } pub fn update(state: &mut crate::State, ctx: &mut comfy::EngineContext<'_>) { - if let Some(house) = &mut state.house { - house.player.update(&house.room.grid); + let house = state.house_mut(); + house.player.update(&house.grid); if house.player.is_moving_to_right_room(&house.room) { house.room = Room::new(ctx); @@ -49,5 +49,4 @@ pub fn update(state: &mut crate::State, ctx: &mut comfy::EngineContext<'_>) { house.room = Room::new(ctx); house.player.reset_on_room(&house.room, false); } - } } diff --git a/src/activities/mod.rs b/src/activities/mod.rs index dfa2b9e..e0afdc4 100644 --- a/src/activities/mod.rs +++ b/src/activities/mod.rs @@ -1,8 +1,11 @@ +use comfy::IVec2; + pub mod house; pub mod overworld; #[derive(Debug, Default)] pub enum Activity { + House(IVec2), #[default] House, #[allow(dead_code)] diff --git a/src/activities/overworld/mod.rs b/src/activities/overworld/mod.rs index f8bee45..d2e1613 100644 --- a/src/activities/overworld/mod.rs +++ b/src/activities/overworld/mod.rs @@ -1,9 +1,17 @@ -use comfy::{ - draw_rect_outline, draw_sprite, main_camera_mut, EngineContext, IVec2, Vec2, RED, - WHITE +use crate::{ + activities::{ + house::{self, HouseState}, + Activity + }, + game::ZLayer, + State }; - -use crate::game::ZLayer; +use comfy::{ + draw_circle, draw_rect_outline, draw_sprite, error, info, is_key_down, + main_camera_mut, EngineContext, IVec2, KeyCode, Vec2, RED, WHITE +}; +use std::time::Instant; +use worldgen::MovementCost; pub mod worldgen; @@ -21,11 +29,168 @@ pub fn draw(state: &crate::State, _engine: &comfy::EngineContext<'_>) { draw_rect_outline(coords.as_vec2(), Vec2::ONE, 0.1, RED, 10); } } + draw_circle(state.ghost.overworld_pos, 0.5, RED, ZLayer::Ghost.into()); } -pub fn update(state: &mut crate::State, _engine: &mut EngineContext<'_>) { +fn update_move_player(state: &mut State) { + let now = Instant::now(); + + // Are there any pending position updates? If so, we ignore all user input and execute + // the pending updates. + if state.ghost.overworld_movement_pending != Vec2::ZERO { + info!( + "Pending Movement: {:?}", + state.ghost.overworld_movement_pending + ); + state.ghost.update_overworld_pos(now); + return; + } + + // Otherwise, we check for user inputs, and update the pending movement accordingly. + let tile_pos = IVec2 { + x: state.ghost.overworld_pos.x.round() as _, + y: state.ghost.overworld_pos.y.round() as _ + }; + let Some(tile) = state.overworld.get_tile(tile_pos).copied() else { + error!("How can we be standing inside a non-generated tile?"); + return; + }; + + let mut requested_pos = None; + let mut requested_pos_diff = None; + let mut requested_cost_curr = None; + let mut requested_cost_new = None; + + if is_key_down(KeyCode::Up) { + let diff = IVec2 { x: 0, y: 1 }; + let new_pos = tile_pos + diff; + let new_tile = state.overworld.get_or_generate_tile(new_pos); + if new_tile.can_stand_inside() { + requested_pos = Some(new_pos); + requested_pos_diff = Some(diff); + requested_cost_curr = Some(tile.movement_cost_up()); + requested_cost_new = Some(new_tile.movement_cost_down()); + } else { + info!("Rejecting movement - cannot stand in the requested tile."); + } + } + + if is_key_down(KeyCode::Down) { + let diff = IVec2 { x: 0, y: -1 }; + let new_pos = tile_pos + diff; + let new_tile = state.overworld.get_or_generate_tile(new_pos); + if new_tile.can_stand_inside() { + requested_pos = Some(new_pos); + requested_pos_diff = Some(diff); + requested_cost_curr = Some(tile.movement_cost_down()); + requested_cost_new = Some(new_tile.movement_cost_up()); + } else { + info!("Rejecting movement - cannot stand in the requested tile."); + } + } + + if is_key_down(KeyCode::Left) { + let diff = IVec2 { x: -1, y: 0 }; + let new_pos = tile_pos + diff; + let new_tile = state.overworld.get_or_generate_tile(new_pos); + if new_tile.can_stand_inside() { + requested_pos = Some(new_pos); + requested_pos_diff = Some(diff); + requested_cost_curr = Some(tile.movement_cost_left()); + requested_cost_new = Some(new_tile.movement_cost_right()); + } else { + info!("Rejecting movement - cannot stand in the requested tile."); + } + } + + if is_key_down(KeyCode::Right) { + let diff = IVec2 { x: 1, y: 0 }; + let new_pos = tile_pos + diff; + let new_tile = state.overworld.get_or_generate_tile(new_pos); + if new_tile.can_stand_inside() { + requested_pos = Some(new_pos); + requested_pos_diff = Some(diff); + requested_cost_curr = Some(tile.movement_cost_right()); + requested_cost_new = Some(new_tile.movement_cost_left()); + } else { + info!("Rejecting movement - cannot stand in the requested tile."); + } + } + + // only continue if some movement was requested + let Some(_requested_pos) = requested_pos else { + return; + }; + let Some(requested_pos_diff) = requested_pos_diff else { + return; + }; + let Some(requested_cost_curr) = requested_cost_curr else { + return; + }; + let Some(requested_cost_new) = requested_cost_new else { + return; + }; + + state.ghost.overworld_movement_speed = match (requested_cost_curr, requested_cost_new) + { + // movement in this direction not possible + (MovementCost::Infinite, _) | (_, MovementCost::Infinite) => { + info!("Rejecting movement - movement cost is infinite"); + return; + }, + + // we are walking on a path + (MovementCost::Path, MovementCost::Path) => 10.0, + + // we are walking across an obstacle + (MovementCost::Obstacle, _) | (_, MovementCost::Obstacle) => 1.0, + + // we are walking on grass + _ => 5.0 + }; + state.ghost.overworld_movement_pending = Vec2 { + x: requested_pos_diff.x as _, + y: requested_pos_diff.y as _ + }; + state.ghost.overworld_pos_last_update = now; + + //move into house if player stepp at door + { + let current_tile = state.overworld.get_or_generate_tile(tile_pos); + if current_tile.can_enter_house() { + info!("enter house at {tile_pos}"); + state.activity = Activity::House(tile_pos); + state.house_mut(); // gen new house + } + } +} + +pub fn update(state: &mut State, _ctx: &mut EngineContext<'_>) { let mut camera = main_camera_mut(); camera.center = Vec2::ZERO; camera.zoom = 30.0; - state.overworld.get_or_generate_tile(IVec2::ZERO); + + // move player + update_move_player(state); + + // generate more chunks if needed + { + let half_viewport = (camera.world_viewport() * 0.5 + 3.0).as_ivec2(); + let rounded_ghost_pos = IVec2 { + x: state.ghost.overworld_pos.x.round() as _, + y: state.ghost.overworld_pos.y.round() as _ + }; + state.overworld.get_or_generate_tile( + rounded_ghost_pos + IVec2::new(half_viewport.x, half_viewport.y) + ); + state.overworld.get_or_generate_tile( + rounded_ghost_pos + IVec2::new(half_viewport.x, -half_viewport.y) + ); + state.overworld.get_or_generate_tile( + rounded_ghost_pos + IVec2::new(-half_viewport.x, half_viewport.y) + ); + state.overworld.get_or_generate_tile( + rounded_ghost_pos + IVec2::new(-half_viewport.x, -half_viewport.y) + ); + } } diff --git a/src/activities/overworld/worldgen.rs b/src/activities/overworld/worldgen.rs index 5af1dcd..83e9067 100644 --- a/src/activities/overworld/worldgen.rs +++ b/src/activities/overworld/worldgen.rs @@ -2,8 +2,7 @@ #![allow(dead_code)] use crate::assets::ASSETS; -use comfy::{IVec2, TextureHandle, UVec2}; -use log::info; +use comfy::{info, IVec2, TextureHandle, UVec2}; use std::collections::HashMap; pub enum MovementCost { @@ -117,28 +116,61 @@ impl Tile { } pub fn can_stand_inside(&self) -> bool { - unimplemented!() + #[allow(clippy::match_like_matches_macro)] // I believe this is better readable + match self { + Self::House { door: false, .. } => false, + _ => true + } } pub fn movement_cost_left(&self) -> MovementCost { - unimplemented!() + match self { + Self::Grass => MovementCost::Default, + Self::Path { left: true, .. } => MovementCost::Path, + Self::Path { left: false, .. } => MovementCost::Default, + Self::Fence { left: false, .. } => MovementCost::Obstacle, + _ => MovementCost::Infinite + } } pub fn movement_cost_right(&self) -> MovementCost { - unimplemented!() + match self { + Self::Grass => MovementCost::Default, + Self::Path { right: true, .. } => MovementCost::Path, + Self::Path { right: false, .. } => MovementCost::Default, + Self::Fence { right: false, .. } => MovementCost::Obstacle, + _ => MovementCost::Infinite + } } pub fn movement_cost_up(&self) -> MovementCost { - unimplemented!() + match self { + Self::Grass => MovementCost::Default, + Self::Path { top: true, .. } => MovementCost::Path, + Self::Path { top: false, .. } => MovementCost::Default, + Self::Fence { top: false, .. } => MovementCost::Obstacle, + _ => MovementCost::Infinite + } } pub fn movement_cost_down(&self) -> MovementCost { - unimplemented!() + match self { + Self::Grass => MovementCost::Default, + Self::Path { bottom: true, .. } => MovementCost::Path, + Self::Path { bottom: false, .. } => MovementCost::Default, + Self::Fence { bottom: false, .. } => MovementCost::Obstacle, + Self::House { door: true, .. } => MovementCost::Path, + _ => MovementCost::Infinite + } } pub fn can_enter_house(&self) -> bool { - unimplemented!() + #[allow(clippy::match_like_matches_macro)] // I believe this is better readable + match self { + Self::House { door: true, .. } => true, + _ => false + } } } /// The size of a chunk (both width and height). This value squared gives the amount of /// tiles in the chunk. -const CHUNK_SIZE: u32 = 100; +const CHUNK_SIZE: u32 = 50; /// Chunks #[derive(Debug)] @@ -286,7 +318,10 @@ impl Chunk { fence_vert, grass, house(ASSETS.overworld.house_bottom_left), - house(ASSETS.overworld.house_bottom_door), + Tile::House { + door: true, + texture: ASSETS.overworld.house_bottom_door + }, house(ASSETS.overworld.house_bottom_window), house(ASSETS.overworld.house_bottom_window), house(ASSETS.overworld.house_bottom_right), @@ -403,7 +438,15 @@ fn world_to_chunk_and_local_coords(world_coords: IVec2) -> (IVec2, UVec2) { } impl Overworld { - fn get_tile(&self, world_coords: IVec2) -> Option<&Tile> { + /// Return a [`Tile`] at the given world coordinates, or `None` if that tile has not + /// been generated yet. Uses engine/world cordinates. + pub fn get_tile(&self, world_coords: IVec2) -> Option<&Tile> { + let mut coords = world_coords; + coords.y *= -1; + self.get_tile_private(coords) + } + + fn get_tile_private(&self, world_coords: IVec2) -> Option<&Tile> { let (chunk_coords, local_chunk_coords) = world_to_chunk_and_local_coords(world_coords); @@ -411,15 +454,15 @@ impl Overworld { chunk.get_tile(local_chunk_coords) } - /// Return a [`Tile`] at the given world coordinates, or `None` if that tile has not - /// been generated yet. use engine/world cordinates. + /// Return a [`Tile`] at the given world coordinates. Generates tiles if necessary. + /// Uses engine/world cordinates. pub fn get_or_generate_tile(&mut self, world_coords: IVec2) -> &Tile { let mut coords = world_coords; coords.y *= -1; - self.get_or_generate_tiles_private(coords) + self.get_or_generate_tile_private(coords) } - fn get_or_generate_tiles_private(&mut self, world_coords: IVec2) -> &Tile { + fn get_or_generate_tile_private(&mut self, world_coords: IVec2) -> &Tile { let (chunk_coords, local_chunk_coords) = world_to_chunk_and_local_coords(world_coords); @@ -430,21 +473,21 @@ impl Overworld { chunk.get_tile(local_chunk_coords).unwrap() } - /// Iterate over all generated tiles and its engine/world cordinates. using a [`Tile`] at the given world coordinates, or `None` if that tile has not - /// been generated yet. + /// Iterate over all generated tiles in all generated chunks and their engine/world + /// cordinates. pub fn iter_tiles(&self) -> impl Iterator { - self.iter_tilese_private().map(|(coords, tile)| { + self.iter_tiles_private().map(|(coords, tile)| { let mut w_coords = coords; w_coords.y *= -1; (w_coords, tile) }) } - /// iterate over all tiles and its global coords - fn iter_tilese_private(&self) -> impl Iterator { + /// Iterate over all generated tiles in all generated chunks. + fn iter_tiles_private(&self) -> impl Iterator { self.chunks.iter().flat_map(|(chunk_coords, chunk)| { chunk.iter_tiles().map(|(local_coords, tile)| { - // never fail because chunksize fits alswas into i32 + // never fail because chunksize fits always into i32 let local_coords: IVec2 = local_coords.try_into().unwrap(); (local_coords + (*chunk_coords * CHUNK_SIZE as i32), tile) }) diff --git a/src/game.rs b/src/game.rs index 1a638c1..e84c08b 100644 --- a/src/game.rs +++ b/src/game.rs @@ -3,22 +3,64 @@ use crate::{ assets::Assets, State }; -use comfy::EngineContext; -use std::ops::Sub; +use comfy::{EngineContext, Vec2}; +use std::{ops::Sub, time::Instant}; #[derive(Debug)] pub struct Ghost { - /// current electric charge of the Ghost + /// Current electric charge of the Ghost. pub charge: f32, - /// max electric charge of the Ghost - pub max_charge: f32 + /// Max electric charge of the Ghost. + pub max_charge: f32, + + /// The position of the ghost in the overworld. Expressed in tile coordinates, but + /// as a float as a ghost takes more than one tick to move. + pub overworld_pos: Vec2, + /// Pending movement of the ghost in the overworld. + pub overworld_movement_pending: Vec2, + /// The current movement speed of the ghost in tiles/sec. + pub overworld_movement_speed: f32, + /// The timestamp of the last overworld position update. + pub overworld_pos_last_update: Instant +} + +impl Ghost { + pub fn update_overworld_pos(&mut self, now: Instant) { + // This calculation is extremely simplistic. It will not work properly if both + // x and y of movement_pending are non-zero. But we only move left,right,up,down + // so that should never happen! + let secs = now + .duration_since(self.overworld_pos_last_update) + .as_secs_f32(); + let mut movement = self.overworld_movement_pending.signum() + * self.overworld_movement_speed + * secs; + + // limit the movement to the remaining movement + if self.overworld_movement_pending.x.abs() < movement.x.abs() { + movement.x = self.overworld_movement_pending.x; + } + if self.overworld_movement_pending.y.abs() < movement.y.abs() { + movement.y = self.overworld_movement_pending.y; + } + + // execute the movement + self.overworld_pos += movement; + self.overworld_movement_pending -= movement; + self.overworld_pos_last_update = now; + } } impl Default for Ghost { fn default() -> Self { Self { charge: 1000.0, - max_charge: 1000.0 + max_charge: 1000.0, + + overworld_pos: Vec2::ZERO, + overworld_movement_pending: Vec2::ZERO, + overworld_movement_speed: 0.0, + overworld_pos_last_update: Instant::now() } } } @@ -51,15 +93,16 @@ pub fn setup(state: &mut State, ctx: &mut EngineContext<'_>) { } pub fn update(state: &mut State, engine: &mut EngineContext<'_>) { + state.score += engine.delta * 10.0; match state.activity { - Activity::House => house::update(state, engine), + Activity::House(_) => house::update(state, engine), Activity::Overworld => overworld::update(state, engine) } } pub fn draw(state: &State, engine: &EngineContext<'_>) { match state.activity { - Activity::House => house::draw(state, engine), + Activity::House(_) => house::draw(state, engine), Activity::Overworld => overworld::draw(state, engine) } crate::ui::draw(state, engine); diff --git a/src/main.rs b/src/main.rs index 0ecf53c..d05f0e5 100644 --- a/src/main.rs +++ b/src/main.rs @@ -16,7 +16,7 @@ use self::{ }; use comfy::{ init_game_config, pollster, run_comfy_main_async, EngineContext, EngineState, - GameConfig, GameLoop + GameConfig, GameLoop, HashMap, IVec2 }; const GAME_NAME: &str = "Powercreep"; @@ -27,7 +27,27 @@ struct State { activity: Activity, ghost: Ghost, overworld: Overworld, - house: Option + houses: HashMap, + score: f32 +} + +impl State { + fn get_house_pos(&self) -> Option { + match self.activity { + Activity::House(pos) => Some(pos), + _ => None + } + } + + fn house(&self) -> Option<&HouseState> { + self.houses.get(&self.get_house_pos().unwrap()) + } + + fn house_mut(&mut self) -> &mut HouseState { + self.houses + .entry(self.get_house_pos().unwrap()) + .or_insert_with(HouseState::default) + } } impl GameLoop for State { diff --git a/src/ui.rs b/src/ui.rs index 7de61ee..9d434b2 100644 --- a/src/ui.rs +++ b/src/ui.rs @@ -1,10 +1,11 @@ use crate::State; use comfy::{ - draw_rect, draw_rect_outline, screen_height, screen_to_world, screen_width, - EngineContext, Vec2, BLUE, RED + draw_rect, draw_rect_outline, egui, screen_height, screen_to_world, screen_width, + EngineContext, Vec2, BLUE, RED, WHITE }; +use egui::widget_text::RichText; -pub fn draw(state: &State, _engine: &EngineContext<'_>) { +pub fn draw_batterie(state: &State, _engine: &EngineContext<'_>) { // seperate fill state into smaller section for better readability let section_count = 5; let mut start_positon = screen_to_world(Vec2::new(screen_width(), screen_height())); @@ -29,3 +30,22 @@ pub fn draw(state: &State, _engine: &EngineContext<'_>) { draw_rect_outline(position, section_size, 0.1, RED, 100); } } + +pub fn draw_highscore(state: &State, _engine: &EngineContext<'_>) { + egui::Area::new("score") + .anchor(egui::Align2::RIGHT_TOP, egui::vec2(0.0, 0.0)) + .show(egui(), |ui| { + ui.label( + RichText::new(format!("{:.0}", state.score)) + .color(WHITE) + .monospace() + .size(16.0) + .strong() + ); + }); +} + +pub fn draw(state: &State, engine: &EngineContext<'_>) { + draw_batterie(state, engine); + draw_highscore(state, engine); +}