Merge branch 'main' into open-doors
This commit is contained in:
@@ -2,8 +2,7 @@ use bevy::prelude::*;
|
|||||||
use bevy_rapier3d::prelude::ColliderDisabled;
|
use bevy_rapier3d::prelude::ColliderDisabled;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
player::{Player, PlayerAction, toolbar::Item},
|
level_instantiation::Door, player::{toolbar::Item, Player, PlayerAction}, util::single_mut
|
||||||
util::single_mut,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{Interact, ui::InteractionOpportunity};
|
use super::{Interact, ui::InteractionOpportunity};
|
||||||
@@ -19,14 +18,15 @@ pub fn plugin(_app: &mut App) {}
|
|||||||
pub fn handle_pick_up(
|
pub fn handle_pick_up(
|
||||||
mut commands: Commands,
|
mut commands: Commands,
|
||||||
// current action
|
// 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>,
|
mut vis_query: Query<&mut Visibility>,
|
||||||
children: Query<&mut Children>,
|
children: Query<&mut Children>,
|
||||||
|
|
||||||
|
mut item_transform: Query<&mut Transform, (With<Interact>, Without<Player>)>,
|
||||||
// current interactable
|
// current interactable
|
||||||
mut interaction_opportunity: ResMut<InteractionOpportunity>,
|
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 {
|
if *action == PlayerAction::PickUp {
|
||||||
// take out the interaction, because we are picking it up
|
// take out the interaction, because we are picking it up
|
||||||
let Some(target) = interaction_opportunity.0.take() else {
|
let Some(target) = interaction_opportunity.0.take() else {
|
||||||
@@ -50,36 +50,52 @@ pub fn handle_pick_up(
|
|||||||
commands.entity(collider).remove::<ColliderDisabled>();
|
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,
|
pub fn handle_drop(
|
||||||
// // current action
|
mut commands: Commands,
|
||||||
// mut action: Query<(&PlayerAction, &Transform, &mut Item), With<Player>>,
|
// current action
|
||||||
// mut vis_query: Query<&mut Visibility>,
|
mut player_query: Query<(&PlayerAction, &Transform, &mut Item), With<Player>>,
|
||||||
// mut item_transform: Query<&mut Transform, With<Interact>>,
|
mut vis_query: Query<&mut Visibility>,
|
||||||
// children: Query<&mut Children>,
|
mut item_transform: Query<&mut Transform, (With<Interact>, Without<Player>)>,
|
||||||
|
children: Query<&mut Children>,
|
||||||
) {
|
) {
|
||||||
// let (action, transform, mut item) = single_mut!(action);
|
let (action, transform, mut item) = single_mut!(player_query);
|
||||||
// if *action == PlayerAction::Drop {
|
if *action == PlayerAction::Drop {
|
||||||
// if let Ok(mut vis) = vis_query.get_mut(target) {
|
let Some(item) = item.take() else {
|
||||||
// *vis = Visibility::Hidden;
|
return;
|
||||||
// }
|
};
|
||||||
// if let Ok(colliders) = children.get(target) {
|
if let Ok(mut vis) = vis_query.get_mut(item) {
|
||||||
// for &collider in colliders {
|
*vis = Visibility::Visible;
|
||||||
// commands.entity(collider).insert(ColliderDisabled);
|
}
|
||||||
// }
|
if let Ok(colliders) = children.get(item) {
|
||||||
// }
|
for &collider in colliders {
|
||||||
// if let Some(dropped) = replaced {
|
commands.entity(collider).remove::<ColliderDisabled>();
|
||||||
// if let Ok(mut vis) = vis_query.get_mut(dropped) {
|
}
|
||||||
// *vis = Visibility::Visible;
|
}
|
||||||
// }
|
|
||||||
// if let Ok(colliders) = children.get(dropped) {
|
// for simplicities sake, set the transform of the item that is dropped to that of the player
|
||||||
// for &collider in colliders {
|
let mut item_transform = item_transform.get_mut(item).unwrap();
|
||||||
// commands.entity(collider).remove::<ColliderDisabled>();
|
*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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
use crate::GameState;
|
use crate::GameState;
|
||||||
use crate::player::toolbar::Item;
|
use crate::player::Player;
|
||||||
use crate::player::{Player, PlayerAction};
|
use crate::util::single;
|
||||||
use crate::util::{single, single_mut};
|
|
||||||
use bevy::{prelude::*, window::PrimaryWindow};
|
use bevy::{prelude::*, window::PrimaryWindow};
|
||||||
use bevy_egui::{EguiContexts, EguiPlugin, egui};
|
use bevy_egui::{EguiContexts, EguiPlugin, egui};
|
||||||
use bevy_rapier3d::prelude::*;
|
use bevy_rapier3d::prelude::*;
|
||||||
@@ -18,7 +17,7 @@ pub(super) fn plugin(app: &mut App) {
|
|||||||
(
|
(
|
||||||
update_interaction_opportunities,
|
update_interaction_opportunities,
|
||||||
display_interaction_prompt,
|
display_interaction_prompt,
|
||||||
(objects::handle_pick_up, objects::handle_drop),
|
(objects::handle_pick_up, objects::handle_drop, objects::handle_door_interaction),
|
||||||
)
|
)
|
||||||
.chain()
|
.chain()
|
||||||
.run_if(in_state(GameState::Playing)),
|
.run_if(in_state(GameState::Playing)),
|
||||||
|
|||||||
@@ -2,13 +2,10 @@ use std::collections::HashMap;
|
|||||||
|
|
||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
use bevy_rapier3d::prelude::*;
|
use bevy_rapier3d::prelude::*;
|
||||||
use rand::Rng;
|
use rand::{Rng, seq::IteratorRandom};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
GameState,
|
asset_loading::{GltfAssets, ImageAssets}, interaction::Interact, player::{toolbar::ItemIcon, Player, PlayerAction}, GameState
|
||||||
asset_loading::{GltfAssets, ImageAssets},
|
|
||||||
interaction::Interact,
|
|
||||||
player::toolbar::ItemIcon,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn map_plugin(app: &mut App) {
|
pub fn map_plugin(app: &mut App) {
|
||||||
@@ -16,15 +13,15 @@ pub fn map_plugin(app: &mut App) {
|
|||||||
OnEnter(GameState::Playing),
|
OnEnter(GameState::Playing),
|
||||||
(spawn_level, spawn_objects, spawn_doors).chain(),
|
(spawn_level, spawn_objects, spawn_doors).chain(),
|
||||||
);
|
);
|
||||||
|
app.add_systems(Update, handle_door_pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fn spawn_level(
|
fn spawn_level(
|
||||||
mut commands: Commands,
|
mut commands: Commands,
|
||||||
mut meshes: ResMut<Assets<Mesh>>,
|
mut meshes: ResMut<Assets<Mesh>>,
|
||||||
mut materials: ResMut<Assets<StandardMaterial>>,
|
mut materials: ResMut<Assets<StandardMaterial>>,
|
||||||
models: Res<Assets<Gltf>>,
|
models: Res<Assets<Gltf>>,
|
||||||
gltf_assets: Res<GltfAssets>
|
gltf_assets: Res<GltfAssets>,
|
||||||
) {
|
) {
|
||||||
println!("LIBRARY: {:?}", gltf_assets.library);
|
println!("LIBRARY: {:?}", gltf_assets.library);
|
||||||
let mesh_names = [
|
let mesh_names = [
|
||||||
@@ -128,138 +125,228 @@ fn spawn_level(
|
|||||||
// corners are handled later, for now just a wall to test
|
// corners are handled later, for now just a wall to test
|
||||||
let node = node.clone();
|
let node = node.clone();
|
||||||
|
|
||||||
let pos = Transform::from_xyz(2.0*(*x) as f32, 0.0, -2.0*(*z) as f32);
|
let pos = Transform::from_xyz(2.0 * (*x) as f32, 0.0, -2.0 * (*z) as f32);
|
||||||
use Side::{Connection, Closed};
|
use Side::{Closed, Connection};
|
||||||
match (node.north, node.east, node.south, node.west) {
|
match (node.north, node.east, node.south, node.west) {
|
||||||
// hallway horizontal
|
// hallway horizontal
|
||||||
(Closed, Connection, Closed, Connection) => {
|
(Closed, Connection, Closed, Connection) => {
|
||||||
vec![
|
vec![
|
||||||
(wall.clone(), pos),
|
(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
|
// hallway vertical
|
||||||
(Connection, Closed, Connection, Closed) => {
|
(Connection, Closed, Connection, Closed) => {
|
||||||
vec![
|
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
|
// dead ends
|
||||||
(Connection, Closed, Closed, Closed) => {
|
(Connection, Closed, Closed, Closed) => {
|
||||||
vec![
|
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(),
|
||||||
(wall.clone(), pos.with_rotation(Quat::from_rotation_y(270.0_f32.to_radians())))
|
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) => {
|
(Closed, Closed, Connection, Closed) => {
|
||||||
vec![
|
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(),
|
||||||
(wall.clone(), pos.with_rotation(Quat::from_rotation_y(270.0_f32.to_radians())))
|
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) => {
|
(Closed, Connection, Closed, Closed) => {
|
||||||
vec![
|
vec![
|
||||||
(wall.clone(), pos),
|
(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) => {
|
(Closed, Closed, Closed, Connection) => {
|
||||||
vec![
|
vec![
|
||||||
(wall.clone(), pos),
|
(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
|
// T hallways
|
||||||
(Closed, Connection, Connection, Connection) => {
|
(Closed, Connection, Connection, Connection) => {
|
||||||
vec![
|
vec![
|
||||||
(wall.clone(), pos),
|
(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) => {
|
(Connection, Closed, Connection, Connection) => {
|
||||||
vec![
|
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) => {
|
(Connection, Connection, Closed, Connection) => {
|
||||||
vec![
|
vec![
|
||||||
(round_hole.clone(), pos),
|
(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) => {
|
(Connection, Connection, Connection, Closed) => {
|
||||||
vec![
|
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
|
// fourway
|
||||||
(Connection, Connection, Connection, Connection) => {
|
(Connection, Connection, Connection, Connection) => {
|
||||||
vec![
|
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(),
|
||||||
(corner_inside.clone(), pos.with_rotation(Quat::from_rotation_y(180.0_f32.to_radians()))),
|
pos.with_rotation(Quat::from_rotation_y(0.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(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
|
// corners
|
||||||
(Connection, Connection, Closed, Closed) => {
|
(Connection, Connection, Closed, Closed) => {
|
||||||
vec![
|
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()))),
|
corner_outside.clone(),
|
||||||
]
|
pos.with_rotation(Quat::from_rotation_y(90.0_f32.to_radians())),
|
||||||
},
|
),
|
||||||
(Closed, Connection, Connection, Closed) => {
|
(
|
||||||
vec![
|
corner_inside.clone(),
|
||||||
(corner_outside.clone(), pos.with_rotation(Quat::from_rotation_y(0.0_f32.to_radians()))),
|
pos.with_rotation(Quat::from_rotation_y(90.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![]
|
(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 {
|
for ((scene_root, colliders), pos) in values {
|
||||||
commands.spawn((
|
commands
|
||||||
RigidBody::Fixed,
|
.spawn((RigidBody::Fixed, scene_root, pos))
|
||||||
scene_root,
|
.with_children(|parent| {
|
||||||
pos,
|
|
||||||
)).with_children(|parent| {
|
|
||||||
for (collider, transform) in colliders {
|
for (collider, transform) in colliders {
|
||||||
parent.spawn((collider, transform));
|
parent.spawn((collider, transform));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let (x,z) = level.end_node;
|
let (x, z) = level.end_node;
|
||||||
commands.spawn((
|
commands.spawn((
|
||||||
Mesh3d(meshes.add(Cuboid::new(1.0, 20.0, 1.0))),
|
Mesh3d(meshes.add(Cuboid::new(1.0, 20.0, 1.0))),
|
||||||
MeshMaterial3d(materials.add(Color::srgb_u8(255, 0, 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> {
|
fn create_levels(n: i32) -> Vec<GameLevel> {
|
||||||
let mut maps = Vec::new();
|
let mut maps = Vec::new();
|
||||||
let mut initial_node = LevelNode::new();
|
let mut initial_node = LevelNode::new();
|
||||||
@@ -274,7 +361,7 @@ fn create_levels(n: i32) -> Vec<GameLevel> {
|
|||||||
|
|
||||||
maps.push(map);
|
maps.push(map);
|
||||||
|
|
||||||
for _ in 0..n-1 {
|
for _ in 0..n - 1 {
|
||||||
let map = maps.last().unwrap();
|
let map = maps.last().unwrap();
|
||||||
let mut pos = map.end_node.clone();
|
let mut pos = map.end_node.clone();
|
||||||
|
|
||||||
@@ -330,21 +417,26 @@ impl LevelNode {
|
|||||||
|
|
||||||
#[derive(Resource)]
|
#[derive(Resource)]
|
||||||
struct GameLevels {
|
struct GameLevels {
|
||||||
pub levels: Vec<GameLevel>
|
pub levels: Vec<GameLevel>,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct GameLevel {
|
struct GameLevel {
|
||||||
nodes: HashMap<(i32, i32), LevelNode>,
|
nodes: HashMap<(i32, i32), LevelNode>,
|
||||||
end_node: (i32, i32),
|
end_node: (i32, i32),
|
||||||
grid_size: i32,
|
grid_size: i32,
|
||||||
initial_point: (i32, i32)
|
initial_point: (i32, i32),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl GameLevel {
|
impl GameLevel {
|
||||||
fn new(initial_point: (i32, i32), node: LevelNode, grid_size: i32) -> Self {
|
fn new(initial_point: (i32, i32), node: LevelNode, grid_size: i32) -> Self {
|
||||||
let mut nodes = HashMap::new();
|
let mut nodes = HashMap::new();
|
||||||
nodes.insert(initial_point, node);
|
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.generate_map();
|
||||||
m
|
m
|
||||||
}
|
}
|
||||||
@@ -374,22 +466,19 @@ impl GameLevel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn ensure_connection(&self, node: &mut LevelNode, (x, y): (i32, i32)) {
|
fn ensure_connection(&self, node: &mut LevelNode, (x, y): (i32, i32)) {
|
||||||
let am_connections = (node.north == Side::Connection) as u8 +
|
let am_connections = (node.north == Side::Connection) as u8
|
||||||
(node.south == Side::Connection) as u8 +
|
+ (node.south == Side::Connection) as u8
|
||||||
(node.east == Side::Connection) as u8 +
|
+ (node.east == Side::Connection) as u8
|
||||||
(node.west == Side::Connection) as u8;
|
+ (node.west == Side::Connection) as u8;
|
||||||
|
|
||||||
if am_connections <= 2 {
|
if am_connections <= 2 {
|
||||||
if node.north != Side::Connection && !self.nodes.contains_key(&(x, y + 1)) {
|
if node.north != Side::Connection && !self.nodes.contains_key(&(x, y + 1)) {
|
||||||
node.north = Side::Connection
|
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
|
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
|
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
|
node.west = Side::Connection
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -442,8 +531,7 @@ impl GameLevel {
|
|||||||
let end_node = self.nodes.get_mut(&self.end_node).unwrap();
|
let end_node = self.nodes.get_mut(&self.end_node).unwrap();
|
||||||
if self.end_node.1 >= self.end_node.0 {
|
if self.end_node.1 >= self.end_node.0 {
|
||||||
end_node.north = Side::Connection;
|
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;
|
end_node.east = Side::Connection;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -475,6 +563,7 @@ impl GameLevel {
|
|||||||
|
|
||||||
fn spawn_objects(
|
fn spawn_objects(
|
||||||
mut commands: Commands,
|
mut commands: Commands,
|
||||||
|
levels: Res<GameLevels>,
|
||||||
models: Res<Assets<Gltf>>,
|
models: Res<Assets<Gltf>>,
|
||||||
gltf_assets: Res<GltfAssets>,
|
gltf_assets: Res<GltfAssets>,
|
||||||
image_assets: Res<ImageAssets>,
|
image_assets: Res<ImageAssets>,
|
||||||
@@ -483,12 +572,29 @@ fn spawn_objects(
|
|||||||
let card = models.get(&gltf_assets.card).unwrap();
|
let card = models.get(&gltf_assets.card).unwrap();
|
||||||
let asset = card.default_scene.as_ref().unwrap();
|
let asset = card.default_scene.as_ref().unwrap();
|
||||||
|
|
||||||
|
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
|
commands
|
||||||
.spawn((
|
.spawn((
|
||||||
Transform::from_xyz(0.0, 2.0, 2.0),
|
transform,
|
||||||
Interact,
|
Interact,
|
||||||
RigidBody::Dynamic,
|
RigidBody::Dynamic,
|
||||||
Name::new("Id Card 1"),
|
Name::new(format!("Id Card {i}")),
|
||||||
Visibility::Visible,
|
Visibility::Visible,
|
||||||
ItemIcon::new(image_assets.id_card.clone()),
|
ItemIcon::new(image_assets.id_card.clone()),
|
||||||
SceneRoot(asset.clone()),
|
SceneRoot(asset.clone()),
|
||||||
@@ -511,58 +617,71 @@ fn spawn_objects(
|
|||||||
Sensor,
|
Sensor,
|
||||||
));
|
));
|
||||||
});
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Component)]
|
||||||
|
pub struct Door {
|
||||||
|
pub is_open: bool,
|
||||||
|
pub open_direction: (i32, i32),
|
||||||
|
pub position: (i32, i32)
|
||||||
|
}
|
||||||
|
|
||||||
fn spawn_doors(
|
fn spawn_doors(
|
||||||
mut commands: Commands,
|
mut commands: Commands,
|
||||||
levels: Res<GameLevels>,
|
levels: Res<GameLevels>,
|
||||||
models: Res<Assets<Gltf>>,
|
models: Res<Assets<Gltf>>,
|
||||||
gltf_assets: Res<GltfAssets>
|
gltf_assets: Res<GltfAssets>,
|
||||||
){
|
) {
|
||||||
let collider: Vec<(Collider, Transform)> = vec![(
|
let collider: Vec<(Collider, Transform)> = vec![(
|
||||||
Collider::cuboid(1.0, 1.0, 0.1),
|
Collider::cuboid(1.0, 1.0, 0.1),
|
||||||
Transform::from_xyz(0.0, 1.0, -1.0),
|
Transform::from_xyz(0.0, 1.0, -1.0),
|
||||||
)];
|
)];
|
||||||
let path = format!("meshes/library/space_round_door.glb", );
|
let path = format!("meshes/library/space_round_door.glb",);
|
||||||
let handle = gltf_assets
|
let handle = gltf_assets.library.get(&path).unwrap();
|
||||||
.library
|
let gltf = models.get(handle).unwrap();
|
||||||
.get(&path)
|
|
||||||
.unwrap();
|
|
||||||
let gltf = models
|
|
||||||
.get(handle)
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let asset = gltf
|
let asset = gltf.default_scene.as_ref().unwrap();
|
||||||
.default_scene
|
|
||||||
.as_ref()
|
|
||||||
.unwrap();
|
|
||||||
let scene_root = SceneRoot(asset.clone());
|
let scene_root = SceneRoot(asset.clone());
|
||||||
|
|
||||||
|
|
||||||
for level in levels.levels.iter() {
|
for level in levels.levels.iter() {
|
||||||
let (x, z) = level.end_node;
|
let (x, z) = level.end_node;
|
||||||
if x <= z {
|
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 {
|
||||||
|
(
|
||||||
|
(1, 0),
|
||||||
|
Transform::from_xyz(2.0 * x as f32, 0.0, -2.0 * z as f32)
|
||||||
|
)
|
||||||
|
};
|
||||||
commands.spawn((
|
commands.spawn((
|
||||||
RigidBody::Fixed,
|
RigidBody::Fixed,
|
||||||
Transform::from_xyz(2.0 * x as f32, 0.0, -2.0 * z as f32)
|
Door {
|
||||||
.with_rotation(Quat::from_rotation_y(90.0_f32.to_radians())),
|
is_open: false,
|
||||||
|
open_direction: direction,
|
||||||
|
position: (x, z)
|
||||||
|
},
|
||||||
|
transform,
|
||||||
scene_root.clone(),
|
scene_root.clone(),
|
||||||
)).with_children(|parent| {
|
)).with_children(|parent| {
|
||||||
for (collider, transform) in collider.clone() {
|
for (collider, transform) in collider.clone() {
|
||||||
parent.spawn((collider, transform));
|
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));
|
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -242,6 +242,7 @@ pub(crate) enum PlayerAction {
|
|||||||
Sprint,
|
Sprint,
|
||||||
Jump,
|
Jump,
|
||||||
ToggleFlashlight,
|
ToggleFlashlight,
|
||||||
|
OpenDoor,
|
||||||
// Objects and stuff
|
// Objects and stuff
|
||||||
PickUp,
|
PickUp,
|
||||||
Drop,
|
Drop,
|
||||||
@@ -290,6 +291,9 @@ pub fn handle_input(
|
|||||||
if keyboard_input.just_pressed(KeyCode::KeyF) {
|
if keyboard_input.just_pressed(KeyCode::KeyF) {
|
||||||
*action = PlayerAction::ToggleFlashlight;
|
*action = PlayerAction::ToggleFlashlight;
|
||||||
}
|
}
|
||||||
|
if keyboard_input.just_pressed(KeyCode::KeyK) {
|
||||||
|
*action = PlayerAction::OpenDoor;
|
||||||
|
}
|
||||||
|
|
||||||
input.movement_direction = movement_direction.normalize_or_zero();
|
input.movement_direction = movement_direction.normalize_or_zero();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,12 @@ use super::Player;
|
|||||||
#[derive(Component, Default, Debug)]
|
#[derive(Component, Default, Debug)]
|
||||||
pub struct Item(Option<Entity>);
|
pub struct Item(Option<Entity>);
|
||||||
|
|
||||||
|
impl Item {
|
||||||
|
pub fn take(&mut self) -> Option<Entity> {
|
||||||
|
self.0.take()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Component, Default, Debug)]
|
#[derive(Component, Default, Debug)]
|
||||||
pub struct ItemIcon(Handle<Image>);
|
pub struct ItemIcon(Handle<Image>);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user