Merge branch 'main' into open-doors

This commit is contained in:
LorrensP-2158466
2025-04-06 21:03:16 +02:00
5 changed files with 338 additions and 194 deletions

View File

@@ -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};
@@ -19,14 +18,15 @@ pub fn plugin(_app: &mut App) {}
pub fn handle_pick_up(
mut commands: Commands,
// current action
mut action: Query<(&PlayerAction, &mut Item), With<Player>>,
mut player_query: Query<(&PlayerAction, &Transform, &mut Item), With<Player>>,
mut vis_query: Query<&mut Visibility>,
children: Query<&mut Children>,
mut item_transform: Query<&mut Transform, (With<Interact>, Without<Player>)>,
// current interactable
mut interaction_opportunity: ResMut<InteractionOpportunity>,
) {
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 {
@@ -50,36 +50,52 @@ pub fn handle_pick_up(
commands.entity(collider).remove::<ColliderDisabled>();
}
}
// 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<Player>>,
// mut vis_query: Query<&mut Visibility>,
// mut item_transform: Query<&mut Transform, With<Interact>>,
// children: Query<&mut Children>,
pub fn handle_drop(
mut commands: Commands,
// current action
mut player_query: Query<(&PlayerAction, &Transform, &mut Item), With<Player>>,
mut vis_query: Query<&mut Visibility>,
mut item_transform: Query<&mut Transform, (With<Interact>, Without<Player>)>,
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::<ColliderDisabled>();
// }
// }
// }
// }
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::<ColliderDisabled>();
}
}
// 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;
}
}
pub fn handle_door_interaction(
player_query: Query<&PlayerAction, With<Player>>, 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;
}
}

View File

@@ -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::*;
@@ -18,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)),

View File

@@ -2,13 +2,10 @@ use std::collections::HashMap;
use bevy::prelude::*;
use bevy_rapier3d::prelude::*;
use rand::Rng;
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,15 +13,15 @@ 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(
mut commands: Commands,
mut meshes: ResMut<Assets<Mesh>>,
mut materials: ResMut<Assets<StandardMaterial>>,
models: Res<Assets<Gltf>>,
gltf_assets: Res<GltfAssets>
gltf_assets: Res<GltfAssets>,
) {
println!("LIBRARY: {:?}", gltf_assets.library);
let mesh_names = [
@@ -128,138 +125,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<GameLevel> {
let mut maps = Vec::new();
let mut initial_node = LevelNode::new();
@@ -274,7 +361,7 @@ fn create_levels(n: i32) -> Vec<GameLevel> {
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 +417,40 @@ impl LevelNode {
#[derive(Resource)]
struct GameLevels {
pub levels: Vec<GameLevel>
pub levels: Vec<GameLevel>,
}
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 +466,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 +531,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 +563,7 @@ impl GameLevel {
fn spawn_objects(
mut commands: Commands,
levels: Res<GameLevels>,
models: Res<Assets<Gltf>>,
gltf_assets: Res<GltfAssets>,
image_assets: Res<ImageAssets>,
@@ -483,86 +572,116 @@ 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,
));
});
}
}
#[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<GameLevels>,
models: Res<Assets<Gltf>>,
gltf_assets: Res<GltfAssets>
){
gltf_assets: Res<GltfAssets>,
) {
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,
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())),
scene_root.clone(),
)).with_children(|parent| {
for (collider, transform) in collider.clone() {
parent.spawn((collider, transform));
}
});
.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;
}
}
}

View File

@@ -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();
}

View File

@@ -9,6 +9,12 @@ use super::Player;
#[derive(Component, Default, Debug)]
pub struct Item(Option<Entity>);
impl Item {
pub fn take(&mut self) -> Option<Entity> {
self.0.take()
}
}
#[derive(Component, Default, Debug)]
pub struct ItemIcon(Handle<Image>);