From cb99170d6e410bdfb6ede4f6817e19881f2b0bd3 Mon Sep 17 00:00:00 2001 From: LorrensP-2158466 Date: Sun, 6 Apr 2025 20:23:51 +0200 Subject: [PATCH 1/3] drop --- src/interaction/objects.rs | 60 ++++++++++++++++++++------------------ src/interaction/ui.rs | 5 ++-- src/player/toolbar.rs | 6 ++++ 3 files changed, 39 insertions(+), 32 deletions(-) diff --git a/src/interaction/objects.rs b/src/interaction/objects.rs index 10d78c0..00bb787 100644 --- a/src/interaction/objects.rs +++ b/src/interaction/objects.rs @@ -13,14 +13,15 @@ pub fn plugin(_app: &mut App) {} pub fn handle_pick_up( mut commands: Commands, // current action - mut action: Query<(&PlayerAction, &mut Item), With>, + mut player_query: Query<(&PlayerAction, &Transform, &mut Item), With>, mut vis_query: Query<&mut Visibility>, children: Query<&mut Children>, + mut item_transform: Query<&mut Transform, (With, Without)>, // current interactable mut interaction_opportunity: ResMut, ) { - let (action, mut item) = single_mut!(action); + let (action, transform, mut item) = single_mut!(player_query); if *action == PlayerAction::PickUp { // take out the interaction, because we are picking it up let Some(target) = interaction_opportunity.0.take() else { @@ -44,36 +45,37 @@ pub fn handle_pick_up( commands.entity(collider).remove::(); } } + // for simplicities sake, set the transform of the item that is dropped to that of the player + let mut item_transform = item_transform.get_mut(dropped).unwrap(); + *item_transform = *transform; } } } -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>, +pub fn handle_drop( + mut commands: Commands, + // current action + mut player_query: Query<(&PlayerAction, &Transform, &mut Item), With>, + mut vis_query: Query<&mut Visibility>, + mut item_transform: Query<&mut Transform, (With, Without)>, + 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::(); - // } - // } - // } - // } + let (action, transform, mut item) = single_mut!(player_query); + if *action == PlayerAction::Drop { + let Some(item) = item.take() else { + return; + }; + if let Ok(mut vis) = vis_query.get_mut(item) { + *vis = Visibility::Visible; + } + if let Ok(colliders) = children.get(item) { + for &collider in colliders { + commands.entity(collider).remove::(); + } + } + + // for simplicities sake, set the transform of the item that is dropped to that of the player + let mut item_transform = item_transform.get_mut(item).unwrap(); + *item_transform = *transform; + } } diff --git a/src/interaction/ui.rs b/src/interaction/ui.rs index e2ca24f..dbf1731 100644 --- a/src/interaction/ui.rs +++ b/src/interaction/ui.rs @@ -1,7 +1,6 @@ use crate::GameState; -use crate::player::toolbar::Item; -use crate::player::{Player, PlayerAction}; -use crate::util::{single, single_mut}; +use crate::player::Player; +use crate::util::single; use bevy::{prelude::*, window::PrimaryWindow}; use bevy_egui::{EguiContexts, EguiPlugin, egui}; use bevy_rapier3d::prelude::*; diff --git a/src/player/toolbar.rs b/src/player/toolbar.rs index 78baad4..2934a14 100644 --- a/src/player/toolbar.rs +++ b/src/player/toolbar.rs @@ -9,6 +9,12 @@ use super::Player; #[derive(Component, Default, Debug)] pub struct Item(Option); +impl Item { + pub fn take(&mut self) -> Option { + self.0.take() + } +} + #[derive(Component, Default, Debug)] pub struct ItemIcon(Handle); From afa4c377290a6e709fb9e8f221ba1fd2fbdac915 Mon Sep 17 00:00:00 2001 From: LorrensP-2158466 Date: Sun, 6 Apr 2025 20:45:16 +0200 Subject: [PATCH 2/3] key cards --- src/level_instantiation/mod.rs | 409 +++++++++++++++++++++------------ 1 file changed, 256 insertions(+), 153 deletions(-) diff --git a/src/level_instantiation/mod.rs b/src/level_instantiation/mod.rs index 9012b09..777b8bf 100644 --- a/src/level_instantiation/mod.rs +++ b/src/level_instantiation/mod.rs @@ -2,7 +2,7 @@ use std::collections::HashMap; use bevy::prelude::*; use bevy_rapier3d::prelude::*; -use rand::Rng; +use rand::{Rng, seq::IteratorRandom}; use crate::{ GameState, @@ -18,13 +18,12 @@ pub fn map_plugin(app: &mut App) { ); } - fn spawn_level( mut commands: Commands, mut meshes: ResMut>, mut materials: ResMut>, models: Res>, - gltf_assets: Res + gltf_assets: Res, ) { println!("LIBRARY: {:?}", gltf_assets.library); let mesh_names = [ @@ -128,138 +127,228 @@ fn spawn_level( // 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::{Connection, Closed}; + 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()))) + ( + 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()))) + ( + 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()))) + ( + 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()))) + ( + 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()))) + ( + 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()))) + ( + 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()))) + ( + 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()))) + ( + 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()))) + ( + 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()))) + ( + 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()))) + ( + 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()))), + ( + 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())), + ), ] } - _ => vec![] + (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)); - } - }); + commands + .spawn((RigidBody::Fixed, scene_root, pos)) + .with_children(|parent| { + for (collider, transform) in colliders { + parent.spawn((collider, transform)); + } + }); } } - let (x,z) = level.end_node; + let (x, z) = level.end_node; commands.spawn(( Mesh3d(meshes.add(Cuboid::new(1.0, 20.0, 1.0))), MeshMaterial3d(materials.add(Color::srgb_u8(255, 0, 0))), - Transform::from_xyz(2.0*x as f32, 0.5, -2.0*z as f32), + Transform::from_xyz(2.0 * x as f32, 0.5, -2.0 * z as f32), )); } - commands.insert_resource(GameLevels {levels}); + commands.insert_resource(GameLevels { levels }); } - fn create_levels(n: i32) -> Vec { let mut maps = Vec::new(); let mut initial_node = LevelNode::new(); @@ -274,7 +363,7 @@ fn create_levels(n: i32) -> Vec { maps.push(map); - for _ in 0..n-1 { + for _ in 0..n - 1 { let map = maps.last().unwrap(); let mut pos = map.end_node.clone(); @@ -330,35 +419,40 @@ impl LevelNode { #[derive(Resource)] struct GameLevels { - pub levels: Vec + pub levels: Vec, } struct GameLevel { nodes: HashMap<(i32, i32), LevelNode>, end_node: (i32, i32), grid_size: i32, - initial_point: (i32, i32) + initial_point: (i32, i32), } impl GameLevel { fn new(initial_point: (i32, i32), node: LevelNode, grid_size: i32) -> Self { let mut nodes = HashMap::new(); nodes.insert(initial_point, node); - let mut m = GameLevel { initial_point, nodes, grid_size, end_node: initial_point}; + let mut m = GameLevel { + initial_point, + nodes, + grid_size, + end_node: initial_point, + }; m.generate_map(); m } fn generate_map(&mut self) { let mut first_point = self.initial_point.clone(); first_point.1 += 1; - self.create_node(first_point); // North + self.create_node(first_point); // North } fn pos_within_boundaries(&self, pos: (i32, i32)) -> bool { pos.0 > self.grid_size + self.initial_point.0 - || pos.1 > self.grid_size + self.initial_point.1 - || pos.0 < self.initial_point.0 - || pos.1 < self.initial_point.1 + || pos.1 > self.grid_size + self.initial_point.1 + || pos.0 < self.initial_point.0 + || pos.1 < self.initial_point.1 } fn choose_side(&self, pos: (i32, i32)) -> Side { @@ -374,22 +468,19 @@ impl GameLevel { } fn ensure_connection(&self, node: &mut LevelNode, (x, y): (i32, i32)) { - let am_connections = (node.north == Side::Connection) as u8 + - (node.south == Side::Connection) as u8 + - (node.east == Side::Connection) as u8 + - (node.west == Side::Connection) as u8; + let am_connections = (node.north == Side::Connection) as u8 + + (node.south == Side::Connection) as u8 + + (node.east == Side::Connection) as u8 + + (node.west == Side::Connection) as u8; if am_connections <= 2 { if node.north != Side::Connection && !self.nodes.contains_key(&(x, y + 1)) { node.north = Side::Connection - } - else if node.south != Side::Connection && !self.nodes.contains_key(&(x, y - 1)) { + } else if node.south != Side::Connection && !self.nodes.contains_key(&(x, y - 1)) { node.south = Side::Connection - } - else if node.east != Side::Connection && !self.nodes.contains_key(&(x + 1, y)) { + } else if node.east != Side::Connection && !self.nodes.contains_key(&(x + 1, y)) { node.east = Side::Connection - } - else if node.west != Side::Connection && !self.nodes.contains_key(&(x - 1, y)) { + } else if node.west != Side::Connection && !self.nodes.contains_key(&(x - 1, y)) { node.west = Side::Connection } } @@ -442,8 +533,7 @@ impl GameLevel { let end_node = self.nodes.get_mut(&self.end_node).unwrap(); if self.end_node.1 >= self.end_node.0 { end_node.north = Side::Connection; - } - else if self.end_node.0 >= self.end_node.1 { + } else if self.end_node.0 >= self.end_node.1 { end_node.east = Side::Connection; } } @@ -475,6 +565,7 @@ impl GameLevel { fn spawn_objects( mut commands: Commands, + levels: Res, models: Res>, gltf_assets: Res, image_assets: Res, @@ -483,86 +574,98 @@ fn spawn_objects( let card = models.get(&gltf_assets.card).unwrap(); let asset = card.default_scene.as_ref().unwrap(); - commands - .spawn(( - Transform::from_xyz(0.0, 2.0, 2.0), - Interact, - RigidBody::Dynamic, - Name::new("Id Card 1"), - Visibility::Visible, - ItemIcon::new(image_assets.id_card.clone()), - SceneRoot(asset.clone()), - )) - .with_children(|parent| { - parent.spawn(( - ColliderMassProperties::Mass(10.0), - Collider::cuboid(0.05, 0.05, 0.01), - Transform::from_rotation(Quat::from_euler( - EulerRot::XYZ, - -10.0f32.to_radians(), // X-axis rotation (tilt) - -5.0f32.to_radians(), // Y-axis rotation - 10.0f32.to_radians(), // Z-axis rotation - )), - )); - parent.spawn(( - ActiveEvents::COLLISION_EVENTS, - Transform::default(), - Collider::ball(0.5), // Interaction radius - Sensor, - )); - }); + for (i, level) in levels.levels.iter().enumerate() { + let begin_node = level.initial_point; + let end_node = level.end_node; + // take a random position that is not the beginning or end_node + let (x, z) = loop { + let positions = level.nodes.keys(); + let random_pos = positions.choose(&mut rand::rng()).unwrap().clone(); + if random_pos != begin_node && random_pos != end_node { + break random_pos; + } + }; + let transform = if x <= z { + Transform::from_xyz(2.0 * x as f32, 0.5, -2.0 * z as f32) + .with_rotation(Quat::from_rotation_y(90.0_f32.to_radians())) + } else { + Transform::from_xyz(2.0 * x as f32, 0.5, -2.0 * z as f32) + }; + commands + .spawn(( + transform, + Interact, + RigidBody::Dynamic, + Name::new(format!("Id Card {i}")), + Visibility::Visible, + ItemIcon::new(image_assets.id_card.clone()), + SceneRoot(asset.clone()), + )) + .with_children(|parent| { + parent.spawn(( + ColliderMassProperties::Mass(10.0), + Collider::cuboid(0.05, 0.05, 0.01), + Transform::from_rotation(Quat::from_euler( + EulerRot::XYZ, + -10.0f32.to_radians(), // X-axis rotation (tilt) + -5.0f32.to_radians(), // Y-axis rotation + 10.0f32.to_radians(), // Z-axis rotation + )), + )); + parent.spawn(( + ActiveEvents::COLLISION_EVENTS, + Transform::default(), + Collider::ball(0.5), // Interaction radius + Sensor, + )); + }); + } } - fn spawn_doors( mut commands: Commands, levels: Res, models: Res>, - gltf_assets: Res -){ + gltf_assets: Res, +) { let collider: Vec<(Collider, Transform)> = vec![( Collider::cuboid(1.0, 1.0, 0.1), Transform::from_xyz(0.0, 1.0, -1.0), )]; - let path = format!("meshes/library/space_round_door.glb", ); - let handle = gltf_assets - .library - .get(&path) - .unwrap(); - let gltf = models - .get(handle) - .unwrap(); + let path = format!("meshes/library/space_round_door.glb",); + let handle = gltf_assets.library.get(&path).unwrap(); + let gltf = models.get(handle).unwrap(); - let asset = gltf - .default_scene - .as_ref() - .unwrap(); + let asset = gltf.default_scene.as_ref().unwrap(); let scene_root = SceneRoot(asset.clone()); - for level in levels.levels.iter() { let (x, z) = level.end_node; if x <= z { - commands.spawn(( - RigidBody::Fixed, - Transform::from_xyz(2.0 * x as f32, 0.0, -2.0 * z as f32) - .with_rotation(Quat::from_rotation_y(90.0_f32.to_radians())), - scene_root.clone(), - )).with_children(|parent| { - for (collider, transform) in collider.clone() { - parent.spawn((collider, transform)); - } - }); + commands + .spawn(( + RigidBody::Fixed, + Transform::from_xyz(2.0 * x as f32, 0.0, -2.0 * z as f32) + .with_rotation(Quat::from_rotation_y(90.0_f32.to_radians())), + scene_root.clone(), + )) + .with_children(|parent| { + for (collider, transform) in collider.clone() { + parent.spawn((collider, transform)); + } + }); } else { - commands.spawn(( - RigidBody::Dynamic, - Transform::from_xyz(2.0 * x as f32, 0.0, -2.0 * z as f32), - scene_root.clone(), - )).with_children(|parent| { - for (collider, transform) in collider.clone() { - parent.spawn((collider, transform)); - } - }); + commands + .spawn(( + RigidBody::Dynamic, + Transform::from_xyz(2.0 * x as f32, 0.0, -2.0 * z as f32), + scene_root.clone(), + )) + .with_children(|parent| { + for (collider, transform) in collider.clone() { + parent.spawn((collider, transform)); + } + }); } } } From 749d480b857b5fcb9a57b90f9299a3b269b06e6c Mon Sep 17 00:00:00 2001 From: AmadeusWM <63149896+AmadeusWM@users.noreply.github.com> Date: Sun, 6 Apr 2025 20:59:58 +0200 Subject: [PATCH 3/3] door opening --- src/interaction/objects.rs | 18 ++++++++- src/interaction/ui.rs | 2 +- src/level_instantiation/mod.rs | 72 +++++++++++++++++++++------------- src/player.rs | 10 +++-- 4 files changed, 68 insertions(+), 34 deletions(-) diff --git a/src/interaction/objects.rs b/src/interaction/objects.rs index 00bb787..9e390e8 100644 --- a/src/interaction/objects.rs +++ b/src/interaction/objects.rs @@ -2,8 +2,7 @@ use bevy::prelude::*; use bevy_rapier3d::prelude::ColliderDisabled; use crate::{ - player::{Player, PlayerAction, toolbar::Item}, - util::single_mut, + level_instantiation::Door, player::{toolbar::Item, Player, PlayerAction}, util::single_mut }; use super::{Interact, ui::InteractionOpportunity}; @@ -79,3 +78,18 @@ pub fn handle_drop( *item_transform = *transform; } } + +pub fn handle_door_interaction( + player_query: Query<&PlayerAction, With>, mut doors: Query<&mut Door> +) { + let Ok(action) = player_query.get_single() else { + return; + }; + if *action != PlayerAction::OpenDoor { + return; + } + + for mut door in doors.iter_mut() { + door.is_open = !door.is_open; + } +} diff --git a/src/interaction/ui.rs b/src/interaction/ui.rs index dbf1731..1b84f3a 100644 --- a/src/interaction/ui.rs +++ b/src/interaction/ui.rs @@ -17,7 +17,7 @@ pub(super) fn plugin(app: &mut App) { ( update_interaction_opportunities, display_interaction_prompt, - (objects::handle_pick_up, objects::handle_drop), + (objects::handle_pick_up, objects::handle_drop, objects::handle_door_interaction), ) .chain() .run_if(in_state(GameState::Playing)), diff --git a/src/level_instantiation/mod.rs b/src/level_instantiation/mod.rs index 777b8bf..121028c 100644 --- a/src/level_instantiation/mod.rs +++ b/src/level_instantiation/mod.rs @@ -5,10 +5,7 @@ use bevy_rapier3d::prelude::*; use rand::{Rng, seq::IteratorRandom}; use crate::{ - GameState, - asset_loading::{GltfAssets, ImageAssets}, - interaction::Interact, - player::toolbar::ItemIcon, + asset_loading::{GltfAssets, ImageAssets}, interaction::Interact, player::{toolbar::ItemIcon, Player, PlayerAction}, GameState }; pub fn map_plugin(app: &mut App) { @@ -16,6 +13,7 @@ pub fn map_plugin(app: &mut App) { OnEnter(GameState::Playing), (spawn_level, spawn_objects, spawn_doors).chain(), ); + app.add_systems(Update, handle_door_pos); } fn spawn_level( @@ -622,6 +620,13 @@ fn spawn_objects( } } +#[derive(Component)] +pub struct Door { + pub is_open: bool, + pub open_direction: (i32, i32), + pub position: (i32, i32) +} + fn spawn_doors( mut commands: Commands, levels: Res, @@ -641,31 +646,42 @@ fn spawn_doors( for level in levels.levels.iter() { let (x, z) = level.end_node; - if x <= z { - commands - .spawn(( - RigidBody::Fixed, - Transform::from_xyz(2.0 * x as f32, 0.0, -2.0 * z as f32) - .with_rotation(Quat::from_rotation_y(90.0_f32.to_radians())), - scene_root.clone(), - )) - .with_children(|parent| { - for (collider, transform) in collider.clone() { - parent.spawn((collider, transform)); - } - }); + let (direction, transform) = if x >= z { + ( + (0, 1), + Transform::from_xyz(2.0 * x as f32, 0.0, -2.0 * z as f32) + .with_rotation(Quat::from_rotation_y(90.0_f32.to_radians())) + ) } else { - commands - .spawn(( - RigidBody::Dynamic, - Transform::from_xyz(2.0 * x as f32, 0.0, -2.0 * z as f32), - scene_root.clone(), - )) - .with_children(|parent| { - for (collider, transform) in collider.clone() { - parent.spawn((collider, transform)); - } - }); + ( + (1, 0), + Transform::from_xyz(2.0 * x as f32, 0.0, -2.0 * z as f32) + ) + }; + commands.spawn(( + RigidBody::Fixed, + Door { + is_open: false, + open_direction: direction, + position: (x, z) + }, + transform, + scene_root.clone(), + )).with_children(|parent| { + for (collider, transform) in collider.clone() { + parent.spawn((collider, transform)); + } + }); + } +} + +fn handle_door_pos(mut query: Query<(&Door, &mut Transform)>) { + for (door, mut transform) in query.iter_mut() { + if door.is_open { + transform.translation.y = 2.0 + } + else { + transform.translation.y = 0.0; } } } diff --git a/src/player.rs b/src/player.rs index 059be77..68f5e41 100644 --- a/src/player.rs +++ b/src/player.rs @@ -130,10 +130,10 @@ pub fn init_player( ..default() }), DistanceFog { - color: Color::srgba(0.12, 0.08, 0.08, 0.65), + color: Color::srgba(0.12, 0.08, 0.08, 0.65), falloff: FogFalloff::Linear { - start: 3.0, - end: 12.0, + start: 3.0, + end: 12.0, }, ..default() }, @@ -242,6 +242,7 @@ pub(crate) enum PlayerAction { Sprint, Jump, ToggleFlashlight, + OpenDoor, // Objects and stuff PickUp, Drop, @@ -290,6 +291,9 @@ pub fn handle_input( if keyboard_input.just_pressed(KeyCode::KeyF) { *action = PlayerAction::ToggleFlashlight; } + if keyboard_input.just_pressed(KeyCode::KeyK) { + *action = PlayerAction::OpenDoor; + } input.movement_direction = movement_direction.normalize_or_zero(); }