diff --git a/Cargo.lock b/Cargo.lock index c04da23..9637b90 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -149,6 +149,7 @@ dependencies = [ "bevy_egui", "bevy_kira_audio", "bevy_rapier3d", + "rand 0.9.0", ] [[package]] @@ -978,7 +979,7 @@ dependencies = [ "derive_more", "glam", "itertools 0.13.0", - "rand", + "rand 0.8.5", "rand_distr", "serde", "smallvec", @@ -2543,7 +2544,7 @@ checksum = "8babf46d4c1c9d92deac9f7be466f76dfc4482b6452fc5024b5e8daf6ffeb3ee" dependencies = [ "bytemuck", "mint", - "rand", + "rand 0.8.5", "serde", ] @@ -4263,8 +4264,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", - "rand_chacha", - "rand_core", + "rand_chacha 0.3.1", + "rand_core 0.6.4", +] + +[[package]] +name = "rand" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3779b94aeb87e8bd4e834cee3650289ee9e0d5677f976ecdb6d219e5f4f6cd94" +dependencies = [ + "rand_chacha 0.9.0", + "rand_core 0.9.3", + "zerocopy 0.8.24", ] [[package]] @@ -4274,7 +4286,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" dependencies = [ "ppv-lite86", - "rand_core", + "rand_core 0.6.4", +] + +[[package]] +name = "rand_chacha" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" +dependencies = [ + "ppv-lite86", + "rand_core 0.9.3", ] [[package]] @@ -4286,6 +4308,15 @@ dependencies = [ "getrandom 0.2.15", ] +[[package]] +name = "rand_core" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" +dependencies = [ + "getrandom 0.3.2", +] + [[package]] name = "rand_distr" version = "0.4.3" @@ -4293,7 +4324,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32cb0b9bc82b0a0876c2dd994a7e7a2683d3e7390ca40e6886785ef0c7e3ee31" dependencies = [ "num-traits", - "rand", + "rand 0.8.5", ] [[package]] @@ -4358,8 +4389,8 @@ dependencies = [ "once_cell", "paste", "profiling", - "rand", - "rand_chacha", + "rand 0.8.5", + "rand_chacha 0.3.1", "simd_helpers", "system-deps", "thiserror 1.0.69", @@ -5427,7 +5458,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b3758f5e68192bb96cc8f9b7e2c2cfdabb435499a28499a42f8f984092adad4b" dependencies = [ "getrandom 0.2.15", - "rand", + "rand 0.8.5", "serde", ] diff --git a/Cargo.toml b/Cargo.toml index 37bea78..9cae002 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,3 +9,4 @@ bevy_asset_loader = { version ="0.22.0", features = ["standard_dynamic_assets"] bevy_egui = "0.33.0" bevy_kira_audio = "0.22.0" bevy_rapier3d = "0.29.0" +rand = "0.9.0" diff --git a/assets/images/pixelart/Flashlight_click_0.png b/assets/images/pixelart/Flashlight_click_0.png index 0519c7e..6adc5ab 100644 Binary files a/assets/images/pixelart/Flashlight_click_0.png and b/assets/images/pixelart/Flashlight_click_0.png differ diff --git a/assets/images/pixelart/Flashlight_click_1.png b/assets/images/pixelart/Flashlight_click_1.png index 8810341..7d36ce0 100644 Binary files a/assets/images/pixelart/Flashlight_click_1.png and b/assets/images/pixelart/Flashlight_click_1.png differ diff --git a/assets/images/pixelart/Flashlight_click_2.png b/assets/images/pixelart/Flashlight_click_2.png index 26adff5..ff24d96 100644 Binary files a/assets/images/pixelart/Flashlight_click_2.png and b/assets/images/pixelart/Flashlight_click_2.png differ diff --git a/assets/images/pixelart/Flashlight_click_3.png b/assets/images/pixelart/Flashlight_click_3.png index 7945d8f..fd07b72 100644 Binary files a/assets/images/pixelart/Flashlight_click_3.png and b/assets/images/pixelart/Flashlight_click_3.png differ diff --git a/assets/images/pixelart/Flashlight_click_4.png b/assets/images/pixelart/Flashlight_click_4.png index bd824d9..d13a42d 100644 Binary files a/assets/images/pixelart/Flashlight_click_4.png and b/assets/images/pixelart/Flashlight_click_4.png differ diff --git a/assets/images/pixelart/Flashlight_hold_0.png b/assets/images/pixelart/Flashlight_hold_0.png index d8d846d..456a929 100644 Binary files a/assets/images/pixelart/Flashlight_hold_0.png and b/assets/images/pixelart/Flashlight_hold_0.png differ diff --git a/assets/images/pixelart/Flashlight_hold_1.png b/assets/images/pixelart/Flashlight_hold_1.png index a299321..31a6d28 100644 Binary files a/assets/images/pixelart/Flashlight_hold_1.png and b/assets/images/pixelart/Flashlight_hold_1.png differ diff --git a/assets/images/pixelart/Flashlight_hold_2.png b/assets/images/pixelart/Flashlight_hold_2.png index c177578..f61389f 100644 Binary files a/assets/images/pixelart/Flashlight_hold_2.png and b/assets/images/pixelart/Flashlight_hold_2.png differ diff --git a/assets/images/pixelart/Flashlight_hold_3.png b/assets/images/pixelart/Flashlight_hold_3.png index 6c1ddd1..02c8549 100644 Binary files a/assets/images/pixelart/Flashlight_hold_3.png and b/assets/images/pixelart/Flashlight_hold_3.png differ diff --git a/assets/images/pixelart/Flashlight_hold_4.png b/assets/images/pixelart/Flashlight_hold_4.png index e3956a8..d3f5f31 100644 Binary files a/assets/images/pixelart/Flashlight_hold_4.png and b/assets/images/pixelart/Flashlight_hold_4.png differ diff --git a/src/interaction/objects.rs b/src/interaction/objects.rs index 32838db..705b479 100644 --- a/src/interaction/objects.rs +++ b/src/interaction/objects.rs @@ -1,3 +1,80 @@ use bevy::prelude::*; +use bevy_rapier3d::prelude::ColliderDisabled; + +use crate::{ + player::{Player, PlayerAction, toolbar::Item}, + util::single_mut, +}; + +use super::{Interact, ui::InteractionOpportunity}; pub fn plugin(_app: &mut App) {} + +pub fn handle_pick_up( + mut commands: Commands, + // current action + mut action: Query<(&PlayerAction, &mut Item), With>, + mut vis_query: Query<&mut Visibility>, + children: Query<&mut Children>, + + // current interactable + mut interaction_opportunity: ResMut, +) { + let (action, mut item) = single_mut!(action); + if *action == PlayerAction::PickUp { + // take out the interaction, because we are picking it up + let Some(target) = interaction_opportunity.0.take() else { + return; + }; + let replaced = item.set_item(target); + if let Ok(mut vis) = vis_query.get_mut(target) { + *vis = Visibility::Hidden; + } + if let Ok(colliders) = children.get(target) { + for &collider in colliders { + commands.entity(collider).insert(ColliderDisabled); + } + } + if let Some(dropped) = replaced { + if let Ok(mut vis) = vis_query.get_mut(dropped) { + *vis = Visibility::Visible; + } + if let Ok(colliders) = children.get(dropped) { + for &collider in colliders { + commands.entity(collider).remove::(); + } + } + } + } +} + +pub fn handle_drop( + mut commands: Commands, + // current action + mut action: Query<(&PlayerAction, &Transform, &mut Item), With>, + mut vis_query: Query<&mut Visibility>, + mut item_transform: Query<&mut Transform, With>, + children: Query<&mut Children>, +) { + // let (action, transform, mut item) = single_mut!(action); + // if *action == PlayerAction::Drop { + // if let Ok(mut vis) = vis_query.get_mut(target) { + // *vis = Visibility::Hidden; + // } + // if let Ok(colliders) = children.get(target) { + // for &collider in colliders { + // commands.entity(collider).insert(ColliderDisabled); + // } + // } + // if let Some(dropped) = replaced { + // if let Ok(mut vis) = vis_query.get_mut(dropped) { + // *vis = Visibility::Visible; + // } + // if let Ok(colliders) = children.get(dropped) { + // for &collider in colliders { + // commands.entity(collider).remove::(); + // } + // } + // } + // } +} diff --git a/src/interaction/ui.rs b/src/interaction/ui.rs index d9a8de4..e2ca24f 100644 --- a/src/interaction/ui.rs +++ b/src/interaction/ui.rs @@ -8,7 +8,7 @@ use bevy_rapier3d::prelude::*; use bevy_rapier3d::rapier::prelude::CollisionEventFlags; use std::iter; -use super::Interact; +use super::{Interact, objects}; pub(super) fn plugin(app: &mut App) { app.add_plugins(EguiPlugin) @@ -18,7 +18,7 @@ pub(super) fn plugin(app: &mut App) { ( update_interaction_opportunities, display_interaction_prompt, - handle_pick_up, + (objects::handle_pick_up, objects::handle_drop), ) .chain() .run_if(in_state(GameState::Playing)), @@ -26,7 +26,7 @@ pub(super) fn plugin(app: &mut App) { } #[derive(Debug, Clone, Eq, PartialEq, Resource, Default)] -struct InteractionOpportunity(Option); +pub struct InteractionOpportunity(pub Option); fn update_interaction_opportunities( mut collision_events: EventReader, @@ -81,6 +81,7 @@ fn display_interaction_prompt( .map(|name| name.as_str()) .expect("A named Interactable object"); + // objective or item egui::Window::new("Interaction") .collapsible(false) .title_bar(false) @@ -90,27 +91,3 @@ fn display_interaction_prompt( ui.label(format!("E: Pick Up {entity_name}")); }); } - -fn handle_pick_up( - // current action - mut action: Query<(&PlayerAction, &mut Item), With>, - mut item_query: Query<&mut Visibility, With>, - // current interactable - interaction_opportunity: Res, -) { - let Some(target) = interaction_opportunity.0 else { - return; - }; - let (action, mut item) = single_mut!(action); - if *action == PlayerAction::Interact { - let replaced = item.set_item(target); - if let Ok(mut vis) = item_query.get_mut(target) { - *vis = Visibility::Hidden; - } - if let Some(dropped) = replaced { - if let Ok(mut vis) = item_query.get_mut(dropped) { - *vis = Visibility::Visible; - } - } - } -} diff --git a/src/level_instantiation/mod.rs b/src/level_instantiation/mod.rs index 609a7d6..98f5448 100644 --- a/src/level_instantiation/mod.rs +++ b/src/level_instantiation/mod.rs @@ -1,5 +1,8 @@ -use bevy::{image, prelude::*, reflect::DynamicTypePath}; +use std::collections::HashMap; + +use bevy::prelude::*; use bevy_rapier3d::prelude::*; +use rand::Rng; use crate::{ GameState, @@ -28,29 +31,45 @@ fn spawn_level(mut commands: Commands, models: Res>, gltf_assets: R let shapes = mesh_names.map(|mesh_name| { let collider: Vec<(Collider, Transform)> = match mesh_name { "corner_inside" => vec![( - Collider::cuboid(1.0, 0.1, 1.0), - Transform::from_xyz(0.0, 0.0, 0.0), - )], - "corner_outside" => vec![( - Collider::cuboid(1.0, 0.1, 1.0), - Transform::from_xyz(0.0, 0.0, 0.0), + Collider::cuboid(0.2, 1.0, 0.2), + Transform::from_xyz(1.0, 1.0, 1.0) + .with_rotation(Quat::from_rotation_y(45.0_f32.to_radians())), )], + "corner_outside" => vec![ + ( + Collider::cuboid(1.0, 1.0, 0.1), + Transform::from_xyz(0.0, 1.0, -1.0), + ), + ( + Collider::cuboid(1.0, 1.0, 0.1), + Transform::from_xyz(-1.0, 1.0, 0.0) + .with_rotation(Quat::from_rotation_y(90.0_f32.to_radians())), + ), + ], "wall" => vec![( Collider::cuboid(1.0, 1.0, 0.1), - Transform::from_xyz(0.0, 0.5, -1.0), + Transform::from_xyz(0.0, 1.0, -1.0), )], "door" => vec![( - Collider::cuboid(1.0, 0.1, 1.0), - Transform::from_xyz(0.0, 0.0, 0.0), + Collider::cuboid(1.0, 1.0, 0.1), + Transform::from_xyz(0.0, 1.0, -1.0), )], "round_door" => vec![( - Collider::cuboid(1.0, 0.1, 1.0), - Transform::from_xyz(0.0, 0.0, 0.0), - )], - "round_hole" => vec![( - Collider::cuboid(1.0, 0.1, 1.0), - Transform::from_xyz(0.0, 0.0, 0.0), + Collider::cuboid(1.0, 1.0, 0.1), + Transform::from_xyz(0.0, 1.0, -1.0), )], + "round_hole" => vec![ + ( + Collider::cuboid(0.2, 1.0, 0.2), + Transform::from_xyz(1.0, 1.0, -1.0) + .with_rotation(Quat::from_rotation_y(45.0_f32.to_radians())), + ), + ( + Collider::cuboid(0.2, 1.0, 0.2), + Transform::from_xyz(-1.0, 1.0, -1.0) + .with_rotation(Quat::from_rotation_y(45.0_f32.to_radians())), + ), + ], _ => vec![( Collider::cuboid(1.0, 0.1, 1.0), Transform::from_xyz(0.0, 0.0, 0.0), @@ -78,31 +97,7 @@ fn spawn_level(mut commands: Commands, models: Res>, gltf_assets: R door, round_door, round_hole, - ] = shapes; - for i in 0..30 { - commands - .spawn(( - wall.0.clone(), - Transform::from_xyz(i as f32 * 2.0, 0.0, 0.0), - )) - .with_children(|parent| { - for ele in wall.1.clone() { - parent.spawn((RigidBody::Fixed, ele.0, ele.1)); - } - }); - - commands - .spawn(( - wall.0.clone(), - Transform::from_xyz(i as f32 * 2.0, 0.0, 0.0) - .with_rotation(Quat::from_rotation_y(std::f32::consts::PI)), - )) - .with_children(|parent| { - for ele in wall.1.clone() { - parent.spawn((RigidBody::Fixed, ele.0, ele.1)); - } - }); - } + ] = shapes.clone(); // huge floor commands.spawn(( @@ -110,11 +105,422 @@ fn spawn_level(mut commands: Commands, models: Res>, gltf_assets: R Collider::cuboid(1000.0, 0.1, 1000.0), Transform::from_xyz(-500.0, 0.0, -500.0), )); - commands.spawn(( - RigidBody::Fixed, - Collider::cuboid(1000.0, 0.1, 1000.0), - Transform::from_xyz(-500.0, 3.0, -500.0), - )); + // huge roof + // commands.spawn(( + // RigidBody::Fixed, + // Collider::cuboid(1000.0, 0.1, 1000.0), + // Transform::from_xyz(-500.0, 3.0, -500.0), + // )); + // let map = GameMap::test(); + let map = GameMap::new(100); + map.print_map(); + + for ((x, z), node) in map.nodes.into_iter() { + let values = { + // corners are handled later, for now just a wall to test + let node = node.clone(); + let pos = Transform::from_xyz(2.0 * x as f32, 0.0, -2.0 * z as f32); + + use Side::{Closed, Connection}; + match (node.north, node.east, node.south, node.west) { + // hallway horizontal + (Closed, Connection, Closed, Connection) => { + vec![ + (wall.clone(), pos), + ( + wall.clone(), + pos.with_rotation(Quat::from_rotation_y(180.0_f32.to_radians())), + ), + ] + } + // hallway vertical + (Connection, Closed, Connection, Closed) => { + vec![ + ( + wall.clone(), + pos.with_rotation(Quat::from_rotation_y(90.0_f32.to_radians())), + ), + ( + wall.clone(), + pos.with_rotation(Quat::from_rotation_y(270.0_f32.to_radians())), + ), + ] + } + // dead ends + (Connection, Closed, Closed, Closed) => { + vec![ + ( + wall.clone(), + pos.with_rotation(Quat::from_rotation_y(90.0_f32.to_radians())), + ), + ( + round_door.clone(), + pos.with_rotation(Quat::from_rotation_y(180.0_f32.to_radians())), + ), + ( + wall.clone(), + pos.with_rotation(Quat::from_rotation_y(270.0_f32.to_radians())), + ), + ] + } + (Closed, Closed, Connection, Closed) => { + vec![ + ( + wall.clone(), + pos.with_rotation(Quat::from_rotation_y(90.0_f32.to_radians())), + ), + ( + round_door.clone(), + pos.with_rotation(Quat::from_rotation_y(0.0_f32.to_radians())), + ), + ( + wall.clone(), + pos.with_rotation(Quat::from_rotation_y(270.0_f32.to_radians())), + ), + ] + } + (Closed, Connection, Closed, Closed) => { + vec![ + (wall.clone(), pos), + ( + round_door.clone(), + pos.with_rotation(Quat::from_rotation_y(90.0_f32.to_radians())), + ), + ( + wall.clone(), + pos.with_rotation(Quat::from_rotation_y(180.0_f32.to_radians())), + ), + ] + } + (Closed, Closed, Closed, Connection) => { + vec![ + (wall.clone(), pos), + ( + round_door.clone(), + pos.with_rotation(Quat::from_rotation_y(270.0_f32.to_radians())), + ), + ( + wall.clone(), + pos.with_rotation(Quat::from_rotation_y(180.0_f32.to_radians())), + ), + ] + } + // T hallways + (Closed, Connection, Connection, Connection) => { + vec![ + (wall.clone(), pos), + ( + round_hole.clone(), + pos.with_rotation(Quat::from_rotation_y(180.0_f32.to_radians())), + ), + ] + } + (Connection, Closed, Connection, Connection) => { + vec![ + ( + round_hole.clone(), + pos.with_rotation(Quat::from_rotation_y(90.0_f32.to_radians())), + ), + ( + wall.clone(), + pos.with_rotation(Quat::from_rotation_y(270.0_f32.to_radians())), + ), + ] + } + (Connection, Connection, Closed, Connection) => { + vec![ + (round_hole.clone(), pos), + ( + wall.clone(), + pos.with_rotation(Quat::from_rotation_y(180.0_f32.to_radians())), + ), + ] + } + (Connection, Connection, Connection, Closed) => { + vec![ + ( + wall.clone(), + pos.with_rotation(Quat::from_rotation_y(90.0_f32.to_radians())), + ), + ( + round_hole.clone(), + pos.with_rotation(Quat::from_rotation_y(270.0_f32.to_radians())), + ), + ] + } + // fourway + (Connection, Connection, Connection, Connection) => { + vec![ + ( + corner_inside.clone(), + pos.with_rotation(Quat::from_rotation_y(0.0_f32.to_radians())), + ), + ( + corner_inside.clone(), + pos.with_rotation(Quat::from_rotation_y(90.0_f32.to_radians())), + ), + ( + corner_inside.clone(), + pos.with_rotation(Quat::from_rotation_y(180.0_f32.to_radians())), + ), + ( + corner_inside.clone(), + pos.with_rotation(Quat::from_rotation_y(270.0_f32.to_radians())), + ), + ] + } + // corners + (Connection, Connection, Closed, Closed) => { + vec![ + ( + corner_outside.clone(), + pos.with_rotation(Quat::from_rotation_y(90.0_f32.to_radians())), + ), + ( + corner_inside.clone(), + pos.with_rotation(Quat::from_rotation_y(90.0_f32.to_radians())), + ), + ] + } + (Closed, Connection, Connection, Closed) => { + vec![ + ( + corner_outside.clone(), + pos.with_rotation(Quat::from_rotation_y(0.0_f32.to_radians())), + ), + ( + corner_inside.clone(), + pos.with_rotation(Quat::from_rotation_y(0.0_f32.to_radians())), + ), + ] + } + (Closed, Closed, Connection, Connection) => { + vec![ + ( + corner_outside.clone(), + pos.with_rotation(Quat::from_rotation_y(270.0_f32.to_radians())), + ), + ( + corner_inside.clone(), + pos.with_rotation(Quat::from_rotation_y(270.0_f32.to_radians())), + ), + ] + } + (Connection, Closed, Closed, Connection) => { + vec![ + ( + corner_outside.clone(), + pos.with_rotation(Quat::from_rotation_y(180.0_f32.to_radians())), + ), + ( + corner_inside.clone(), + pos.with_rotation(Quat::from_rotation_y(180.0_f32.to_radians())), + ), + ] + } + _ => vec![], + } + }; + + for ((scene_root, colliders), pos) in values { + commands + .spawn((RigidBody::Fixed, scene_root, pos)) + .with_children(|parent| { + for (collider, transform) in colliders { + parent.spawn((collider, transform)); + } + }); + } + } +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +enum Side { + Empty, + Connection, + Closed, +} + +#[derive(Clone, Debug)] +struct MapNode { + north: Side, + south: Side, + east: Side, + west: Side, + collapsed: bool, +} + +impl MapNode { + fn new() -> Self { + MapNode { + north: Side::Empty, + south: Side::Empty, + east: Side::Empty, + west: Side::Empty, + collapsed: false, + } + } +} + +struct GameMap { + nodes: HashMap<(i32, i32), MapNode>, + max_nodes: i32, +} + +impl GameMap { + fn new(max_nodes: i32) -> Self { + let mut nodes = HashMap::new(); + let mut start_node = MapNode::new(); + start_node.north = Side::Connection; + start_node.south = Side::Connection; + start_node.east = Side::Connection; + start_node.west = Side::Connection; + nodes.insert((0, 0), start_node); + let mut m = GameMap { nodes, max_nodes }; + m.generate_map(); + m + } + + fn test() -> Self { + let mut nodes = HashMap::new(); + + let mut wall_node0 = MapNode::new(); + wall_node0.north = Side::Connection; + wall_node0.south = Side::Closed; + wall_node0.east = Side::Closed; + wall_node0.west = Side::Closed; + nodes.insert((0, -1), wall_node0); + + let mut wall_node1 = MapNode::new(); + wall_node1.north = Side::Connection; + wall_node1.south = Side::Connection; + wall_node1.east = Side::Connection; + wall_node1.west = Side::Closed; + nodes.insert((0, 0), wall_node1); + + let mut wall_node2 = MapNode::new(); + wall_node2.north = Side::Connection; + wall_node2.south = Side::Connection; + wall_node2.east = Side::Closed; + wall_node2.west = Side::Connection; + nodes.insert((0, 1), wall_node2); + + let mut corner_node = MapNode::new(); + corner_node.south = Side::Connection; + corner_node.east = Side::Connection; + corner_node.north = Side::Closed; + corner_node.west = Side::Closed; + nodes.insert((0, 2), corner_node); + + let mut wall_node3 = MapNode::new(); + wall_node3.west = Side::Connection; + wall_node3.east = Side::Connection; + wall_node3.north = Side::Closed; + wall_node3.south = Side::Connection; + nodes.insert((1, 2), wall_node3); + + let mut wall_node4 = MapNode::new(); + wall_node4.west = Side::Connection; + wall_node4.east = Side::Connection; + wall_node4.north = Side::Connection; + wall_node4.south = Side::Closed; + nodes.insert((2, 2), wall_node4); + + let mut wall_node5 = MapNode::new(); + wall_node5.west = Side::Connection; + wall_node5.east = Side::Closed; + wall_node5.north = Side::Closed; + wall_node5.south = Side::Connection; + nodes.insert((3, 2), wall_node5); + + GameMap { + nodes, + max_nodes: 7, + } + } + + fn generate_map(&mut self) { + self.create_node(&(0, 1)); // North + // self.create_node(&(0, -1)); // South + // self.create_node(&(1, 0)); // East + // self.create_node(&(-1, 0)); // West + } + + fn choose_side(&self) -> Side { + if self.nodes.len() > self.max_nodes as usize { + Side::Closed + } else { + if rand::rng().random_bool(0.5) { + Side::Connection + } else { + Side::Closed + } + } + } + + fn create_node(&mut self, idx: &(i32, i32)) { + let mut nodes_to_process = vec![*idx]; + let mut nodes_created = 0; + + while let Some(current_idx) = nodes_to_process.pop() { + if self.nodes.contains_key(¤t_idx) { + continue; + } + + let (x, y) = current_idx; + let mut new_node = MapNode::new(); + + let north = self.nodes.get(&(x, y + 1)); + let south = self.nodes.get(&(x, y - 1)); + let east = self.nodes.get(&(x + 1, y)); + let west = self.nodes.get(&(x - 1, y)); + + new_node.north = north.map_or_else(|| self.choose_side(), |n| n.south); + new_node.south = south.map_or_else(|| self.choose_side(), |s| s.north); + new_node.east = east.map_or_else(|| self.choose_side(), |e| e.west); + new_node.west = west.map_or_else(|| self.choose_side(), |w| w.east); + + if new_node.north == Side::Connection && !self.nodes.contains_key(&(x, y + 1)) { + nodes_to_process.push((x, y + 1)); + } + if new_node.south == Side::Connection && !self.nodes.contains_key(&(x, y - 1)) { + nodes_to_process.push((x, y - 1)); + } + if new_node.east == Side::Connection && !self.nodes.contains_key(&(x + 1, y)) { + nodes_to_process.push((x + 1, y)); + } + if new_node.west == Side::Connection && !self.nodes.contains_key(&(x - 1, y)) { + nodes_to_process.push((x - 1, y)); + } + + self.nodes.insert(current_idx, new_node); + nodes_created += 1; + } + } + + fn print_map(&self) { + let mut min_x = 0; + let mut max_x = 0; + let mut min_y = 0; + let mut max_y = 0; + + for &(x, y) in self.nodes.keys() { + min_x = min_x.min(x); + max_x = max_x.max(x); + min_y = min_y.min(y); + max_y = max_y.max(y); + } + + for y in (min_y..=max_y).rev() { + for x in min_x..=max_x { + match self.nodes.get(&(x, y)) { + Some(node) => print!("[+]"), + None => print!(" "), + } + } + println!(); + } + } } fn spawn_objects( @@ -156,14 +562,13 @@ fn spawn_objects( Transform::from_xyz(0.0, 2.0, 2.0), Interact, RigidBody::Dynamic, - Name::new("Id Card"), + Name::new("Id Card 1"), Visibility::Visible, ItemIcon::new(image_assets.id_card.clone()), SceneRoot(asset.clone()), )) .with_children(|parent| { parent.spawn(( - Visibility::Inherited, ColliderMassProperties::Mass(10.0), Collider::cuboid(0.05, 0.05, 0.01), Transform::from_rotation(Quat::from_euler( @@ -174,7 +579,6 @@ fn spawn_objects( )), )); parent.spawn(( - Visibility::Inherited, ActiveEvents::COLLISION_EVENTS, Transform::default(), Collider::ball(0.5), // Interaction radius diff --git a/src/player.rs b/src/player.rs index f969cf2..4297c2c 100644 --- a/src/player.rs +++ b/src/player.rs @@ -1,13 +1,18 @@ - use bevy::{ - input::mouse::AccumulatedMouseMotion, prelude::*, render::view::RenderLayers, window::{PrimaryWindow, WindowResized} + input::mouse::AccumulatedMouseMotion, + prelude::*, + render::view::RenderLayers, + window::{PrimaryWindow, WindowResized}, }; use bevy_kira_audio::{Audio, AudioControl}; use bevy_rapier3d::prelude::*; pub mod toolbar; -use crate::{asset_loading::{AudioAssets, FlashlightAssets}, GameState}; +use crate::{ + GameState, + asset_loading::{AudioAssets, FlashlightAssets}, +}; #[derive(Debug, Component, Default)] pub struct Player { @@ -64,13 +69,12 @@ pub struct FlashlightButtonAnimation { impl Default for FlashlightButtonAnimation { fn default() -> Self { Self { - timer: Timer::from_seconds(0.20, TimerMode::Once), + timer: Timer::from_seconds(0.20, TimerMode::Once), is_pressed: false, } } } - pub fn plugin(app: &mut App) { app.add_plugins(toolbar::plugin) .add_systems(OnEnter(GameState::Playing), (init_player, hide_cursor)) @@ -78,12 +82,13 @@ pub fn plugin(app: &mut App) { Update, ( move_camera, - handle_input, - apply_head_bob, + handle_input, + apply_head_bob, on_resize_system, handle_flashlight, update_flashlight_button_animation, - ).run_if(in_state(GameState::Playing)), + ) + .run_if(in_state(GameState::Playing)), ) .add_systems( FixedUpdate, @@ -138,8 +143,6 @@ pub fn init_player( }, RenderLayers::layer(STATIC_LAYER), )); - - // pitslamp sprite let window = window.single(); let transform = flashlight_base_transform(window.width(), window.height()); parent.spawn(( @@ -149,18 +152,18 @@ pub fn init_player( RenderLayers::layer(STATIC_LAYER), FlashlightButtonAnimation::default(), )); - + // feitelijke pitslamp parent.spawn(( Flashlight, SpotLight { - intensity: 0.0, + intensity: 0.0, color: Color::WHITE, - range: 4.0, + range: 4.0, outer_angle: 30.0_f32.to_radians(), // wide cone for flashlight inner_angle: 10.0_f32.to_radians(), // narrower inner cone - shadows_enabled: false, // (set to true for realism) - radius: 0.35, // low value for hard light + shadows_enabled: false, // (set to true for realism) + radius: 0.35, // low value for hard light ..default() }, Transform::from_xyz(0.0, -0.15, 0.5), @@ -184,15 +187,17 @@ fn on_resize_system( fn flashlight_base_transform(window_width: f32, window_height: f32) -> BaseTransform { let window_size = Vec2::new(window_width, window_height); - let sprite_size = Vec2::new(101.0, 101.0); - let scale = window_width / 600.0; + let sprite_size = Vec2::new(404.0, 404.0); + let scale = window_width / 2400.0; let world_size = sprite_size * scale; let xoffset = window_size.x / 4.0 - 40.0; let yoffset = 15.0; - - let mut transform = Transform::from_translation( - Vec3::new(window_size.x / 2.0 - world_size.x / 2.0 - xoffset, -window_size.y / 2.0 + world_size.y / 2.0 - yoffset, 0.0) - ); + + let mut transform = Transform::from_translation(Vec3::new( + window_size.x / 2.0 - world_size.x / 2.0 - xoffset, + -window_size.y / 2.0 + world_size.y / 2.0 - yoffset, + 0.0, + )); transform.scale = Vec3::new(scale, scale, 1.0); return BaseTransform(transform); } @@ -231,8 +236,10 @@ pub(crate) enum PlayerAction { Move, Sprint, Jump, - Interact, - ToggleFlashlight + ToggleFlashlight, + // Objects and stuff + PickUp, + Drop, } pub fn handle_input( @@ -240,7 +247,7 @@ pub fn handle_input( mut query: Query<(&Transform, &mut PlayerInput, &mut PlayerAction, &mut Player), With>, ) { for (transform, mut input, mut action, mut player) in query.iter_mut() { - *action = PlayerAction::Move; + *action = PlayerAction::Move; let forward = transform.forward(); let right = transform.right(); @@ -267,10 +274,13 @@ pub fn handle_input( } else if keyboard_input.pressed(KeyCode::ControlLeft) { player.speed_factor = 0.65; } else { - player.speed_factor = 1.0; + player.speed_factor = 1.0; } if keyboard_input.just_pressed(KeyCode::KeyE) { - *action = PlayerAction::Interact + *action = PlayerAction::PickUp; + } + if keyboard_input.just_pressed(KeyCode::KeyQ) { + *action = PlayerAction::Drop; } if keyboard_input.just_pressed(KeyCode::KeyF) { *action = PlayerAction::ToggleFlashlight; @@ -280,7 +290,9 @@ pub fn handle_input( } } -pub fn apply_player_movement(mut player_query: Query<(&PlayerInput, &mut Velocity, &Player), With>) { +pub fn apply_player_movement( + mut player_query: Query<(&PlayerInput, &mut Velocity, &Player), With>, +) { const SPEED: f32 = 2.6; const JUMP_FORCE: f32 = 4.0; @@ -297,7 +309,7 @@ pub fn apply_player_movement(mut player_query: Query<(&PlayerInput, &mut Velocit if input.movement_direction.y > 0.0 { velocity.linvel.y = JUMP_FORCE; - } + } } } @@ -305,14 +317,18 @@ pub fn apply_head_bob( time: Res