drop
49
Cargo.lock
generated
@@ -149,6 +149,7 @@ dependencies = [
|
|||||||
"bevy_egui",
|
"bevy_egui",
|
||||||
"bevy_kira_audio",
|
"bevy_kira_audio",
|
||||||
"bevy_rapier3d",
|
"bevy_rapier3d",
|
||||||
|
"rand 0.9.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -978,7 +979,7 @@ dependencies = [
|
|||||||
"derive_more",
|
"derive_more",
|
||||||
"glam",
|
"glam",
|
||||||
"itertools 0.13.0",
|
"itertools 0.13.0",
|
||||||
"rand",
|
"rand 0.8.5",
|
||||||
"rand_distr",
|
"rand_distr",
|
||||||
"serde",
|
"serde",
|
||||||
"smallvec",
|
"smallvec",
|
||||||
@@ -2543,7 +2544,7 @@ checksum = "8babf46d4c1c9d92deac9f7be466f76dfc4482b6452fc5024b5e8daf6ffeb3ee"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"bytemuck",
|
"bytemuck",
|
||||||
"mint",
|
"mint",
|
||||||
"rand",
|
"rand 0.8.5",
|
||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -4263,8 +4264,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
|
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
"rand_chacha",
|
"rand_chacha 0.3.1",
|
||||||
"rand_core",
|
"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]]
|
[[package]]
|
||||||
@@ -4274,7 +4286,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
|
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ppv-lite86",
|
"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]]
|
[[package]]
|
||||||
@@ -4286,6 +4308,15 @@ dependencies = [
|
|||||||
"getrandom 0.2.15",
|
"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]]
|
[[package]]
|
||||||
name = "rand_distr"
|
name = "rand_distr"
|
||||||
version = "0.4.3"
|
version = "0.4.3"
|
||||||
@@ -4293,7 +4324,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "32cb0b9bc82b0a0876c2dd994a7e7a2683d3e7390ca40e6886785ef0c7e3ee31"
|
checksum = "32cb0b9bc82b0a0876c2dd994a7e7a2683d3e7390ca40e6886785ef0c7e3ee31"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"num-traits",
|
"num-traits",
|
||||||
"rand",
|
"rand 0.8.5",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -4358,8 +4389,8 @@ dependencies = [
|
|||||||
"once_cell",
|
"once_cell",
|
||||||
"paste",
|
"paste",
|
||||||
"profiling",
|
"profiling",
|
||||||
"rand",
|
"rand 0.8.5",
|
||||||
"rand_chacha",
|
"rand_chacha 0.3.1",
|
||||||
"simd_helpers",
|
"simd_helpers",
|
||||||
"system-deps",
|
"system-deps",
|
||||||
"thiserror 1.0.69",
|
"thiserror 1.0.69",
|
||||||
@@ -5427,7 +5458,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "b3758f5e68192bb96cc8f9b7e2c2cfdabb435499a28499a42f8f984092adad4b"
|
checksum = "b3758f5e68192bb96cc8f9b7e2c2cfdabb435499a28499a42f8f984092adad4b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"getrandom 0.2.15",
|
"getrandom 0.2.15",
|
||||||
"rand",
|
"rand 0.8.5",
|
||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|||||||
@@ -9,3 +9,4 @@ bevy_asset_loader = { version ="0.22.0", features = ["standard_dynamic_assets"]
|
|||||||
bevy_egui = "0.33.0"
|
bevy_egui = "0.33.0"
|
||||||
bevy_kira_audio = "0.22.0"
|
bevy_kira_audio = "0.22.0"
|
||||||
bevy_rapier3d = "0.29.0"
|
bevy_rapier3d = "0.29.0"
|
||||||
|
rand = "0.9.0"
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 18 KiB |
@@ -1,3 +1,80 @@
|
|||||||
use bevy::prelude::*;
|
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 plugin(_app: &mut App) {}
|
||||||
|
|
||||||
|
pub fn handle_pick_up(
|
||||||
|
mut commands: Commands,
|
||||||
|
// current action
|
||||||
|
mut action: Query<(&PlayerAction, &mut Item), With<Player>>,
|
||||||
|
mut vis_query: Query<&mut Visibility>,
|
||||||
|
children: Query<&mut Children>,
|
||||||
|
|
||||||
|
// current interactable
|
||||||
|
mut interaction_opportunity: ResMut<InteractionOpportunity>,
|
||||||
|
) {
|
||||||
|
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::<ColliderDisabled>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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>,
|
||||||
|
) {
|
||||||
|
// 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>();
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ use bevy_rapier3d::prelude::*;
|
|||||||
use bevy_rapier3d::rapier::prelude::CollisionEventFlags;
|
use bevy_rapier3d::rapier::prelude::CollisionEventFlags;
|
||||||
use std::iter;
|
use std::iter;
|
||||||
|
|
||||||
use super::Interact;
|
use super::{Interact, objects};
|
||||||
|
|
||||||
pub(super) fn plugin(app: &mut App) {
|
pub(super) fn plugin(app: &mut App) {
|
||||||
app.add_plugins(EguiPlugin)
|
app.add_plugins(EguiPlugin)
|
||||||
@@ -18,7 +18,7 @@ pub(super) fn plugin(app: &mut App) {
|
|||||||
(
|
(
|
||||||
update_interaction_opportunities,
|
update_interaction_opportunities,
|
||||||
display_interaction_prompt,
|
display_interaction_prompt,
|
||||||
handle_pick_up,
|
(objects::handle_pick_up, objects::handle_drop),
|
||||||
)
|
)
|
||||||
.chain()
|
.chain()
|
||||||
.run_if(in_state(GameState::Playing)),
|
.run_if(in_state(GameState::Playing)),
|
||||||
@@ -26,7 +26,7 @@ pub(super) fn plugin(app: &mut App) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Eq, PartialEq, Resource, Default)]
|
#[derive(Debug, Clone, Eq, PartialEq, Resource, Default)]
|
||||||
struct InteractionOpportunity(Option<Entity>);
|
pub struct InteractionOpportunity(pub Option<Entity>);
|
||||||
|
|
||||||
fn update_interaction_opportunities(
|
fn update_interaction_opportunities(
|
||||||
mut collision_events: EventReader<CollisionEvent>,
|
mut collision_events: EventReader<CollisionEvent>,
|
||||||
@@ -81,6 +81,7 @@ fn display_interaction_prompt(
|
|||||||
.map(|name| name.as_str())
|
.map(|name| name.as_str())
|
||||||
.expect("A named Interactable object");
|
.expect("A named Interactable object");
|
||||||
|
|
||||||
|
// objective or item
|
||||||
egui::Window::new("Interaction")
|
egui::Window::new("Interaction")
|
||||||
.collapsible(false)
|
.collapsible(false)
|
||||||
.title_bar(false)
|
.title_bar(false)
|
||||||
@@ -90,27 +91,3 @@ fn display_interaction_prompt(
|
|||||||
ui.label(format!("E: Pick Up {entity_name}"));
|
ui.label(format!("E: Pick Up {entity_name}"));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_pick_up(
|
|
||||||
// current action
|
|
||||||
mut action: Query<(&PlayerAction, &mut Item), With<Player>>,
|
|
||||||
mut item_query: Query<&mut Visibility, With<Interact>>,
|
|
||||||
// current interactable
|
|
||||||
interaction_opportunity: Res<InteractionOpportunity>,
|
|
||||||
) {
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
use bevy::{image, prelude::*, reflect::DynamicTypePath};
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
use bevy::prelude::*;
|
||||||
use bevy_rapier3d::prelude::*;
|
use bevy_rapier3d::prelude::*;
|
||||||
|
use rand::Rng;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
GameState,
|
GameState,
|
||||||
@@ -28,29 +31,45 @@ fn spawn_level(mut commands: Commands, models: Res<Assets<Gltf>>, gltf_assets: R
|
|||||||
let shapes = mesh_names.map(|mesh_name| {
|
let shapes = mesh_names.map(|mesh_name| {
|
||||||
let collider: Vec<(Collider, Transform)> = match mesh_name {
|
let collider: Vec<(Collider, Transform)> = match mesh_name {
|
||||||
"corner_inside" => vec![(
|
"corner_inside" => vec![(
|
||||||
Collider::cuboid(1.0, 0.1, 1.0),
|
Collider::cuboid(0.2, 1.0, 0.2),
|
||||||
Transform::from_xyz(0.0, 0.0, 0.0),
|
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, 0.1, 1.0),
|
|
||||||
Transform::from_xyz(0.0, 0.0, 0.0),
|
|
||||||
)],
|
)],
|
||||||
|
"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![(
|
"wall" => vec![(
|
||||||
Collider::cuboid(1.0, 1.0, 0.1),
|
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![(
|
"door" => vec![(
|
||||||
Collider::cuboid(1.0, 0.1, 1.0),
|
Collider::cuboid(1.0, 1.0, 0.1),
|
||||||
Transform::from_xyz(0.0, 0.0, 0.0),
|
Transform::from_xyz(0.0, 1.0, -1.0),
|
||||||
)],
|
)],
|
||||||
"round_door" => vec![(
|
"round_door" => vec![(
|
||||||
Collider::cuboid(1.0, 0.1, 1.0),
|
Collider::cuboid(1.0, 1.0, 0.1),
|
||||||
Transform::from_xyz(0.0, 0.0, 0.0),
|
Transform::from_xyz(0.0, 1.0, -1.0),
|
||||||
)],
|
|
||||||
"round_hole" => vec![(
|
|
||||||
Collider::cuboid(1.0, 0.1, 1.0),
|
|
||||||
Transform::from_xyz(0.0, 0.0, 0.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![(
|
_ => vec![(
|
||||||
Collider::cuboid(1.0, 0.1, 1.0),
|
Collider::cuboid(1.0, 0.1, 1.0),
|
||||||
Transform::from_xyz(0.0, 0.0, 0.0),
|
Transform::from_xyz(0.0, 0.0, 0.0),
|
||||||
@@ -78,31 +97,7 @@ fn spawn_level(mut commands: Commands, models: Res<Assets<Gltf>>, gltf_assets: R
|
|||||||
door,
|
door,
|
||||||
round_door,
|
round_door,
|
||||||
round_hole,
|
round_hole,
|
||||||
] = shapes;
|
] = shapes.clone();
|
||||||
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));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// huge floor
|
// huge floor
|
||||||
commands.spawn((
|
commands.spawn((
|
||||||
@@ -110,11 +105,422 @@ fn spawn_level(mut commands: Commands, models: Res<Assets<Gltf>>, gltf_assets: R
|
|||||||
Collider::cuboid(1000.0, 0.1, 1000.0),
|
Collider::cuboid(1000.0, 0.1, 1000.0),
|
||||||
Transform::from_xyz(-500.0, 0.0, -500.0),
|
Transform::from_xyz(-500.0, 0.0, -500.0),
|
||||||
));
|
));
|
||||||
commands.spawn((
|
// huge roof
|
||||||
RigidBody::Fixed,
|
// commands.spawn((
|
||||||
Collider::cuboid(1000.0, 0.1, 1000.0),
|
// RigidBody::Fixed,
|
||||||
Transform::from_xyz(-500.0, 3.0, -500.0),
|
// 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(
|
fn spawn_objects(
|
||||||
@@ -156,14 +562,13 @@ fn spawn_objects(
|
|||||||
Transform::from_xyz(0.0, 2.0, 2.0),
|
Transform::from_xyz(0.0, 2.0, 2.0),
|
||||||
Interact,
|
Interact,
|
||||||
RigidBody::Dynamic,
|
RigidBody::Dynamic,
|
||||||
Name::new("Id Card"),
|
Name::new("Id Card 1"),
|
||||||
Visibility::Visible,
|
Visibility::Visible,
|
||||||
ItemIcon::new(image_assets.id_card.clone()),
|
ItemIcon::new(image_assets.id_card.clone()),
|
||||||
SceneRoot(asset.clone()),
|
SceneRoot(asset.clone()),
|
||||||
))
|
))
|
||||||
.with_children(|parent| {
|
.with_children(|parent| {
|
||||||
parent.spawn((
|
parent.spawn((
|
||||||
Visibility::Inherited,
|
|
||||||
ColliderMassProperties::Mass(10.0),
|
ColliderMassProperties::Mass(10.0),
|
||||||
Collider::cuboid(0.05, 0.05, 0.01),
|
Collider::cuboid(0.05, 0.05, 0.01),
|
||||||
Transform::from_rotation(Quat::from_euler(
|
Transform::from_rotation(Quat::from_euler(
|
||||||
@@ -174,7 +579,6 @@ fn spawn_objects(
|
|||||||
)),
|
)),
|
||||||
));
|
));
|
||||||
parent.spawn((
|
parent.spawn((
|
||||||
Visibility::Inherited,
|
|
||||||
ActiveEvents::COLLISION_EVENTS,
|
ActiveEvents::COLLISION_EVENTS,
|
||||||
Transform::default(),
|
Transform::default(),
|
||||||
Collider::ball(0.5), // Interaction radius
|
Collider::ball(0.5), // Interaction radius
|
||||||
|
|||||||
115
src/player.rs
@@ -1,13 +1,18 @@
|
|||||||
|
|
||||||
use bevy::{
|
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_kira_audio::{Audio, AudioControl};
|
||||||
use bevy_rapier3d::prelude::*;
|
use bevy_rapier3d::prelude::*;
|
||||||
|
|
||||||
pub mod toolbar;
|
pub mod toolbar;
|
||||||
|
|
||||||
use crate::{asset_loading::{AudioAssets, FlashlightAssets}, GameState};
|
use crate::{
|
||||||
|
GameState,
|
||||||
|
asset_loading::{AudioAssets, FlashlightAssets},
|
||||||
|
};
|
||||||
|
|
||||||
#[derive(Debug, Component, Default)]
|
#[derive(Debug, Component, Default)]
|
||||||
pub struct Player {
|
pub struct Player {
|
||||||
@@ -64,13 +69,12 @@ pub struct FlashlightButtonAnimation {
|
|||||||
impl Default for FlashlightButtonAnimation {
|
impl Default for FlashlightButtonAnimation {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
timer: Timer::from_seconds(0.20, TimerMode::Once),
|
timer: Timer::from_seconds(0.20, TimerMode::Once),
|
||||||
is_pressed: false,
|
is_pressed: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pub fn plugin(app: &mut App) {
|
pub fn plugin(app: &mut App) {
|
||||||
app.add_plugins(toolbar::plugin)
|
app.add_plugins(toolbar::plugin)
|
||||||
.add_systems(OnEnter(GameState::Playing), (init_player, hide_cursor))
|
.add_systems(OnEnter(GameState::Playing), (init_player, hide_cursor))
|
||||||
@@ -78,12 +82,13 @@ pub fn plugin(app: &mut App) {
|
|||||||
Update,
|
Update,
|
||||||
(
|
(
|
||||||
move_camera,
|
move_camera,
|
||||||
handle_input,
|
handle_input,
|
||||||
apply_head_bob,
|
apply_head_bob,
|
||||||
on_resize_system,
|
on_resize_system,
|
||||||
handle_flashlight,
|
handle_flashlight,
|
||||||
update_flashlight_button_animation,
|
update_flashlight_button_animation,
|
||||||
).run_if(in_state(GameState::Playing)),
|
)
|
||||||
|
.run_if(in_state(GameState::Playing)),
|
||||||
)
|
)
|
||||||
.add_systems(
|
.add_systems(
|
||||||
FixedUpdate,
|
FixedUpdate,
|
||||||
@@ -138,8 +143,6 @@ pub fn init_player(
|
|||||||
},
|
},
|
||||||
RenderLayers::layer(STATIC_LAYER),
|
RenderLayers::layer(STATIC_LAYER),
|
||||||
));
|
));
|
||||||
|
|
||||||
// pitslamp sprite
|
|
||||||
let window = window.single();
|
let window = window.single();
|
||||||
let transform = flashlight_base_transform(window.width(), window.height());
|
let transform = flashlight_base_transform(window.width(), window.height());
|
||||||
parent.spawn((
|
parent.spawn((
|
||||||
@@ -149,18 +152,18 @@ pub fn init_player(
|
|||||||
RenderLayers::layer(STATIC_LAYER),
|
RenderLayers::layer(STATIC_LAYER),
|
||||||
FlashlightButtonAnimation::default(),
|
FlashlightButtonAnimation::default(),
|
||||||
));
|
));
|
||||||
|
|
||||||
// feitelijke pitslamp
|
// feitelijke pitslamp
|
||||||
parent.spawn((
|
parent.spawn((
|
||||||
Flashlight,
|
Flashlight,
|
||||||
SpotLight {
|
SpotLight {
|
||||||
intensity: 0.0,
|
intensity: 0.0,
|
||||||
color: Color::WHITE,
|
color: Color::WHITE,
|
||||||
range: 4.0,
|
range: 4.0,
|
||||||
outer_angle: 30.0_f32.to_radians(), // wide cone for flashlight
|
outer_angle: 30.0_f32.to_radians(), // wide cone for flashlight
|
||||||
inner_angle: 10.0_f32.to_radians(), // narrower inner cone
|
inner_angle: 10.0_f32.to_radians(), // narrower inner cone
|
||||||
shadows_enabled: false, // (set to true for realism)
|
shadows_enabled: false, // (set to true for realism)
|
||||||
radius: 0.35, // low value for hard light
|
radius: 0.35, // low value for hard light
|
||||||
..default()
|
..default()
|
||||||
},
|
},
|
||||||
Transform::from_xyz(0.0, -0.15, 0.5),
|
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 {
|
fn flashlight_base_transform(window_width: f32, window_height: f32) -> BaseTransform {
|
||||||
let window_size = Vec2::new(window_width, window_height);
|
let window_size = Vec2::new(window_width, window_height);
|
||||||
let sprite_size = Vec2::new(101.0, 101.0);
|
let sprite_size = Vec2::new(404.0, 404.0);
|
||||||
let scale = window_width / 600.0;
|
let scale = window_width / 2400.0;
|
||||||
let world_size = sprite_size * scale;
|
let world_size = sprite_size * scale;
|
||||||
let xoffset = window_size.x / 4.0 - 40.0;
|
let xoffset = window_size.x / 4.0 - 40.0;
|
||||||
let yoffset = 15.0;
|
let yoffset = 15.0;
|
||||||
|
|
||||||
let mut transform = Transform::from_translation(
|
let mut transform = Transform::from_translation(Vec3::new(
|
||||||
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)
|
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);
|
transform.scale = Vec3::new(scale, scale, 1.0);
|
||||||
return BaseTransform(transform);
|
return BaseTransform(transform);
|
||||||
}
|
}
|
||||||
@@ -231,8 +236,10 @@ pub(crate) enum PlayerAction {
|
|||||||
Move,
|
Move,
|
||||||
Sprint,
|
Sprint,
|
||||||
Jump,
|
Jump,
|
||||||
Interact,
|
ToggleFlashlight,
|
||||||
ToggleFlashlight
|
// Objects and stuff
|
||||||
|
PickUp,
|
||||||
|
Drop,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn handle_input(
|
pub fn handle_input(
|
||||||
@@ -240,7 +247,7 @@ pub fn handle_input(
|
|||||||
mut query: Query<(&Transform, &mut PlayerInput, &mut PlayerAction, &mut Player), With<Player>>,
|
mut query: Query<(&Transform, &mut PlayerInput, &mut PlayerAction, &mut Player), With<Player>>,
|
||||||
) {
|
) {
|
||||||
for (transform, mut input, mut action, mut player) in query.iter_mut() {
|
for (transform, mut input, mut action, mut player) in query.iter_mut() {
|
||||||
*action = PlayerAction::Move;
|
*action = PlayerAction::Move;
|
||||||
|
|
||||||
let forward = transform.forward();
|
let forward = transform.forward();
|
||||||
let right = transform.right();
|
let right = transform.right();
|
||||||
@@ -267,10 +274,13 @@ pub fn handle_input(
|
|||||||
} else if keyboard_input.pressed(KeyCode::ControlLeft) {
|
} else if keyboard_input.pressed(KeyCode::ControlLeft) {
|
||||||
player.speed_factor = 0.65;
|
player.speed_factor = 0.65;
|
||||||
} else {
|
} else {
|
||||||
player.speed_factor = 1.0;
|
player.speed_factor = 1.0;
|
||||||
}
|
}
|
||||||
if keyboard_input.just_pressed(KeyCode::KeyE) {
|
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) {
|
if keyboard_input.just_pressed(KeyCode::KeyF) {
|
||||||
*action = PlayerAction::ToggleFlashlight;
|
*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<Player>>) {
|
pub fn apply_player_movement(
|
||||||
|
mut player_query: Query<(&PlayerInput, &mut Velocity, &Player), With<Player>>,
|
||||||
|
) {
|
||||||
const SPEED: f32 = 2.6;
|
const SPEED: f32 = 2.6;
|
||||||
const JUMP_FORCE: f32 = 4.0;
|
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 {
|
if input.movement_direction.y > 0.0 {
|
||||||
velocity.linvel.y = JUMP_FORCE;
|
velocity.linvel.y = JUMP_FORCE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -305,14 +317,18 @@ pub fn apply_head_bob(
|
|||||||
time: Res<Time>,
|
time: Res<Time>,
|
||||||
mut query: Query<(&PlayerInput, &mut HeadBob, &Player), With<Player>>,
|
mut query: Query<(&PlayerInput, &mut HeadBob, &Player), With<Player>>,
|
||||||
mut camera_query: Query<&mut Transform, (With<WorldModelCamera>, Without<Player>)>,
|
mut camera_query: Query<&mut Transform, (With<WorldModelCamera>, Without<Player>)>,
|
||||||
mut sprite_query: Query<(&mut Transform, &Sprite, &BaseTransform), (With<Sprite>, Without<WorldModelCamera>, Without<Player>)>,
|
mut sprite_query: Query<
|
||||||
|
(&mut Transform, &Sprite, &BaseTransform),
|
||||||
|
(With<Sprite>, Without<WorldModelCamera>, Without<Player>),
|
||||||
|
>,
|
||||||
) {
|
) {
|
||||||
let Ok((input, mut head_bob, player)) = query.get_single_mut() else {
|
let Ok((input, mut head_bob, player)) = query.get_single_mut() else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
// bob when moving horizontally
|
// bob when moving horizontally
|
||||||
let horizontal_movement = Vec3::new(input.movement_direction.x, 0.0, input.movement_direction.z);
|
let horizontal_movement =
|
||||||
|
Vec3::new(input.movement_direction.x, 0.0, input.movement_direction.z);
|
||||||
let is_moving = horizontal_movement.length_squared() > 0.01;
|
let is_moving = horizontal_movement.length_squared() > 0.01;
|
||||||
let bobbing_speed = head_bob.speed * player.speed_factor;
|
let bobbing_speed = head_bob.speed * player.speed_factor;
|
||||||
|
|
||||||
@@ -325,7 +341,7 @@ pub fn apply_head_bob(
|
|||||||
if let Some(camera_transform) = camera_query.iter_mut().next() {
|
if let Some(camera_transform) = camera_query.iter_mut().next() {
|
||||||
let current_offset = camera_transform.translation.y;
|
let current_offset = camera_transform.translation.y;
|
||||||
if current_offset.abs() < 0.005 {
|
if current_offset.abs() < 0.005 {
|
||||||
// cancel out so head_bob.time_offset
|
// cancel out so head_bob.time_offset
|
||||||
offset = -head_bob.time_offset;
|
offset = -head_bob.time_offset;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -336,7 +352,7 @@ pub fn apply_head_bob(
|
|||||||
// calculate vertical and horizontal offsets using sine and cosine
|
// calculate vertical and horizontal offsets using sine and cosine
|
||||||
let vertical_offset = head_bob.intensity * f32::sin(head_bob.time_offset);
|
let vertical_offset = head_bob.intensity * f32::sin(head_bob.time_offset);
|
||||||
let horizontal_offset = (head_bob.intensity * 0.5) * f32::cos(head_bob.time_offset * 0.5);
|
let horizontal_offset = (head_bob.intensity * 0.5) * f32::cos(head_bob.time_offset * 0.5);
|
||||||
|
|
||||||
// apply
|
// apply
|
||||||
for mut transform in camera_query.iter_mut() {
|
for mut transform in camera_query.iter_mut() {
|
||||||
transform.translation.y = vertical_offset;
|
transform.translation.y = vertical_offset;
|
||||||
@@ -347,32 +363,31 @@ pub fn apply_head_bob(
|
|||||||
transform.translation.x *= 0.8;
|
transform.translation.x *= 0.8;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// apply offsets to flashlight
|
// apply offsets to flashlight
|
||||||
for (mut transform, _sprite, base_transform) in sprite_query.iter_mut() {
|
for (mut transform, _sprite, base_transform) in sprite_query.iter_mut() {
|
||||||
let scale_factor = 40.0 * player.speed_factor;
|
let scale_factor = 40.0 * player.speed_factor;
|
||||||
|
|
||||||
if is_moving {
|
if is_moving {
|
||||||
transform.translation.x = base_transform.0.translation.x + horizontal_offset * scale_factor;
|
transform.translation.x =
|
||||||
transform.translation.y = base_transform.0.translation.y + vertical_offset * scale_factor;
|
base_transform.0.translation.x + horizontal_offset * scale_factor;
|
||||||
|
transform.translation.y =
|
||||||
transform.rotation = Quat::from_euler(
|
base_transform.0.translation.y + vertical_offset * scale_factor;
|
||||||
EulerRot::XYZ,
|
|
||||||
0.0,
|
transform.rotation =
|
||||||
0.0,
|
Quat::from_euler(EulerRot::XYZ, 0.0, 0.0, horizontal_offset * 0.1);
|
||||||
horizontal_offset * 0.1,
|
|
||||||
);
|
|
||||||
} else {
|
} else {
|
||||||
transform.translation = transform.translation.lerp(base_transform.0.translation, 0.1);
|
transform.translation = transform
|
||||||
|
.translation
|
||||||
|
.lerp(base_transform.0.translation, 0.1);
|
||||||
transform.rotation = transform.rotation.slerp(Quat::IDENTITY, 0.1);
|
transform.rotation = transform.rotation.slerp(Quat::IDENTITY, 0.1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn handle_flashlight(
|
pub fn handle_flashlight(
|
||||||
player_query: Query<&PlayerAction, With<Player>>,
|
player_query: Query<&PlayerAction, With<Player>>,
|
||||||
mut flashlight_query: Query<&mut SpotLight, With<Flashlight>>,
|
mut flashlight_query: Query<&mut SpotLight, With<Flashlight>>,
|
||||||
mut flashlight_sprite_query: Query<&mut FlashlightButtonAnimation>,
|
mut flashlight_sprite_query: Query<&mut FlashlightButtonAnimation>,
|
||||||
audio_assets: Res<AudioAssets>,
|
audio_assets: Res<AudioAssets>,
|
||||||
audio: Res<Audio>,
|
audio: Res<Audio>,
|
||||||
@@ -390,9 +405,9 @@ pub fn handle_flashlight(
|
|||||||
if let Ok(mut spotlight) = flashlight_query.get_single_mut() {
|
if let Ok(mut spotlight) = flashlight_query.get_single_mut() {
|
||||||
audio.play(audio_assets.flash_click.clone());
|
audio.play(audio_assets.flash_click.clone());
|
||||||
|
|
||||||
spotlight.intensity = if spotlight.intensity > 0.0 {
|
spotlight.intensity = if spotlight.intensity > 0.0 {
|
||||||
0.0
|
0.0
|
||||||
} else {
|
} else {
|
||||||
300_000.0
|
300_000.0
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -414,4 +429,4 @@ pub fn update_flashlight_button_animation(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ fn bottom_panel(
|
|||||||
) {
|
) {
|
||||||
let item = single!(player_item_query);
|
let item = single!(player_item_query);
|
||||||
let item = item.0.and_then(|id| item_query.get(id).ok());
|
let item = item.0.and_then(|id| item_query.get(id).ok());
|
||||||
let (name, icon) = item.map_or((Name::new(""), None), |(name, handle)| {
|
let (name, icon) = item.map_or((Name::new("➖"), None), |(name, handle)| {
|
||||||
(
|
(
|
||||||
name.clone(),
|
name.clone(),
|
||||||
Some(egui_ctx.add_image(handle.0.clone_weak())),
|
Some(egui_ctx.add_image(handle.0.clone_weak())),
|
||||||
@@ -82,8 +82,8 @@ fn bottom_panel(
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
ui.label(egui::RichText::new("➖").size(24.0));
|
|
||||||
ui.label(egui::RichText::new("Empty").size(12.0));
|
ui.label(egui::RichText::new("Empty").size(12.0));
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ui.label(
|
ui.label(
|
||||||
|
|||||||