Interactable hud bug fixes

This commit is contained in:
Franklin 2023-11-12 11:05:37 -04:00
parent bc90efbbc4
commit 8afa56d306
74 changed files with 1097 additions and 561 deletions

View File

@ -1,9 +1,15 @@
use bevy::prelude::*;
use bevy_rapier3d::prelude::*;
use crate::{logic::core::player::{player_movement::{
move_player, PlayerLinearXZState, PlayerLinearYState, PlayerMovementInput,
}, player_values_state::PlayerValuesState}, ui::game::settings::SettingsScreenUIConfiguration};
use crate::{
logic::core::player::{
player_movement::{
move_player, PlayerLinearXZState, PlayerLinearYState, PlayerMovementInput,
},
player_values_state::PlayerValuesState,
},
ui::game::settings::SettingsScreenUIConfiguration,
};
use super::markers::player::Player;
@ -23,7 +29,7 @@ pub fn capture_input(
>,
time: Res<Time>,
settings_screen_config: Res<SettingsScreenUIConfiguration>,
player_values_state: Res<PlayerValuesState>
player_values_state: Res<PlayerValuesState>,
) {
// Don't allocate on each frame. Instead Check if any of the inputs are being pressed and then allocate.
if keyboard_input.any_pressed([
@ -51,9 +57,19 @@ pub fn capture_input(
sprint: keyboard_input.pressed(KeyCode::ShiftLeft),
};
if settings_screen_config.settings_menu_shown {
move_player(PlayerMovementInput::default(), player_query, time, player_values_state);
move_player(
PlayerMovementInput::default(),
player_query,
time,
player_values_state,
);
} else {
move_player(player_movement_input, player_query, time, player_values_state);
move_player(
player_movement_input,
player_query,
time,
player_values_state,
);
}
}
}

View File

@ -3,4 +3,4 @@ use bevy::prelude::*;
use crate::comps::core::inventory::any_inventory::AnyInventory;
#[derive(Event)]
pub struct LootContainerEvent(pub AnyInventory);
pub struct LootContainerEvent(pub AnyInventory);

View File

@ -1,2 +1,2 @@
pub mod loot_container;
pub mod pickup_item;
pub mod pickup_item;

View File

@ -1,4 +1,4 @@
use bevy::prelude::*;
#[derive(Event)]
pub struct PickupItemEvent();
pub struct PickupItemEvent();

View File

@ -1,4 +1,3 @@
#[derive(Copy, Clone, Default, Debug, PartialEq, Eq, PartialOrd, Ord)]
pub struct UGrid {
pub width: u32,
@ -8,7 +7,10 @@ pub struct UGrid {
impl UGrid {
/// Creates a ugrid with width = size and height = size
pub fn new_square(size: u32) -> Self {
Self { width: size, height: size }
Self {
width: size,
height: size,
}
}
}
@ -16,7 +18,10 @@ impl std::ops::Add for UGrid {
type Output = UGrid;
fn add(self, rhs: Self) -> Self::Output {
Self { width: self.width + rhs.width, height: self.height + rhs.height }
Self {
width: self.width + rhs.width,
height: self.height + rhs.height,
}
}
}
@ -24,6 +29,9 @@ impl std::ops::Sub for UGrid {
type Output = UGrid;
fn sub(self, rhs: Self) -> Self::Output {
Self { width: self.width - rhs.width, height: self.height - rhs.height }
Self {
width: self.width - rhs.width,
height: self.height - rhs.height,
}
}
}

View File

@ -1,6 +1,6 @@
use bevy::ecs::component::SparseStorage;
use crate::comps::core::{items::item::Item, grid::UGrid};
use crate::comps::core::{grid::UGrid, items::item::Item};
use super::inventory_item::InventoryItem;
@ -8,19 +8,18 @@ use super::inventory_item::InventoryItem;
#[derive(Clone)]
pub struct AnyInventory {
size: UGrid,
items: Vec<InventoryItem>
items: Vec<InventoryItem>,
}
#[allow(unused)]
impl AnyInventory {
pub fn new(size: UGrid) -> Self {
Self { size, items: Vec::new() }
Self {
size,
items: Vec::new(),
}
}
pub fn add_item_at(
&mut self,
position: UGrid,
item: impl Item<Storage = SparseStorage>,
) {
pub fn add_item_at(&mut self, position: UGrid, item: impl Item<Storage = SparseStorage>) {
// Is Item bigger than inventory?
// Does position + item size exceed bounds?
if !self.valid_item_and_size_for_inventory(position, &item) {
@ -38,17 +37,23 @@ impl AnyInventory {
let spots_to_occupy = Self::get_spots_from_item_at_pos(position, item);
for inventory_item in self.items.iter() {
if inventory_item.is_in_range(&spots_to_occupy) {
return false
return false;
}
}
true
}
pub fn get_spots_from_item_at_pos(position: UGrid, item: &impl Item<Storage = SparseStorage>) -> Vec<UGrid> {
pub fn get_spots_from_item_at_pos(
position: UGrid,
item: &impl Item<Storage = SparseStorage>,
) -> Vec<UGrid> {
let end_position = position + item.inventory_size();
let mut spots = Vec::new();
for pos_width in position.width..end_position.width {
for pos_height in position.height..end_position.height {
spots.push(UGrid { width: pos_width, height: pos_height });
spots.push(UGrid {
width: pos_width,
height: pos_height,
});
}
}
spots
@ -61,4 +66,4 @@ impl AnyInventory {
let item_bounds = position + item.inventory_size();
!(item_bounds.width > self.size.width || item_bounds.height > self.size.height)
}
}
}

View File

@ -4,7 +4,6 @@ use bevy::ecs::component::SparseStorage;
use crate::comps::core::{grid::UGrid, items::item::Item};
#[derive(Clone)]
pub struct InventoryItem {
item: Arc<dyn Item<Storage = SparseStorage>>,
@ -21,21 +20,22 @@ impl InventoryItem {
pub fn rotated(&self) -> Option<bool> {
self.rotated
}
pub fn new(
item: impl Item<Storage = SparseStorage>,
occupied_spots: Vec<UGrid>,
) -> Self {
pub fn new(item: impl Item<Storage = SparseStorage>, occupied_spots: Vec<UGrid>) -> Self {
let size = item.inventory_size();
let rotated = item.inventory_rotatable().then(|| false);
Self { item: Arc::new(item), occupied_spots, rotated }
Self {
item: Arc::new(item),
occupied_spots,
rotated,
}
}
/// Returns true if there is overlap between both
pub fn is_in_range(&self, spots_to_occupy: &Vec<UGrid>) -> bool {
for occupied_spot in self.occupied_spots.iter() {
if spots_to_occupy.contains(occupied_spot) {
return true
return true;
}
}
false
}
}
}

View File

@ -1,6 +1,6 @@
use std::sync::Arc;
use bevy::{prelude::*, ecs::component::SparseStorage};
use bevy::{ecs::component::SparseStorage, prelude::*};
use crate::comps::core::items::item::Item;
@ -9,4 +9,4 @@ use crate::comps::core::items::item::Item;
#[derive(Component, Clone, Default)]
pub struct ItemInventory {
pub item: Option<Arc<dyn Item<Storage = SparseStorage>>>,
}
}

View File

@ -1,4 +1,4 @@
pub mod any_inventory;
pub mod inventory_item;
pub mod item_inventory;
pub mod player_inventory;
pub mod player_inventory;

View File

@ -2,7 +2,7 @@ use bevy::prelude::*;
use crate::comps::core::grid::UGrid;
use super::{item_inventory::ItemInventory, any_inventory::AnyInventory};
use super::{any_inventory::AnyInventory, item_inventory::ItemInventory};
#[derive(Component)]
pub struct PlayerInventory {
@ -13,6 +13,10 @@ pub struct PlayerInventory {
impl Default for PlayerInventory {
fn default() -> Self {
Self { primary: Default::default(), secondary: Default::default(), backpack: AnyInventory::new(UGrid::new_square(10)) }
Self {
primary: Default::default(),
secondary: Default::default(),
backpack: AnyInventory::new(UGrid::new_square(10)),
}
}
}
}

View File

@ -0,0 +1,46 @@
use bevy::prelude::*;
use crate::{
comps::core::{
grid::UGrid,
items::item::{Item, ItemType},
markers::holdable::HoldableObjectType,
},
logic::core::guns::firearm::Firearm,
};
#[derive(Component)]
pub struct M4a1GunItem;
impl Item for M4a1GunItem {
fn get_type(&self) -> ItemType {
ItemType::Holdable(HoldableObjectType::Firearm(Firearm::M4A1))
}
fn asset_path(&self) -> &str {
"weapons/m4a1_rifle.glb"
}
fn stackable(&self) -> Option<u32> {
None
}
fn inventory_size(&self) -> crate::comps::core::grid::UGrid {
UGrid {
width: 4,
height: 2,
}
}
fn inventory_rotatable(&self) -> bool {
true
}
fn inventory_title(&self) -> String {
String::from("M4A1 Rifle")
}
fn inventory_description(&self) -> String {
String::from("Rifle chambered in 5.56x45mm NATO, shoots 800 rounds per minute.")
}
}

View File

@ -0,0 +1 @@
pub mod m4a1;

View File

@ -1,16 +1,22 @@
use bevy::prelude::*;
use crate::comps::core::grid::UGrid;
use crate::{
comps::core::{
grid::UGrid,
markers::{firearm::FirearmData, holdable::HoldableObjectType, interactable::Interactable},
},
setup::assets::{GltfAssetType, GltfAssets},
utils,
};
use bevy::{gltf::Gltf, prelude::*};
use bevy_rapier3d::prelude::*;
#[allow(unused)]
pub enum ItemType {
Holdable,
Holdable(HoldableObjectType),
Equippable,
Consumable,
}
pub trait Item: Component {
pub trait Item: Component {
fn get_type(&self) -> ItemType;
fn asset_path(&self) -> &str;
/// Optional Stackable. If value is Some(x) x is the max quantity per stack
@ -18,4 +24,72 @@ pub trait Item: Component {
fn inventory_size(&self) -> UGrid;
fn inventory_rotatable(&self) -> bool;
fn inventory_title(&self) -> String;
}
fn inventory_description(&self) -> String;
fn spawn(
&self,
commands: &mut Commands,
transform: Transform,
assets_gltf: &GltfAssets,
loaded_gltf_assets: &Assets<Gltf>,
) {
match self.get_type() {
ItemType::Holdable(object_type) => {
match object_type {
HoldableObjectType::Firearm(firearm) => {
if let Some(asset_handle) = assets_gltf.assets.iter().find(|asset| {
asset.asset_type == GltfAssetType::Firearm(firearm.clone())
}) {
if let Some(gltf) = loaded_gltf_assets.get(&asset_handle.asset) {
let firearm_data: FirearmData = firearm.firearm_data();
let mut firearm_transform = Transform::from_xyz(0.0, 0.0, 0.0);
firearm_transform.rotate_local_y(
utils::rad_deg::radians_from_degrees(
firearm.holdable_object_data().y_rot,
),
);
firearm_transform.scale =
firearm_transform.scale * firearm_data.scale_factor;
let scene = gltf.scenes[0].clone();
let firearm_asset_entity = commands
.spawn((
SceneBundle {
scene,
visibility: Visibility::Inherited,
transform: firearm_transform,
..default()
},
Name::new(format!(
"{} Item Gltf Asset",
self.inventory_title()
)),
))
.id();
commands
.spawn((
firearm.holdable_object_data(),
Name::new(format!("{} Item", self.inventory_title())),
TransformBundle {
local: transform,
..Default::default()
},
VisibilityBundle {
visibility: Visibility::Visible,
..Default::default()
},
RigidBody::Dynamic,
Collider::cuboid(5.0, 5.0, 5.0),
Interactable::Item,
))
.push_children(&[firearm_asset_entity]);
}
}
}
};
}
ItemType::Equippable => todo!(),
ItemType::Consumable => todo!(),
};
}
}

View File

@ -1 +1,2 @@
pub mod item;
pub mod guns;
pub mod item;

View File

@ -1,11 +1,14 @@
use bevy::{prelude::{Component, Vec3}, reflect::Reflect, time::Timer};
use bevy::{
prelude::{Component, Vec3},
reflect::Reflect,
time::Timer,
};
use crate::logic::core::guns::caliber::Caliber;
#[derive(Component, Reflect)]
pub struct BulletMarker {
pub caliber: Caliber,
pub starting_point: Vec3,
pub timer: Timer,
}
}

View File

@ -1,4 +1,7 @@
use bevy::{prelude::{Component, Quat, Vec3}, reflect::Reflect};
use bevy::{
prelude::{Component, Quat, Vec3},
reflect::Reflect,
};
use crate::logic::core::guns::{caliber::Caliber, spray_pattern::FirearmSprayPattern};
@ -46,4 +49,4 @@ pub struct FirearmData {
pub struct MagazineData {
pub rounds_shot: usize,
pub max_capacity: usize,
}
}

View File

@ -1,5 +1,7 @@
use bevy::prelude::*;
use crate::logic::core::guns::firearm::Firearm;
/// Anything that can go in the player's hands.
#[derive(Component, Default, Debug, Reflect)]
pub struct HoldableObjectData {
@ -11,3 +13,8 @@ pub struct HoldableObjectData {
#[derive(Component, Reflect)]
pub struct InPlayerHands;
#[derive(Reflect)]
pub enum HoldableObjectType {
Firearm(Firearm),
}

View File

@ -20,4 +20,4 @@ impl Display for Interactable {
Interactable::Item => write!(f, "Item"),
}
}
}
}

View File

@ -1,7 +1,7 @@
pub mod bullet;
pub mod camera;
pub mod firearm;
pub mod holdable;
pub mod player;
pub mod interactable;
pub mod muzzle_flash;
pub mod bullet;
pub mod interactable;
pub mod player;

View File

@ -1,4 +1,4 @@
use bevy::{prelude::Component, time::Timer};
#[derive(Component)]
pub struct MuzzleFlashMarker(pub Timer);
pub struct MuzzleFlashMarker(pub Timer);

View File

@ -10,4 +10,4 @@ pub struct PlayerData {
pub struct Player(pub PlayerData);
#[derive(Component, Reflect)]
pub struct PlayerHand;
pub struct PlayerHand;

View File

@ -1,6 +1,6 @@
pub mod controller;
pub mod markers;
pub mod grid;
pub mod events;
pub mod grid;
pub mod inventory;
pub mod items;
pub mod items;
pub mod markers;

View File

@ -0,0 +1 @@

View File

@ -0,0 +1 @@

View File

@ -49,4 +49,4 @@ impl Caliber {
Caliber::Parabellum9mm => 0.05,
}
}
}
}

View File

@ -1,8 +1,12 @@
use crate::comps::core::markers::{bullet::BulletMarker, muzzle_flash::MuzzleFlashMarker};
use bevy::prelude::*;
use bevy_rapier3d::prelude::*;
use crate::comps::core::markers::{muzzle_flash::MuzzleFlashMarker, bullet::BulletMarker};
pub fn despawn_muzzle_flashes(mut commands: Commands, mut query: Query<(&mut MuzzleFlashMarker, Entity)>, time: Res<Time>) {
pub fn despawn_muzzle_flashes(
mut commands: Commands,
mut query: Query<(&mut MuzzleFlashMarker, Entity)>,
time: Res<Time>,
) {
for (mut muzzle_flash, entity) in query.iter_mut() {
muzzle_flash.0.tick(time.delta());
if muzzle_flash.0.finished() {
@ -26,28 +30,41 @@ pub fn despawn_stray_bullets(
for event in collisions_read.iter() {
match event {
CollisionEvent::Started(entity_a, entity_b, _) => {
if entity_a == entity_b { // Avoid inner collisions
if entity_a == entity_b {
// Avoid inner collisions
continue;
}
if entity_a == &bullet_entity || entity_b == &bullet_entity{
if entity_a == &bullet_entity || entity_b == &bullet_entity {
commands.entity(bullet_entity).remove::<Collider>();
//commands.entity(bullet_entity).insert(Sensor);
spawn_bullet_hit_marker(&mut commands, transform.translation, &mut meshes, &mut materials);
}
},
CollisionEvent::Stopped(entity_a, entity_b, _) => {
if entity_a == entity_b { // Avoid inner collisions
continue;
}
if entity_a == &bullet_entity || entity_b == &bullet_entity{
commands.entity(bullet_entity).insert(Collider::ball(bullet.caliber.size()));
//commands.entity(bullet_entity).remove::<Sensor>();
//commands.entity(*entity_b).despawn();
spawn_bullet_exit_marker(&mut commands, transform.translation, &mut meshes, &mut materials);
continue;
spawn_bullet_hit_marker(
&mut commands,
transform.translation,
&mut meshes,
&mut materials,
);
}
}
//_ => {}
CollisionEvent::Stopped(entity_a, entity_b, _) => {
if entity_a == entity_b {
// Avoid inner collisions
continue;
}
if entity_a == &bullet_entity || entity_b == &bullet_entity {
commands
.entity(bullet_entity)
.insert(Collider::ball(bullet.caliber.size()));
//commands.entity(bullet_entity).remove::<Sensor>();
//commands.entity(*entity_b).despawn();
spawn_bullet_exit_marker(
&mut commands,
transform.translation,
&mut meshes,
&mut materials,
);
continue;
}
} //_ => {}
}
}
if bullet.timer.finished() {
@ -65,27 +82,27 @@ fn spawn_bullet_hit_marker(
meshes: &mut ResMut<Assets<Mesh>>,
materials: &mut ResMut<Assets<StandardMaterial>>,
) {
commands.spawn(
(
MaterialMeshBundle {
mesh: {
meshes.add(
shape::UVSphere { radius: 0.05, sectors: 36, stacks: 18 }.into()
)
},
material: materials.add(StandardMaterial {
base_color: Color::GREEN,
//base_color_texture: Some(Color::GREEN),
emissive: Color::GREEN,
..Default::default()
}),
visibility: Visibility::Visible,
transform: Transform::from_translation(at),
..Default::default()
},
)
);
commands.spawn((MaterialMeshBundle {
mesh: {
meshes.add(
shape::UVSphere {
radius: 0.05,
sectors: 36,
stacks: 18,
}
.into(),
)
},
material: materials.add(StandardMaterial {
base_color: Color::GREEN,
//base_color_texture: Some(Color::GREEN),
emissive: Color::GREEN,
..Default::default()
}),
visibility: Visibility::Visible,
transform: Transform::from_translation(at),
..Default::default()
},));
}
fn spawn_bullet_exit_marker(
@ -94,25 +111,25 @@ fn spawn_bullet_exit_marker(
meshes: &mut ResMut<Assets<Mesh>>,
materials: &mut ResMut<Assets<StandardMaterial>>,
) {
commands.spawn(
(
MaterialMeshBundle {
mesh: {
meshes.add(
shape::UVSphere { radius: 0.05, sectors: 36, stacks: 18 }.into()
)
},
material: materials.add(StandardMaterial {
base_color: Color::RED,
//base_color_texture: Some(Color::GREEN),
emissive: Color::RED,
..Default::default()
}),
visibility: Visibility::Visible,
transform: Transform::from_translation(at),
..Default::default()
},
)
);
}
commands.spawn((MaterialMeshBundle {
mesh: {
meshes.add(
shape::UVSphere {
radius: 0.05,
sectors: 36,
stacks: 18,
}
.into(),
)
},
material: materials.add(StandardMaterial {
base_color: Color::RED,
//base_color_texture: Some(Color::GREEN),
emissive: Color::RED,
..Default::default()
}),
visibility: Visibility::Visible,
transform: Transform::from_translation(at),
..Default::default()
},));
}

View File

@ -1,4 +1,4 @@
use bevy::prelude::*;
#[derive(Event)]
pub struct SpawnFirearmEvent();
pub struct SpawnFirearmEvent();

View File

@ -1,4 +1,7 @@
use crate::comps::core::markers::{firearm::{FirearmData, FiringPoint}, holdable::HoldableObjectData};
use crate::comps::core::markers::{
firearm::{FirearmData, FiringPoint},
holdable::HoldableObjectData,
};
use bevy::prelude::*;
use super::{caliber::Caliber, spray_pattern::FirearmSprayPattern};
@ -27,13 +30,13 @@ impl Firearm {
horizontal_recoil_modifier: 0.5,
recoil_pattern: FirearmSprayPattern {
vertical: Vec::from([
1.0, 1.2, 1.3, 1.6, 1.5, 1.7, 1.5, 1.5, 1.5, 2.0 // 10 for now
1.0, 1.2, 1.3, 1.6, 1.5, 1.7, 1.5, 1.5, 1.5, 2.0, // 10 for now
]),
horizontal: Vec::from([
1.0, 1.2, 1.3, -1.6, 1.5, -1.7, -1.5, 1.5, -1.5, 2.0 // 10 for now
1.0, 1.2, 1.3, -1.6, 1.5, -1.7, -1.5, 1.5, -1.5, 2.0, // 10 for now
]),
},
final_aimed_rotation: Quat::from_rotation_x(0.026),
final_rotation: Quat::default(),
final_aimed_position: Vec3 {
@ -52,7 +55,7 @@ impl Firearm {
scale_factor: 1.0,
asset_path: String::from("weapons/m4a1_rifle.glb"),
}
},
}
Firearm::Glock17 => {
FirearmData {
firing_point: FiringPoint {
@ -68,13 +71,13 @@ impl Firearm {
horizontal_recoil_modifier: 1.0,
recoil_pattern: FirearmSprayPattern {
vertical: Vec::from([
1.0, 1.2, 1.3, 1.6, 1.5, 1.7, 1.5, 1.5, 1.5, 2.0 // 10 for now
1.0, 1.2, 1.3, 1.6, 1.5, 1.7, 1.5, 1.5, 1.5, 2.0, // 10 for now
]),
horizontal: Vec::from([
1.0, 1.2, 1.3, -1.6, 1.5, -1.7, -1.5, 1.5, -1.5, 2.0 // 10 for now
1.0, 1.2, 1.3, -1.6, 1.5, -1.7, -1.5, 1.5, -1.5, 2.0, // 10 for now
]),
},
final_aimed_rotation: Quat::from_rotation_x(0.026),
final_rotation: Quat::default(),
final_aimed_position: Vec3 {
@ -93,7 +96,7 @@ impl Firearm {
scale_factor: 0.25,
asset_path: String::from("weapons/glock_17_pistol.glb"),
}
},
}
}
}
pub fn holdable_object_data(&self) -> HoldableObjectData {

View File

@ -1,7 +1,7 @@
pub mod caliber;
pub mod despawn_shots;
pub mod equip_firearm;
pub mod firearm;
pub mod player_firing;
pub mod spray_pattern;
pub mod equip_firearm;
pub mod shoot;
pub mod despawn_shots;
pub mod spray_pattern;

View File

@ -3,7 +3,7 @@ use std::time::Duration;
use bevy::prelude::*;
use bevy_rapier3d::prelude::*;
use crate::comps::core::markers::{muzzle_flash::MuzzleFlashMarker, bullet::BulletMarker};
use crate::comps::core::markers::{bullet::BulletMarker, muzzle_flash::MuzzleFlashMarker};
use super::caliber::Caliber;
@ -14,14 +14,19 @@ pub fn shoot_bullet(
firing_point: Transform,
forward: Vec3,
up: Vec3,
caliber: Caliber
caliber: Caliber,
) {
// Spawn muzzle flash LIGHT
commands.spawn(
(PointLightBundle {
commands.spawn((
PointLightBundle {
point_light: PointLight {
//RGB 252, 238, 128
color: Color::Rgba { red: 252., green: 238., blue: 128., alpha: 0.5 },
color: Color::Rgba {
red: 252.,
green: 238.,
blue: 128.,
alpha: 0.5,
},
intensity: 0.005,
range: 50.0,
shadows_enabled: true,
@ -30,8 +35,9 @@ pub fn shoot_bullet(
transform: firing_point,
visibility: Visibility::Visible,
..Default::default()
}, MuzzleFlashMarker(Timer::new(Duration::from_millis(10), TimerMode::Once)))
);
},
MuzzleFlashMarker(Timer::new(Duration::from_millis(10), TimerMode::Once)),
));
// Spawn Line
/*commands.spawn(
MaterialMeshBundle {
@ -50,7 +56,15 @@ pub fn shoot_bullet(
}
);*/
spawn_bullet(commands, meshes, materials, firing_point, forward, up, caliber);
spawn_bullet(
commands,
meshes,
materials,
firing_point,
forward,
up,
caliber,
);
}
pub fn spawn_bullet(
@ -60,45 +74,56 @@ pub fn spawn_bullet(
firing_point: Transform,
forward: Vec3,
_up: Vec3,
caliber: Caliber
caliber: Caliber,
) {
commands.spawn(
(
Name::new("Bullet"),
BulletMarker {
caliber: caliber.clone(),
starting_point: firing_point.translation,
timer: Timer::new(Duration::from_secs_f32(caliber.max_airtime_secs()), TimerMode::Once)
commands.spawn((
Name::new("Bullet"),
BulletMarker {
caliber: caliber.clone(),
starting_point: firing_point.translation,
timer: Timer::new(
Duration::from_secs_f32(caliber.max_airtime_secs()),
TimerMode::Once,
),
},
MaterialMeshBundle {
mesh: {
meshes.add(
shape::UVSphere {
radius: caliber.size(),
sectors: 36,
stacks: 18,
}
.into(),
)
},
MaterialMeshBundle {
mesh: {
meshes.add(
shape::UVSphere { radius: caliber.size(), sectors: 36, stacks: 18 }.into()
)
material: materials.add(StandardMaterial {
base_color: Color::Rgba {
red: 253.,
green: 207.,
blue: 88.,
alpha: 1.0,
},
material: materials.add(StandardMaterial {
base_color: Color::Rgba { red: 253., green: 207., blue: 88., alpha: 1.0 },
..Default::default()
}),
visibility: Visibility::Visible,
transform: firing_point,
..Default::default()
},
RigidBody::Dynamic,
GravityScale(4.0),
Collider::ball(caliber.size()),
Velocity::zero(),
Damping {
linear_damping: caliber.linear_damping(),
angular_damping: caliber.angular_damping(),
},
ColliderMassProperties::Mass(caliber.mass()),
ExternalImpulse {
impulse: forward * caliber.impulse(),
torque_impulse: Vec3::ZERO,
},
ActiveEvents::COLLISION_EVENTS,
Ccd::enabled()
)
);
}
}),
visibility: Visibility::Visible,
transform: firing_point,
..Default::default()
},
RigidBody::Dynamic,
GravityScale(4.0),
Collider::ball(caliber.size()),
Velocity::zero(),
Damping {
linear_damping: caliber.linear_damping(),
angular_damping: caliber.angular_damping(),
},
ColliderMassProperties::Mass(caliber.mass()),
ExternalImpulse {
impulse: forward * caliber.impulse(),
torque_impulse: Vec3::ZERO,
},
ActiveEvents::COLLISION_EVENTS,
Ccd::enabled(),
));
}

View File

@ -1,7 +1,5 @@
use bevy::reflect::Reflect;
#[derive(Clone, Reflect)]
pub struct FirearmSprayPattern {
pub vertical: Vec<f32>,

View File

@ -1,2 +1,2 @@
pub mod guns;
pub mod player;
pub mod player;

View File

@ -0,0 +1 @@

View File

@ -3,7 +3,8 @@ use bevy::{input::mouse::MouseMotion, prelude::*, window::CursorGrabMode};
use crate::{
comps::core::markers::{camera::MainCamera, player::Player},
utils::rad_deg::radians_from_degrees, ui::game::settings::SettingsScreenUIConfiguration,
ui::game::settings::SettingsScreenUIConfiguration,
utils::rad_deg::radians_from_degrees,
};
use super::{player_movement::PlayerLinearXZState, player_values_state::PlayerValuesState};
@ -80,11 +81,13 @@ pub fn follow_cursor_with_camera(
) {
if let Ok(mut window) = primary_window.get_single_mut() {
if keyboard_input.just_pressed(KeyCode::Escape) {
if settings_screen_config.settings_menu_shown { // Hide settings screen & Capture Cursor
if settings_screen_config.settings_menu_shown {
// Hide settings screen & Capture Cursor
settings_screen_config.settings_menu_shown = false;
window.cursor.grab_mode = CursorGrabMode::Locked; // use `Locked` mode to keep the cursor in one place
window.cursor.visible = false; // also hide the cursor
} else { // Show Settings screen & Release Cursor
} else {
// Show Settings screen & Release Cursor
settings_screen_config.settings_menu_shown = true;
window.cursor.grab_mode = CursorGrabMode::None; // Release cursor
window.cursor.visible = true; // Show cursor
@ -112,14 +115,23 @@ pub fn follow_cursor_with_camera(
for motion in motions.read() {
let window_scale = window.height().min(window.width());
if btn.pressed(MouseButton::Right) {
pitch -= ((settings.aimed_sensitivity * motion.delta.y as f64 * window_scale as f64) as f32)
pitch -= ((settings.aimed_sensitivity
* motion.delta.y as f64
* window_scale as f64) as f32)
.to_radians();
yaw -= ((settings.aimed_sensitivity * motion.delta.x as f64 * window_scale as f64) as f32)
yaw -= ((settings.aimed_sensitivity
* motion.delta.x as f64
* window_scale as f64) as f32)
.to_radians();
} else {
pitch -=
((settings.sensitivity * motion.delta.y as f64 * window_scale as f64) as f32).to_radians();
yaw -= ((settings.sensitivity * motion.delta.x as f64 * window_scale as f64) as f32).to_radians();
pitch -= ((settings.sensitivity
* motion.delta.y as f64
* window_scale as f64) as f32)
.to_radians();
yaw -=
((settings.sensitivity * motion.delta.x as f64 * window_scale as f64)
as f32)
.to_radians();
}
}
pitch = pitch.clamp(-1.54, 1.54);
@ -132,28 +144,53 @@ pub fn follow_cursor_with_camera(
let right = Vec3::new(local_z.z, camera_transform.translation.y, -local_z.x);
player_transform.rotation = desired_rotation_quat;
if keyboard_input.pressed(KeyCode::Q) {
let final_quat = Quat::from_axis_angle(Vec3::Z, radians_from_degrees(player_values_state.player_lean_angle));
camera_transform.rotation = camera_transform
.rotation
.lerp(final_quat, time.delta_seconds() / player_values_state.player_lean_time);
camera_transform.translation = camera_transform.translation.lerp(Vec3 { x: -right.x, y: camera_transform.translation.y, z: -right.z }, time.delta_seconds() / player_values_state.player_lean_time);
let final_quat = Quat::from_axis_angle(
Vec3::Z,
radians_from_degrees(player_values_state.player_lean_angle),
);
camera_transform.rotation = camera_transform.rotation.lerp(
final_quat,
time.delta_seconds() / player_values_state.player_lean_time,
);
camera_transform.translation = camera_transform.translation.lerp(
Vec3 {
x: -right.x,
y: camera_transform.translation.y,
z: -right.z,
},
time.delta_seconds() / player_values_state.player_lean_time,
);
} else if keyboard_input.pressed(KeyCode::E) {
let final_quat =
Quat::from_axis_angle(Vec3::Z, radians_from_degrees(-player_values_state.player_lean_angle));
camera_transform.rotation = camera_transform
.rotation
.lerp(final_quat, time.delta_seconds() / player_values_state.player_lean_time);
camera_transform.translation = camera_transform.translation.lerp(Vec3 { x: right.x, y: camera_transform.translation.y, z: right.z }, time.delta_seconds() / player_values_state.player_lean_time);
let final_quat = Quat::from_axis_angle(
Vec3::Z,
radians_from_degrees(-player_values_state.player_lean_angle),
);
camera_transform.rotation = camera_transform.rotation.lerp(
final_quat,
time.delta_seconds() / player_values_state.player_lean_time,
);
camera_transform.translation = camera_transform.translation.lerp(
Vec3 {
x: right.x,
y: camera_transform.translation.y,
z: right.z,
},
time.delta_seconds() / player_values_state.player_lean_time,
);
} else {
camera_transform.rotation = camera_transform
.rotation
.lerp(Quat::default(), time.delta_seconds() / player_values_state.player_lean_time);
camera_transform.rotation = camera_transform.rotation.lerp(
Quat::default(),
time.delta_seconds() / player_values_state.player_lean_time,
);
camera_transform.translation = camera_transform.translation.lerp(Vec3 {
x: 0.0,
y: camera_transform.translation.y,
z: 0.0,
}, time.delta_seconds() / player_values_state.player_lean_time);
camera_transform.translation = camera_transform.translation.lerp(
Vec3 {
x: 0.0,
y: camera_transform.translation.y,
z: 0.0,
},
time.delta_seconds() / player_values_state.player_lean_time,
);
}
}
}

View File

@ -2,8 +2,24 @@ use bevy::prelude::*;
use bevy_rapier3d::prelude::*;
use crate::{
comps::core::{markers::{firearm::{FirearmData, MagazineData}, holdable::InPlayerHands, player::{PlayerHand, Player}, camera::MainCamera, interactable::Interactable}, events::loot_container::LootContainerEvent},
logic::core::guns::{player_firing::PlayerFiringInfo, shoot::shoot_bullet, firearm::Firearm}, utils::rad_deg::radians_from_degrees, setup::{animations::AllFirearmAnimations, load_state::GameLoadState, equipment::{EquipmentChangeEvent, Equipment}}, ui::game::{settings::SettingsScreenUIConfiguration, hud::hud::HudState},
comps::core::{
events::loot_container::LootContainerEvent,
markers::{
camera::MainCamera,
firearm::{FirearmData, MagazineData},
holdable::InPlayerHands,
interactable::Interactable,
player::{Player, PlayerHand},
},
},
logic::core::guns::{firearm::Firearm, player_firing::PlayerFiringInfo, shoot::shoot_bullet},
setup::{
animations::AllFirearmAnimations,
equipment::{Equipment, EquipmentChangeEvent},
load_state::GameLoadState,
},
ui::game::{hud::hud::HudState, settings::SettingsScreenUIConfiguration},
utils::rad_deg::radians_from_degrees,
};
pub fn capture_hand_usage(
@ -24,8 +40,7 @@ pub fn capture_hand_usage(
animation_clips: Res<Assets<AnimationClip>>,
game_load_state: Res<GameLoadState>,
#[allow(unused)]
mut equipment_change_event_writer: EventWriter<EquipmentChangeEvent>,
#[allow(unused)] mut equipment_change_event_writer: EventWriter<EquipmentChangeEvent>,
settings_screen_config: Res<SettingsScreenUIConfiguration>,
mut meshes: ResMut<Assets<Mesh>>,
@ -40,18 +55,19 @@ pub fn capture_hand_usage(
// Equipping stuff
// Equipping gun
if !settings_screen_config.settings_menu_shown {
if keyboard_input.just_pressed(KeyCode::Key1) {
equipment_change_event_writer.send(EquipmentChangeEvent(Equipment::Firearm(Firearm::M4A1)));
equipment_change_event_writer
.send(EquipmentChangeEvent(Equipment::Firearm(Firearm::M4A1)));
} else if keyboard_input.just_pressed(KeyCode::Key2) {
equipment_change_event_writer.send(EquipmentChangeEvent(Equipment::Firearm(Firearm::Glock17) ));
equipment_change_event_writer
.send(EquipmentChangeEvent(Equipment::Firearm(Firearm::Glock17)));
} else if keyboard_input.just_pressed(KeyCode::Key3) {
equipment_change_event_writer.send(EquipmentChangeEvent(Equipment::Nothing ));
equipment_change_event_writer.send(EquipmentChangeEvent(Equipment::Nothing));
}
}
// Firearm stuff
if let Equipment::Firearm(player_firearm) = player_query.single().0.equipment.clone() {
for mut player_firing_info in player_firing_info_query.iter_mut() {
@ -59,11 +75,16 @@ pub fn capture_hand_usage(
for (firearm_transform, firearm_data, mut magazine_data) in firearm_query.iter_mut() {
for mut hand_transform in hand_query.iter_mut() {
if player_firing_info.is_reloading {
for animation_player in &mut animation_players {
if let Some(firearm_animations) = all_firearm_animations.animations.iter().find(|animation| &animation.firearm == &player_firearm) {
if let Some(animation_clip) = animation_clips.get(&firearm_animations.reload_magazine) {
if let Some(firearm_animations) = all_firearm_animations
.animations
.iter()
.find(|animation| &animation.firearm == &player_firearm)
{
if let Some(animation_clip) =
animation_clips.get(&firearm_animations.reload_magazine)
{
if animation_player.elapsed() >= animation_clip.duration() {
magazine_data.rounds_shot = 0;
player_firing_info.is_reloading = false;
@ -71,12 +92,20 @@ pub fn capture_hand_usage(
}
}
}
} else { // Player is not in a reload animation
if keyboard_input.just_pressed(KeyCode::R) && !settings_screen_config.settings_menu_shown{
} else {
// Player is not in a reload animation
if keyboard_input.just_pressed(KeyCode::R)
&& !settings_screen_config.settings_menu_shown
{
// Start reload animation
for mut animation_player in &mut animation_players {
if let Some(firearm_animations) = all_firearm_animations.animations.iter().find(|animation| &animation.firearm == &player_firearm) {
animation_player.start(firearm_animations.reload_magazine.clone_weak());
if let Some(firearm_animations) = all_firearm_animations
.animations
.iter()
.find(|animation| &animation.firearm == &player_firearm)
{
animation_player
.start(firearm_animations.reload_magazine.clone_weak());
player_firing_info.is_reloading = true;
}
}
@ -84,29 +113,38 @@ pub fn capture_hand_usage(
// At the end of reload animation, set magazine data to capacity = 0
}
// AIMING IN/OUT
if mouse_buttons.pressed(MouseButton::Right) && !settings_screen_config.settings_menu_shown {
if mouse_buttons.pressed(MouseButton::Right)
&& !settings_screen_config.settings_menu_shown
{
let rotation_lerp_quat = hand_transform.rotation.lerp(
firearm_data.final_aimed_rotation,
(time.delta_seconds() / firearm_data.rebound_time_seconds).clamp(0.0, 1.0),
(time.delta_seconds() / firearm_data.rebound_time_seconds)
.clamp(0.0, 1.0),
);
let position_lerp_vec3 = hand_transform.translation.lerp(
firearm_data.final_aimed_position,
(time.delta_seconds() / firearm_data.rebound_time_seconds).clamp(0.0, 1.0),
(time.delta_seconds() / firearm_data.rebound_time_seconds)
.clamp(0.0, 1.0),
);
hand_transform.rotation = rotation_lerp_quat;
hand_transform.translation = position_lerp_vec3;
} else {
hand_transform.rotation = hand_transform
.rotation
.lerp(firearm_data.final_rotation, (time.delta_seconds() / firearm_data.rebound_time_seconds).clamp(0.0, 1.0));
} else {
hand_transform.rotation = hand_transform.rotation.lerp(
firearm_data.final_rotation,
(time.delta_seconds() / firearm_data.rebound_time_seconds)
.clamp(0.0, 1.0),
);
hand_transform.translation = hand_transform.translation.lerp(
firearm_data.final_position,
(time.delta_seconds() / firearm_data.rebound_time_seconds).clamp(0.0, 1.0),
(time.delta_seconds() / firearm_data.rebound_time_seconds)
.clamp(0.0, 1.0),
);
}
// SHOOTING & RECOIL
if mouse_buttons.pressed(MouseButton::Left) && !settings_screen_config.settings_menu_shown {
if mouse_buttons.pressed(MouseButton::Left)
&& !settings_screen_config.settings_menu_shown
{
if player_firing_info.full_auto_timer.finished() {
if magazine_data.rounds_shot < magazine_data.max_capacity {
// Get recoil numbers from patterns
@ -129,10 +167,23 @@ pub fn capture_hand_usage(
let firearm_transform = firearm_transform.clone();
// TODO: M4 holdableobject data has a Y ROT of -90. Apply that rotation here if it exists.
let firing_point = firearm_transform.translation() + (firearm_transform.forward() * firearm_data.firing_point.forward) + (firearm_transform.up() * firearm_data.firing_point.up) + (firearm_transform.right() * firearm_data.firing_point.right);
let firing_point = firearm_transform.translation()
+ (firearm_transform.forward()
* firearm_data.firing_point.forward)
+ (firearm_transform.up() * firearm_data.firing_point.up)
+ (firearm_transform.right()
* firearm_data.firing_point.right);
let forward = firearm_transform.forward();
let up = firearm_transform.up();
shoot_bullet(&mut commands, &mut meshes, &mut materials, Transform::from_translation(firing_point), forward, up, firearm_data.caliber.clone());
shoot_bullet(
&mut commands,
&mut meshes,
&mut materials,
Transform::from_translation(firing_point),
forward,
up,
firearm_data.caliber.clone(),
);
// Increment indexes and timers
player_firing_info.current_round_index += 1;
player_firing_info.last_shot_timestamp = time.elapsed_seconds();
@ -140,13 +191,17 @@ pub fn capture_hand_usage(
magazine_data.rounds_shot += 1;
// Apply recoil
hand_transform
.rotate_x(radians_from_degrees(firearm_data.vertical_recoil_modifier * vertical_recoil_number));
hand_transform.rotate_y(radians_from_degrees(firearm_data.horizontal_recoil_modifier * horizontal_recoil_number));
hand_transform.rotate_x(radians_from_degrees(
firearm_data.vertical_recoil_modifier
* vertical_recoil_number,
));
hand_transform.rotate_y(radians_from_degrees(
firearm_data.horizontal_recoil_modifier
* horizontal_recoil_number,
));
} else {
//TODO: play magazine empty sound
}
}
} else {
if player_firing_info.full_auto_timer.finished() {
@ -154,19 +209,17 @@ pub fn capture_hand_usage(
}
}
}
}
}
}
}
}
/// Method that is run when player hits interact button.
/// Method that is run when player hits interact button.
/// Should raycast where the player is looking and scan for interactable
pub fn interact_action(
//mut commands: Commands,
player_query: Query<&Transform, (With<Player>, Without<MainCamera>)>,
player_query: Query<(Entity, &Transform), (With<Player>, Without<MainCamera>)>,
camera_query: Query<&GlobalTransform, (With<MainCamera>, Without<Player>)>,
interactables_query: Query<(Entity, &Interactable)>,
keyboard_input: Res<Input<KeyCode>>,
@ -174,32 +227,47 @@ pub fn interact_action(
mut hud_state: ResMut<HudState>,
mut loot_container_event_writer: EventWriter<LootContainerEvent>,
) {
for transform in player_query.iter() {
for (player_entity, transform) in player_query.iter() {
for global_transform in camera_query.iter() {
let ray_pos = global_transform.translation();
let ray_dir = transform.forward() * 2.0; // TODO: Move this into global Resource state
let max_toi = 4.0;
let solid = true;
if let Some((entity, _toi)) = rapier_context.cast_ray(
ray_pos, ray_dir, max_toi, solid, QueryFilter::only_fixed()
ray_pos,
ray_dir,
max_toi,
solid,
QueryFilter::default().exclude_collider(player_entity),
) {
for (interactable_entity, interactable) in interactables_query.iter() {
println!(
"Hit: {:?} == interactable_entity: {:?} interactable: {}",
entity, interactable_entity, interactable
);
//println!("Collided! {}, {}", entity.index(), interactable.to_string());
if interactable_entity == entity {
hud_state.interaction_clue_shown = true;
if keyboard_input.just_pressed(KeyCode::F) { // TODO: Move this key to Controls state global
hud_state.interaction_clue_text = interactable.to_string();
println!("{interactable}");
if keyboard_input.just_pressed(KeyCode::F) {
// TODO: Move this key to Controls state global
println!("Interacted with interactable");
match interactable {
Interactable::Holdable => todo!(),
Interactable::Lootable(any_inventory) => loot_container_event_writer.send(LootContainerEvent(any_inventory.clone())),
Interactable::Lootable(any_inventory) => {
loot_container_event_writer
.send(LootContainerEvent(any_inventory.clone()))
}
Interactable::Item => todo!(),
}
}
return;
}
return;
}
}
}
}
hud_state.interaction_clue_shown = false;
}
}

View File

@ -2,5 +2,5 @@ pub mod camera_effects;
pub mod camera_player_sync;
pub mod hands;
pub mod player_movement;
pub mod player_values_state;
pub mod player_vertical_sync;
pub mod player_values_state;

View File

@ -109,7 +109,7 @@ pub fn move_player(
With<Player>,
>,
time: Res<Time>,
player_values_state: Res<PlayerValuesState>
player_values_state: Res<PlayerValuesState>,
) {
for (
mut player_velocity,
@ -151,7 +151,7 @@ pub fn move_player(
player_velocity.linvel,
time.delta_seconds(),
sprint_multiplier * crouch_multiplier,
player_values_state.player_acceleration
player_values_state.player_acceleration,
);
}
if player_movement_input.back {
@ -164,7 +164,7 @@ pub fn move_player(
player_velocity.linvel,
time.delta_seconds(),
crouch_multiplier,
player_values_state.player_acceleration
player_values_state.player_acceleration,
);
}
if player_movement_input.right {
@ -177,11 +177,13 @@ pub fn move_player(
player_velocity.linvel,
time.delta_seconds(),
if player_linear_xz_state.is_sprinting() {
player_values_state.player_lateral_acceleration_while_sprinting_multiplier * crouch_multiplier
player_values_state.player_lateral_acceleration_while_sprinting_multiplier
* crouch_multiplier
} else {
player_values_state.player_lateral_acceleration_multiplier * crouch_multiplier
player_values_state.player_lateral_acceleration_multiplier
* crouch_multiplier
},
player_values_state.player_acceleration
player_values_state.player_acceleration,
);
}
if player_movement_input.left {
@ -194,17 +196,22 @@ pub fn move_player(
player_velocity.linvel,
time.delta_seconds(),
if player_linear_xz_state.is_sprinting() {
player_values_state.player_lateral_acceleration_while_sprinting_multiplier * crouch_multiplier
player_values_state.player_lateral_acceleration_while_sprinting_multiplier
* crouch_multiplier
} else {
player_values_state.player_lateral_acceleration_multiplier * crouch_multiplier
player_values_state.player_lateral_acceleration_multiplier
* crouch_multiplier
},
player_values_state.player_acceleration
player_values_state.player_acceleration,
);
}
}
if player_movement_input.up && player_linear_y_state.is_grounded(&player_values_state.player_jump_cooldown_s) {
player_external_force.impulse = Vec3::new(0.0, player_values_state.player_jump_force, 0.0);
if player_movement_input.up
&& player_linear_y_state.is_grounded(&player_values_state.player_jump_cooldown_s)
{
player_external_force.impulse =
Vec3::new(0.0, player_values_state.player_jump_force, 0.0);
*player_linear_y_state = PlayerLinearYState::Jumping;
*player_damping = Damping {
linear_damping: player_values_state.player_linear_damping_while_jumping,
@ -217,10 +224,12 @@ pub fn move_player(
{
let positive = player_velocity.linvel.x.is_sign_positive();
if positive {
player_velocity.linvel.x =
player_values_state.max_linear_player_velocity * crouch_multiplier * sprint_multiplier
player_velocity.linvel.x = player_values_state.max_linear_player_velocity
* crouch_multiplier
* sprint_multiplier
} else {
player_velocity.linvel.x = player_values_state.max_linear_player_velocity * -1.0 * crouch_multiplier
player_velocity.linvel.x =
player_values_state.max_linear_player_velocity * -1.0 * crouch_multiplier
}
}
if player_velocity.linvel.z.abs()
@ -228,9 +237,11 @@ pub fn move_player(
{
let positive = player_velocity.linvel.z.is_sign_positive();
if positive {
player_velocity.linvel.z = player_values_state.max_linear_player_velocity * crouch_multiplier
player_velocity.linvel.z =
player_values_state.max_linear_player_velocity * crouch_multiplier
} else {
player_velocity.linvel.z = player_values_state.max_linear_player_velocity * -1.0 * crouch_multiplier
player_velocity.linvel.z =
player_values_state.max_linear_player_velocity * -1.0 * crouch_multiplier
}
}
if player_velocity.linvel.x > -1.0

View File

@ -1,5 +1,7 @@
use bevy::{prelude::{Resource, ReflectResource}, reflect::Reflect};
use bevy::{
prelude::{ReflectResource, Resource},
reflect::Reflect,
};
#[derive(Resource, Reflect)]
#[reflect(Resource)]
@ -7,7 +9,7 @@ pub struct PlayerValuesState {
pub max_linear_player_velocity: f32,
pub player_acceleration: f32,
pub player_jump_force: f32,
pub player_jump_cooldown_s: f64,
pub player_sprint_speed_multiplier: f32,
pub player_crouch_speed_multiplier: f32,
@ -18,10 +20,10 @@ pub struct PlayerValuesState {
pub player_camera_height: f32,
pub player_crouch_height: f32,
pub player_crouch_time_s: f32,
pub player_linear_damping: f32,
pub player_linear_damping_while_jumping: f32,
pub player_lean_time: f32,
pub player_lean_angle: f32,
@ -55,4 +57,4 @@ impl Default for PlayerValuesState {
player_linear_damping_time_offset_after_jump_in_s: 0.02,
}
}
}
}

View File

@ -9,7 +9,7 @@ use super::{player_movement::PlayerLinearYState, player_values_state::PlayerValu
pub fn sync_player_y_state(
mut query: Query<(&Velocity, &mut PlayerLinearYState, &mut Damping), With<Player>>,
time: Res<Time>,
player_values_state: Res<PlayerValuesState>
player_values_state: Res<PlayerValuesState>,
) {
for (player_velocity, mut player_linear_y_state, mut player_damping) in &mut query {
if player_velocity.linvel.y < -1.0 {
@ -26,7 +26,8 @@ pub fn sync_player_y_state(
let new_grounded_time = previous_grounded_time + time.delta().as_secs_f64();
*player_linear_y_state = PlayerLinearYState::Grounded(new_grounded_time);
if new_grounded_time
> player_values_state.player_jump_cooldown_s - player_values_state.player_linear_damping_time_offset_after_jump_in_s
> player_values_state.player_jump_cooldown_s
- player_values_state.player_linear_damping_time_offset_after_jump_in_s
{
*player_damping = Damping {
linear_damping: player_values_state.player_linear_damping,

View File

@ -2,15 +2,15 @@
use bevy::prelude::*;
use bevy_rapier3d::prelude::*;
use scenes::scene1;
use ui::{game::plugin::MainGameUIPlugin, editor::plugin::MainEditorUiPlugin};
use ui::{editor::plugin::MainEditorUiPlugin, game::plugin::MainGameUIPlugin};
mod comps;
mod constants;
mod logic;
mod scenes;
mod setup;
mod utils;
mod ui;
mod utils;
fn main() {
let mut application = App::new();

View File

@ -7,11 +7,11 @@ pub fn spawn_ground(
mut materials: ResMut<Assets<StandardMaterial>>,
) {
commands
.spawn((Collider::cuboid(50.0, 0.1, 50.0), Name::new("Ground")))
.spawn((Collider::cuboid(100.0, 0.1, 100.0), Name::new("Ground")))
.insert(TransformBundle::from(Transform::from_xyz(0.0, -2.0, 0.0)))
.insert(RigidBody::Fixed)
.insert(PbrBundle {
mesh: meshes.add(shape::Plane::from_size(100.0).into()),
mesh: meshes.add(shape::Plane::from_size(200.0).into()),
material: materials.add(StandardMaterial {
base_color: Color::WHITE,
perceptual_roughness: 1.0,

View File

@ -2,17 +2,30 @@ use bevy::prelude::*;
use crate::{
comps::core::controller::capture_input,
logic::core::{player::{
logic::core::{
guns::despawn_shots::{despawn_muzzle_flashes, despawn_stray_bullets},
player::{
camera_player_sync::{
follow_cursor_with_camera, update_camera_vertical_position, MouseMovementSettings,
},
hands::{capture_hand_usage, interact_action},
player_vertical_sync::sync_player_y_state, player_values_state::PlayerValuesState,
}, guns::despawn_shots::{despawn_muzzle_flashes, despawn_stray_bullets}}, setup::{assets::load_all_assets, load_state::GameLoadState, spawn::add_all_spawners, animations::{load_animations, AllFirearmAnimations}, equipment::{EquipmentChangeEvent, change_equipment}, spawners::player::player_spawner},
player_values_state::PlayerValuesState,
player_vertical_sync::sync_player_y_state,
},
},
setup::{
animations::{load_animations, AllFirearmAnimations},
assets::load_all_assets,
equipment::{change_equipment, EquipmentChangeEvent},
load_state::GameLoadState,
spawn::add_all_spawners,
spawners::player::player_spawner,
},
};
use super::{
ground::spawn_ground, lighting::setup_lighting, obstacles::spawn_obstacles, skybox::set_skybox_if_loaded, spawn_points::set_spawn_points,
ground::spawn_ground, items::spawn_items, lighting::setup_lighting, obstacles::spawn_obstacles,
skybox::set_skybox_if_loaded, spawn_points::set_spawn_points,
};
pub fn load_scene(application: &mut App) {
@ -23,7 +36,10 @@ pub fn load_scene(application: &mut App) {
// Startup
application.add_systems(PreStartup, load_all_assets);
application.add_systems(Startup, spawn_ground);
application.add_systems(Startup, spawn_obstacles);
application.add_systems(
Startup,
(spawn_obstacles, spawn_items.after(load_all_assets)),
);
application.add_systems(Startup, setup_lighting);
application.add_systems(Startup, set_spawn_points);
// Update
@ -32,7 +48,7 @@ pub fn load_scene(application: &mut App) {
application.add_systems(Update, sync_player_y_state);
application.add_systems(Update, follow_cursor_with_camera);
application.add_systems(Update, load_animations);
application.add_systems(Update, set_skybox_if_loaded);
application.add_systems(Update, update_camera_vertical_position);
application.add_systems(Update, (capture_hand_usage, interact_action));

View File

@ -0,0 +1,16 @@
use bevy::{gltf::Gltf, prelude::*};
use crate::{
comps::core::items::{guns::m4a1::M4a1GunItem, item::Item},
setup::assets::GltfAssets,
};
pub fn spawn_items(
mut commands: Commands,
assets_gltf: Res<GltfAssets>,
loaded_gltf_assets: Res<Assets<Gltf>>,
) {
let transform = Transform::from_xyz(20.0, 1.0, 10.0);
let m4item = M4a1GunItem;
m4item.spawn(&mut commands, transform, &assets_gltf, &loaded_gltf_assets);
}

View File

@ -1,16 +1,19 @@
use bevy::prelude::*;
pub fn setup_lighting(mut commands: Commands) {
commands.spawn((SpotLightBundle {
spot_light: SpotLight {
color: Color::WHITE,
intensity: 3000.0,
range: 500.0,
shadows_enabled: true,
commands.spawn((
SpotLightBundle {
spot_light: SpotLight {
color: Color::WHITE,
intensity: 3000.0,
range: 500.0,
shadows_enabled: true,
..Default::default()
},
transform: Transform::from_xyz(20.0, 20.0, 20.0).looking_at(Vec3::ZERO, Vec3::Y),
visibility: Visibility::Visible,
..Default::default()
},
transform: Transform::from_xyz(20.0, 20.0, 20.0).looking_at(Vec3::ZERO, Vec3::Y),
visibility: Visibility::Visible,
..Default::default()
}, Name::new("LightSource")));
Name::new("LightSource"),
));
}

View File

@ -1,7 +1,8 @@
pub mod init;
pub mod ground;
pub mod items;
pub mod lighting;
pub mod obstacles;
pub mod skybox;
pub mod spawn_points;
pub mod spawn_points;

View File

@ -1,7 +1,9 @@
use bevy::prelude::*;
use bevy_rapier3d::prelude::*;
use crate::comps::core::{markers::interactable::Interactable, grid::UGrid, inventory::any_inventory::AnyInventory};
use crate::comps::core::{
grid::UGrid, inventory::any_inventory::AnyInventory, markers::interactable::Interactable,
};
pub fn spawn_obstacles(
mut commands: Commands,
@ -15,7 +17,10 @@ pub fn spawn_obstacles(
let box_4_mesh = shape::Box::new(3.0, 7.0, 3.0).into();
let box_5_mesh = shape::Box::new(2.0, 2.0, 2.0).into();
commands
.spawn((Collider::from_bevy_mesh(&box_1_mesh, &Default::default()).unwrap(), Name::new("Obstacle 1")))
.spawn((
Collider::from_bevy_mesh(&box_1_mesh, &Default::default()).unwrap(),
Name::new("Obstacle 1"),
))
.insert(RigidBody::Fixed)
.insert(PbrBundle {
mesh: meshes.add(box_1_mesh.into()),
@ -29,7 +34,10 @@ pub fn spawn_obstacles(
});
commands
.spawn((Collider::from_bevy_mesh(&box_2_mesh, &Default::default()).unwrap(), Name::new("Obstacle 2")))
.spawn((
Collider::from_bevy_mesh(&box_2_mesh, &Default::default()).unwrap(),
Name::new("Obstacle 2"),
))
.insert(RigidBody::Fixed)
.insert(PbrBundle {
mesh: meshes.add(box_2_mesh.into()),
@ -43,7 +51,10 @@ pub fn spawn_obstacles(
});
commands
.spawn((Collider::from_bevy_mesh(&box_3_mesh, &Default::default()).unwrap(), Name::new("Obstacle 3")))
.spawn((
Collider::from_bevy_mesh(&box_3_mesh, &Default::default()).unwrap(),
Name::new("Obstacle 3"),
))
.insert(RigidBody::Fixed)
.insert(PbrBundle {
mesh: meshes.add(box_3_mesh.into()),
@ -57,7 +68,10 @@ pub fn spawn_obstacles(
});
commands
.spawn((Collider::from_bevy_mesh(&box_4_mesh, &Default::default()).unwrap(), Name::new("Obstacle 4")))
.spawn((
Collider::from_bevy_mesh(&box_4_mesh, &Default::default()).unwrap(),
Name::new("Obstacle 4"),
))
.insert(RigidBody::Fixed)
.insert(PbrBundle {
mesh: meshes.add(box_4_mesh.into()),
@ -69,10 +83,13 @@ pub fn spawn_obstacles(
transform: Transform::from_xyz(15.0, 3.5, 15.0),
..default()
});
// CRATE
commands
.spawn((Collider::from_bevy_mesh(&box_5_mesh, &Default::default()).unwrap(), Name::new("Crate")))
.spawn((
Collider::from_bevy_mesh(&box_5_mesh, &Default::default()).unwrap(),
Name::new("Crate"),
))
.insert(RigidBody::Fixed)
.insert(PbrBundle {
mesh: meshes.add(box_5_mesh.into()),
@ -84,7 +101,7 @@ pub fn spawn_obstacles(
transform: Transform::from_xyz(20.0, 2.0, 20.0),
..default()
})
.insert(
Interactable::Lootable(AnyInventory::new(UGrid::new_square(10)))
);
.insert(Interactable::Lootable(AnyInventory::new(
UGrid::new_square(10),
)));
}

View File

@ -27,7 +27,8 @@ pub fn set_skybox_if_loaded(
mut cubemap: ResMut<Cubemap>,
mut camera_query: Query<Entity, With<MainCamera>>,
) {
if !cubemap.is_loaded && asset_server.get_load_state(&cubemap.image_handle) == Some(LoadState::Loaded)
if !cubemap.is_loaded
&& asset_server.get_load_state(&cubemap.image_handle) == Some(LoadState::Loaded)
{
let image = images.get_mut(&cubemap.image_handle).unwrap();
// NOTE: PNGs do not have any metadata that could indicate they contain a cubemap texture,
@ -43,7 +44,9 @@ pub fn set_skybox_if_loaded(
}
for camera_entity in camera_query.iter_mut() {
commands.entity(camera_entity).insert(Skybox(cubemap.image_handle.clone()));
commands
.entity(camera_entity)
.insert(Skybox(cubemap.image_handle.clone()));
cubemap.is_loaded = true;
}
}

View File

@ -1,8 +1,20 @@
use bevy::prelude::*;
use crate::{setup::spawn::SpawnPoint, comps::core::markers::player::{Player, PlayerData}};
use crate::{
comps::core::{
items::guns::m4a1::M4a1GunItem,
markers::player::{Player, PlayerData},
},
setup::spawn::SpawnPoint,
};
pub fn set_spawn_points(mut commands: Commands) {
commands.spawn(SpawnPoint { at: Transform::from_xyz(3.0, 5.0, 2.0), what: Player(PlayerData::default()) });
}
commands.spawn(SpawnPoint {
at: Transform::from_xyz(3.0, 5.0, 2.0),
what: Player(PlayerData::default()),
});
commands.spawn(SpawnPoint {
at: Transform::from_xyz(20.0, 10.0, 10.0),
what: M4a1GunItem,
});
}

View File

@ -1,4 +1,4 @@
use bevy::{prelude::*, gltf::Gltf};
use bevy::{gltf::Gltf, prelude::*};
use crate::logic::core::guns::firearm::Firearm;
@ -14,7 +14,6 @@ pub struct AllFirearmAnimations {
pub struct FirearmAnimations {
pub firearm: Firearm,
pub reload_magazine: Handle<AnimationClip>,
}
/// System to load animations once the Gltf file is loaded.
@ -31,16 +30,21 @@ pub fn load_animations(
if assets_gltf.assets.len() != loaded_gltf_assets.len() {
return;
}
let mut all_firearm_animations = AllFirearmAnimations { animations: Vec::new() };
let mut all_firearm_animations = AllFirearmAnimations {
animations: Vec::new(),
};
for gltf_asset in assets_gltf.assets.iter() {
if gltf_asset.asset_type.is_firearm() {
if let Some(loaded_gltf) = loaded_gltf_assets.get(&gltf_asset.asset) {
// Needs to have all firearm animations
let reload_animation = &loaded_gltf.animations[0];
all_firearm_animations.animations.push(FirearmAnimations { firearm: gltf_asset.asset_type.get_firearm().clone(), reload_magazine: reload_animation.clone() })
all_firearm_animations.animations.push(FirearmAnimations {
firearm: gltf_asset.asset_type.get_firearm().clone(),
reload_magazine: reload_animation.clone(),
})
}
}
}
}
commands.insert_resource(all_firearm_animations);
game_load_state.animations_loaded = true;
}
}

View File

@ -1,6 +1,9 @@
use bevy::{prelude::*, gltf::Gltf};
use bevy::{gltf::Gltf, prelude::*};
use crate::{logic::core::guns::firearm::Firearm, scenes::scene1::skybox::{CUBEMAPS, Cubemap}};
use crate::{
logic::core::guns::firearm::Firearm,
scenes::scene1::skybox::{Cubemap, CUBEMAPS},
};
use super::load_state::GameLoadState;
@ -10,18 +13,19 @@ pub enum GltfAssetType {
#[allow(unused)]
Enemy,
}
#[derive(Resource, Reflect, Default)]
#[reflect(Resource)]
pub struct GltfAssets {
pub assets: Vec<GltfAsset>
pub assets: Vec<GltfAsset>,
}
#[derive(Reflect)]
pub struct GltfAsset {
pub asset_type: GltfAssetType,
pub asset: Handle<Gltf>,
}
pub fn load_all_assets(
mut commands: Commands,
asset_server: Res<AssetServer>,
@ -32,13 +36,16 @@ pub fn load_all_assets(
is_loaded: false,
image_handle: skybox_handle,
});
let m4a1_gltf_asset = GltfAsset { asset_type: GltfAssetType::Firearm(Firearm::M4A1), asset: asset_server.load(Firearm::M4A1.firearm_data().asset_path) } ;
let glock17_gltf_asset = GltfAsset { asset_type: GltfAssetType::Firearm(Firearm::Glock17), asset: asset_server.load(Firearm::Glock17.firearm_data().asset_path) };
let m4a1_gltf_asset = GltfAsset {
asset_type: GltfAssetType::Firearm(Firearm::M4A1),
asset: asset_server.load(Firearm::M4A1.firearm_data().asset_path),
};
let glock17_gltf_asset = GltfAsset {
asset_type: GltfAssetType::Firearm(Firearm::Glock17),
asset: asset_server.load(Firearm::Glock17.firearm_data().asset_path),
};
commands.insert_resource(GltfAssets {
assets: Vec::from([
m4a1_gltf_asset,
glock17_gltf_asset
])
assets: Vec::from([m4a1_gltf_asset, glock17_gltf_asset]),
});
game_load_state.assets_loaded = true;
// This works becaue this system is called on startup, so commands will finish running when game starts the update phase.
@ -49,7 +56,7 @@ impl GltfAssetType {
pub fn is_firearm(&self) -> bool {
match self {
GltfAssetType::Firearm(_) => true,
_ => false
_ => false,
}
}
pub fn get_firearm(&self) -> &Firearm {
@ -58,4 +65,4 @@ impl GltfAssetType {
_ => panic!("Called get_firearm on Non-Firearm GltfAssetType"),
}
}
}
}

View File

@ -1,10 +1,18 @@
use std::time::Duration;
use bevy::{prelude::*, gltf::Gltf};
use bevy::{gltf::Gltf, prelude::*};
use crate::{logic::core::guns::{firearm::Firearm, player_firing::PlayerFiringInfo}, comps::core::markers::{player::{Player, PlayerHand}, firearm::{MagazineData, FirearmData}, holdable::InPlayerHands}, utils};
use crate::{
comps::core::markers::{
firearm::{FirearmData, MagazineData},
holdable::InPlayerHands,
player::{Player, PlayerHand},
},
logic::core::guns::{firearm::Firearm, player_firing::PlayerFiringInfo},
utils,
};
use super::assets::{GltfAssets, GltfAssetType};
use super::assets::{GltfAssetType, GltfAssets};
#[derive(Event)]
pub struct EquipmentChangeEvent(pub Equipment);
@ -29,22 +37,27 @@ pub fn change_equipment(
for equipment_change_event in equipment_change_event_reader.read() {
let Ok((mut player, player_firing_info)) = player_query.get_single_mut() else {
return;
} ;
};
// Primary firearm change
if equipment_change_event.0 != player.0.equipment {
let player_hands = player_hands_query.single_mut();
commands.entity(player_hands).despawn_descendants(); // TODO: Don't do this without keeping the state from the last mag
if let Equipment::Firearm(new_firearm) = equipment_change_event.0.clone() {
spawn_firearm_on_player_hands(&mut commands, player_firing_info, player_hands, &assets_gltf, &loaded_gltf_assets, new_firearm);
spawn_firearm_on_player_hands(
&mut commands,
player_firing_info,
player_hands,
&assets_gltf,
&loaded_gltf_assets,
new_firearm,
);
}
// Set the player's equipment to the newly spawned equipment
player.0.equipment = equipment_change_event.0.clone();
println!("Equipment change done");
}
}
}
@ -56,7 +69,11 @@ fn spawn_firearm_on_player_hands(
loaded_gltf_assets: &Assets<Gltf>,
firearm: Firearm,
) {
if let Some(asset_handle) = assets_gltf.assets.iter().find(|asset| asset.asset_type == GltfAssetType::Firearm(firearm.clone())) {
if let Some(asset_handle) = assets_gltf
.assets
.iter()
.find(|asset| asset.asset_type == GltfAssetType::Firearm(firearm.clone()))
{
if let Some(gltf) = loaded_gltf_assets.get(&asset_handle.asset) {
let firearm_data: FirearmData = firearm.firearm_data();
let mut firearm_transform = Transform::from_xyz(0.0, 0.0, 0.0);
@ -65,19 +82,27 @@ fn spawn_firearm_on_player_hands(
firearm.holdable_object_data().y_rot,
));
firearm_transform.scale = firearm_transform.scale * firearm_data.scale_factor;
let scene = gltf.scenes[0].clone();
let firearm_asset_entity = commands.spawn((SceneBundle {
scene,
visibility: Visibility::Inherited,
transform: firearm_transform,
..default()
}, Name::new("Firearm Gltf Asset"))).id();
let scene = gltf.scenes[0].clone();
let firearm_asset_entity = commands
.spawn((
SceneBundle {
scene,
visibility: Visibility::Inherited,
transform: firearm_transform,
..default()
},
Name::new("Firearm Gltf Asset"),
))
.id();
let firearm_entity = commands
.spawn((
firearm_data.clone(),
firearm.holdable_object_data(),
MagazineData { rounds_shot: 0, max_capacity: firearm_data.max_capacity },
MagazineData {
rounds_shot: 0,
max_capacity: firearm_data.max_capacity,
},
InPlayerHands,
Name::new("Firearm"),
TransformBundle {
@ -88,18 +113,19 @@ fn spawn_firearm_on_player_hands(
visibility: Visibility::Inherited,
..Default::default()
},
)).push_children(&[firearm_asset_entity])
))
.push_children(&[firearm_asset_entity])
.id();
commands.entity(player_hands).push_children(&[firearm_entity]);
let time_in_secs_between_each_round =
1.0 / firearm_data.fire_rate * 60.0;
commands
.entity(player_hands)
.push_children(&[firearm_entity]);
let time_in_secs_between_each_round = 1.0 / firearm_data.fire_rate * 60.0;
player_firing_info.full_auto_timer = Timer::new(
Duration::from_secs_f32(time_in_secs_between_each_round),
TimerMode::Once,
);
}
}
}
}

View File

@ -5,12 +5,11 @@ use bevy::prelude::*;
pub struct GameLoadState {
pub assets_loaded: bool,
pub animations_loaded: bool,
pub player_loaded: bool,
pub player_loaded: bool,
}
impl GameLoadState {
pub fn is_everything_except_player_loaded(&self) -> bool {
self.assets_loaded &&
self.animations_loaded
self.assets_loaded && self.animations_loaded
}
}
}

View File

@ -1,6 +1,6 @@
pub mod assets;
pub mod animations;
pub mod assets;
pub mod equipment;
pub mod load_state;
pub mod spawn;
pub mod spawners;
pub mod equipment;

View File

@ -1,14 +1,22 @@
use bevy::prelude::*;
use super::{spawners::{player::player_spawner, firearm::firearm_spawner}, equipment::change_equipment};
use crate::comps::core::items::{guns::m4a1::M4a1GunItem, item::Item};
use super::{
equipment::change_equipment,
spawners::{item::item_spawner, player::player_spawner},
};
/// Where some Bundle T will replace this.
#[derive(Component, Reflect)]
pub struct SpawnPoint<T: Bundle> {
pub at: Transform,
pub what: T
pub what: T,
}
pub fn add_all_spawners(application: &mut App) {
application.add_systems(Update, (player_spawner, firearm_spawner).after(change_equipment));
}
application.add_systems(
Update,
(player_spawner, item_spawner::<M4a1GunItem>).after(change_equipment),
);
}

View File

@ -1,12 +0,0 @@
use bevy::prelude::*;
use crate::{logic::core::guns::firearm::Firearm, setup::{spawn::SpawnPoint, load_state::GameLoadState}};
#[allow(unused)]
pub fn firearm_spawner(
mut commands: Commands,
firearm_sp_query: Query<(Entity, &SpawnPoint<Firearm>)>,
mut game_load_state: ResMut<GameLoadState>,
) {
}

View File

@ -0,0 +1,22 @@
use bevy::{gltf::Gltf, prelude::*};
use crate::{
comps::core::items::{guns::m4a1::M4a1GunItem, item::Item},
setup::{assets::GltfAssets, load_state::GameLoadState, spawn::SpawnPoint},
};
pub fn item_spawner<T: Item>(
mut commands: Commands,
item_sp_query: Query<(Entity, &SpawnPoint<T>)>,
game_load_state: ResMut<GameLoadState>,
assets_gltf: Res<GltfAssets>,
loaded_gltf_assets: Res<Assets<Gltf>>,
) {
if game_load_state.is_everything_except_player_loaded() {
for (entity, item_sp) in item_sp_query.iter() {
let m4 = M4a1GunItem;
m4.spawn(&mut commands, item_sp.at, &assets_gltf, &loaded_gltf_assets);
commands.entity(entity).despawn();
}
}
}

View File

@ -1,2 +1,2 @@
pub mod item;
pub mod player;
pub mod firearm;

View File

@ -4,9 +4,16 @@ use bevy_rapier3d::prelude::*;
use crate::{
comps::core::markers::{
camera::MainCamera,
player::{Player, PlayerHand, PlayerData},
player::{Player, PlayerData, PlayerHand},
},
logic::core::{player::{player_movement::{PlayerLinearYState, PlayerLinearXZState}, player_values_state::PlayerValuesState}, guns::player_firing::PlayerFiringInfo}, setup::{load_state::GameLoadState, equipment::EquipmentChangeEvent},
logic::core::{
guns::player_firing::PlayerFiringInfo,
player::{
player_movement::{PlayerLinearXZState, PlayerLinearYState},
player_values_state::PlayerValuesState,
},
},
setup::{equipment::EquipmentChangeEvent, load_state::GameLoadState},
};
use crate::setup::spawn::SpawnPoint;
@ -28,7 +35,9 @@ pub fn player_spawner(
// Spawn hand
let player_hand = commands
.spawn((PlayerHand, Name::new("Player Hand")))
.insert(TransformBundle::from(Transform::from_xyz(0.6, -0.45, -20.0)))
.insert(TransformBundle::from(Transform::from_xyz(
0.6, -0.45, -20.0,
)))
.insert(VisibilityBundle {
visibility: Visibility::Inherited,
..Default::default()
@ -76,7 +85,9 @@ pub fn player_spawner(
| LockedAxes::ROTATION_LOCKED_X
| LockedAxes::ROTATION_LOCKED_Y,
)
.insert(ColliderMassProperties::Mass(player_values_state.player_initial_weight))
.insert(ColliderMassProperties::Mass(
player_values_state.player_initial_weight,
))
.insert(ExternalImpulse {
impulse: Vec3::ZERO,
torque_impulse: Vec3::ZERO,
@ -94,7 +105,9 @@ pub fn player_spawner(
.push_children(&[camera]);
game_load_state.player_loaded = true;
equipment_change_event_writer.send(EquipmentChangeEvent(player_spawn_point.what.0.equipment.clone()));
equipment_change_event_writer.send(EquipmentChangeEvent(
player_spawn_point.what.0.equipment.clone(),
));
commands.entity(player_spawn_point_entity).despawn();
}
}
}

View File

@ -1,6 +1,9 @@
use bevy::{prelude::*, window::PrimaryWindow};
use bevy_editor_pls::{controls::{self, EditorControls}, default_windows::cameras::EditorCamera};
use bevy_inspector_egui::{egui, bevy_egui::EguiContext, bevy_inspector};
use bevy_editor_pls::{
controls::{self, EditorControls},
default_windows::cameras::EditorCamera,
};
use bevy_inspector_egui::{bevy_egui::EguiContext, bevy_inspector, egui};
#[allow(unused)]
pub fn inspector_ui(world: &mut World) {
@ -9,10 +12,8 @@ pub fn inspector_ui(world: &mut World) {
.single(world)
.clone();
egui::Window::new("World")
.show(egui_context.get_mut(), |ui| {
egui::ScrollArea::vertical()
.show(ui, |ui| {
egui::Window::new("World").show(egui_context.get_mut(), |ui| {
egui::ScrollArea::vertical().show(ui, |ui| {
bevy_inspector::ui_for_world(world, ui);
});
});
@ -33,7 +34,9 @@ pub fn editor_controls() -> EditorControls {
}
pub fn set_cam3d_controls(
mut query: Query<&mut bevy_editor_pls::default_windows::cameras::camera_3d_free::FlycamControls>,
mut query: Query<
&mut bevy_editor_pls::default_windows::cameras::camera_3d_free::FlycamControls,
>,
mut query_camera_transforms: Query<&mut Transform, With<EditorCamera>>,
) {
for mut controls in query.iter_mut() {
@ -45,7 +48,11 @@ pub fn set_cam3d_controls(
}
// TODO: run this after the position update already in the editor plugin
for mut transform in query_camera_transforms.iter_mut() {
transform.translation = Vec3 { x: 6.5, y: 28.0, z: 41.6 };
transform.translation = Vec3 {
x: 6.5,
y: 28.0,
z: 41.6,
};
transform.look_at(Vec3::ZERO, Vec3::Y);
}
}
}

View File

@ -1,8 +1,8 @@
//! Editor UI means everything that won't be in the actual game
pub mod plugin;
pub mod inspector;
pub mod plugin;
/*
pub mod panels;
pub mod state;
pub mod camera;
*/
*/

View File

@ -2,7 +2,31 @@ use bevy::prelude::*;
use bevy_editor_pls::EditorPlugin;
use bevy_inspector_egui::bevy_egui::EguiPlugin;
use crate::{logic::core::{guns::{player_firing::PlayerFiringInfo, caliber::Caliber, firearm::Firearm, spray_pattern::FirearmSprayPattern}, player::{player_values_state::PlayerValuesState, camera_player_sync::MouseMovementSettings, player_movement::{PlayerLinearYState, PlayerLinearXZState, PlayerMovementInput}}}, comps::core::markers::{firearm::{FirearmData, MagazineData}, holdable::{HoldableObjectData, InPlayerHands}, player::{PlayerData, Player, PlayerHand}}, scenes::scene1::skybox::Cubemap, setup::{animations::{AllFirearmAnimations, FirearmAnimations}, assets::{GltfAssetType, GltfAssets}, equipment::Equipment, load_state::GameLoadState}};
use crate::{
comps::core::markers::{
firearm::{FirearmData, MagazineData},
holdable::{HoldableObjectData, InPlayerHands},
player::{Player, PlayerData, PlayerHand},
},
logic::core::{
guns::{
caliber::Caliber, firearm::Firearm, player_firing::PlayerFiringInfo,
spray_pattern::FirearmSprayPattern,
},
player::{
camera_player_sync::MouseMovementSettings,
player_movement::{PlayerLinearXZState, PlayerLinearYState, PlayerMovementInput},
player_values_state::PlayerValuesState,
},
},
scenes::scene1::skybox::Cubemap,
setup::{
animations::{AllFirearmAnimations, FirearmAnimations},
assets::{GltfAssetType, GltfAssets},
equipment::Equipment,
load_state::GameLoadState,
},
};
use super::inspector::{editor_controls, set_cam3d_controls};
@ -14,34 +38,33 @@ pub struct MainEditorUiPlugin;
impl Plugin for MainEditorUiPlugin {
fn build(&self, app: &mut App) {
app
.register_type::<PlayerFiringInfo>()
.register_type::<PlayerValuesState>()
.register_type::<FirearmData>()
.register_type::<MagazineData>()
.register_type::<HoldableObjectData>()
.register_type::<InPlayerHands>()
.register_type::<PlayerData>()
.register_type::<Player>()
.register_type::<PlayerHand>()
.register_type::<Caliber>()
.register_type::<Firearm>()
.register_type::<FirearmSprayPattern>()
.register_type::<MouseMovementSettings>()
.register_type::<PlayerLinearYState>()
.register_type::<PlayerLinearXZState>()
.register_type::<PlayerMovementInput>()
.register_type::<Cubemap>()
.register_type::<AllFirearmAnimations>()
.register_type::<FirearmAnimations>()
.register_type::<GltfAssetType>()
.register_type::<GltfAssets>()
.register_type::<Equipment>()
.register_type::<GameLoadState>()
.add_plugins(EguiPlugin)
.add_plugins(EditorPlugin::default())
.insert_resource(editor_controls())
.add_systems(PostStartup, set_cam3d_controls);
app.register_type::<PlayerFiringInfo>()
.register_type::<PlayerValuesState>()
.register_type::<FirearmData>()
.register_type::<MagazineData>()
.register_type::<HoldableObjectData>()
.register_type::<InPlayerHands>()
.register_type::<PlayerData>()
.register_type::<Player>()
.register_type::<PlayerHand>()
.register_type::<Caliber>()
.register_type::<Firearm>()
.register_type::<FirearmSprayPattern>()
.register_type::<MouseMovementSettings>()
.register_type::<PlayerLinearYState>()
.register_type::<PlayerLinearXZState>()
.register_type::<PlayerMovementInput>()
.register_type::<Cubemap>()
.register_type::<AllFirearmAnimations>()
.register_type::<FirearmAnimations>()
.register_type::<GltfAssetType>()
.register_type::<GltfAssets>()
.register_type::<Equipment>()
.register_type::<GameLoadState>()
.add_plugins(EguiPlugin)
.add_plugins(EditorPlugin::default())
.insert_resource(editor_controls())
.add_systems(PostStartup, set_cam3d_controls);
//.add_plugins(ResourceInspectorPlugin::<MouseMovementSettings>::default());
//.add_plugins(bevy_inspector_egui::DefaultInspectorConfigPlugin) // adds default options and `InspectorEguiImpl`s
//.add_systems(Update, inspector_ui);
@ -49,4 +72,4 @@ impl Plugin for MainEditorUiPlugin {
//app.add_systems(Update, editor_ui);
//app.add_systems(PostUpdate, set_camera_viewport);
}
}
}

View File

@ -9,24 +9,37 @@ pub struct FpsCounterMarker {
}
impl FpsCounterMarker {
pub fn new() -> Self {
Self { timer: Timer::new(Duration::from_secs_f32(0.5), TimerMode::Repeating), frames_elapsed: 0, }
Self {
timer: Timer::new(Duration::from_secs_f32(0.5), TimerMode::Repeating),
frames_elapsed: 0,
}
}
}
pub fn setup_fps_counter(mut commands: Commands, ) {
commands.spawn((TextBundle {
text: Text::from_section("FPS: 0.0", TextStyle {
font_size: 18.0, color: Color::GREEN, ..Default::default()
}).with_alignment(TextAlignment::Center),
style: Style {
position_type: PositionType::Absolute,
right: Val::Px(10.0),
top: Val::Px(30.0),
..Default::default()
},
..Default::default()
}, Name::new("Fps Counter")))
.insert(FpsCounterMarker::new());
pub fn setup_fps_counter(mut commands: Commands) {
commands
.spawn((
TextBundle {
text: Text::from_section(
"FPS: 0.0",
TextStyle {
font_size: 18.0,
color: Color::GREEN,
..Default::default()
},
)
.with_alignment(TextAlignment::Center),
style: Style {
position_type: PositionType::Absolute,
right: Val::Px(10.0),
top: Val::Px(30.0),
..Default::default()
},
..Default::default()
},
Name::new("Fps Counter"),
))
.insert(FpsCounterMarker::new());
}
pub fn tick_fps_counter(
@ -45,4 +58,4 @@ pub fn tick_fps_counter(
}
}
}
}
}

View File

@ -4,5 +4,5 @@ use bevy::prelude::*;
#[reflect(Resource)]
pub struct HudState {
pub interaction_clue_shown: bool,
}
pub interaction_clue_text: String,
}

View File

@ -1,4 +1,4 @@
use bevy::{prelude::*, ui::FocusPolicy};
use bevy::prelude::*;
use crate::ui::game::settings::SettingsScreenUIConfiguration;
@ -9,51 +9,51 @@ pub struct InteractClueHudMarker;
pub fn setup_interact_clue(mut commands: Commands) {
commands.spawn((
NodeBundle {
TextBundle {
text: Text::from_section(
"Interact",
TextStyle {
font_size: 12.0,
color: Color::WHITE,
..Default::default()
},
)
.with_alignment(TextAlignment::Center),
style: Style {
display: Display::Flex,
width: Val::Percent(100.0),
height: Val::Percent(100.0),
justify_content: JustifyContent::Center,
align_items: AlignItems::Center,
position_type: PositionType::Absolute,
top: Val::Percent(50.0),
left: Val::Percent(50.0),
..Default::default()
},
visibility: Visibility::Hidden,
background_color: BackgroundColor(Color::NONE),
focus_policy: FocusPolicy::Pass,
visibility: Visibility::Visible,
..Default::default()
}, Name::new("Interaction Clue Background"),
InteractClueHudMarker)
).with_children(|parent| {
parent.spawn((TextBundle {
text: Text::from_section("Loot", TextStyle {
font_size: 12.0, color: Color::WHITE, ..Default::default()
}).with_alignment(TextAlignment::Center),
..Default::default()
}, Name::new("Interaction Clue text"),
},
Name::new("Interaction Clue text"),
InteractClueHudMarker,
));
});
}
pub fn update_interact_clue(
//mut commands: Commands,
interact_clue: Res<HudState>,
settings_screen_config: Res<SettingsScreenUIConfiguration>,
mut query: Query<&mut Visibility, With<InteractClueHudMarker>>
mut query: Query<(&mut Visibility, &mut Text), With<InteractClueHudMarker>>,
) {
if !settings_screen_config.is_changed() && !interact_clue.is_changed() {
return;
}
for mut vis in query.iter_mut() {
for (mut vis, mut text) in query.iter_mut() {
if settings_screen_config.settings_menu_shown {
*vis = Visibility::Hidden;
return;
}
if interact_clue.interaction_clue_shown {
*vis = Visibility::Visible;
if let Some(section) = text.sections.first_mut() {
section.value = interact_clue.interaction_clue_text.clone();
}
} else {
*vis = Visibility::Hidden;
}
}
}
}

View File

@ -1,3 +1,3 @@
pub mod hud;
pub mod interact_clue;
pub mod plugin;
pub mod hud;

View File

@ -4,7 +4,6 @@ use crate::ui::game::hud::hud::HudState;
use super::interact_clue::{setup_interact_clue, update_interact_clue};
pub struct HudOverlayPlugin;
impl Plugin for HudOverlayPlugin {
@ -14,4 +13,4 @@ impl Plugin for HudOverlayPlugin {
app.add_systems(Startup, setup_interact_clue);
app.add_systems(Update, update_interact_clue);
}
}
}

View File

@ -2,15 +2,9 @@ use bevy::prelude::*;
use crate::comps::core::events::loot_container::LootContainerEvent;
/// # Inventory Screen
/// Should contain player inventory and if player is looting something as well
pub fn setup_inventory_screen(
mut commands: Commands,
) {
}
pub fn setup_inventory_screen(mut commands: Commands) {}
pub fn update_inventory_screen(
mut commands: Commands,
@ -19,4 +13,4 @@ pub fn update_inventory_screen(
for loot_container_event in event_reader.read() {
//let a = loot_container_event.0.clone();
}
}
}

View File

@ -1,2 +1,2 @@
pub mod menu;
pub mod plugin;
pub mod plugin;

View File

@ -4,7 +4,6 @@ use crate::comps::core::events::loot_container::LootContainerEvent;
use super::menu::{setup_inventory_screen, update_inventory_screen};
pub struct InventoryMenuPlugin;
impl Plugin for InventoryMenuPlugin {
@ -13,4 +12,4 @@ impl Plugin for InventoryMenuPlugin {
app.add_systems(Startup, setup_inventory_screen);
app.add_systems(Update, update_inventory_screen);
}
}
}

View File

@ -1,7 +1,7 @@
//! Game UI means all the UI that will be part of the actual game
pub mod plugin;
pub mod fps_counter;
pub mod hud;
pub mod inventory;
pub mod plugin;
pub mod settings;
pub mod settings_screen;
pub mod inventory;
pub mod hud;

View File

@ -2,7 +2,9 @@ use bevy::prelude::*;
use crate::ui::game::settings::GameConfiguration;
use super::{fps_counter, settings_screen, settings::SettingsScreenUIConfiguration, inventory, hud};
use super::{
fps_counter, hud, inventory, settings::SettingsScreenUIConfiguration, settings_screen,
};
pub struct MainGameUIPlugin;
@ -12,15 +14,21 @@ impl Plugin for MainGameUIPlugin {
app.add_plugins(inventory::plugin::InventoryMenuPlugin);
app.insert_resource(GameConfiguration::default());
app.insert_resource(SettingsScreenUIConfiguration::default());
app.add_systems(Startup, (
settings_screen::setup_settings_screen,
fps_counter::setup_fps_counter,
inventory::menu::setup_inventory_screen,
));
app.add_systems(Update, (
settings_screen::toggle_settings_screen,
settings_screen::handle_settings_button_click,
fps_counter::tick_fps_counter,
));
app.add_systems(
Startup,
(
settings_screen::setup_settings_screen,
fps_counter::setup_fps_counter,
inventory::menu::setup_inventory_screen,
),
);
app.add_systems(
Update,
(
settings_screen::toggle_settings_screen,
settings_screen::handle_settings_button_click,
fps_counter::tick_fps_counter,
),
);
}
}
}

View File

@ -8,7 +8,9 @@ pub struct SettingsScreenUIConfiguration {
impl Default for SettingsScreenUIConfiguration {
fn default() -> Self {
Self { settings_menu_shown: false }
Self {
settings_menu_shown: false,
}
}
}
@ -16,13 +18,12 @@ impl Default for SettingsScreenUIConfiguration {
#[reflect(Resource)]
pub struct GameConfiguration {
pub fps_counter_enabled: bool,
}
impl Default for GameConfiguration {
fn default() -> Self {
Self {
Self {
fps_counter_enabled: true,
}
}
}
}

View File

@ -1,4 +1,4 @@
use bevy::{prelude::*, ui::FocusPolicy, app::AppExit};
use bevy::{app::AppExit, prelude::*, ui::FocusPolicy};
use super::settings::SettingsScreenUIConfiguration;
@ -12,64 +12,86 @@ pub enum SettingsScreenActions {
}
pub fn setup_settings_screen(mut commands: Commands) {
commands.spawn((
NodeBundle {
style: Style {
display: Display::Flex,
width: Val::Percent(100.0),
height: Val::Percent(100.0),
justify_content: JustifyContent::Center,
align_items: AlignItems::Center,
flex_direction: FlexDirection::Column,
..Default::default()
},
visibility: Visibility::Hidden,
background_color: BackgroundColor(Color::rgba(0.0, 0.0, 0.0, 0.9)),
focus_policy: FocusPolicy::Block,
..Default::default()
}, Name::new("Settings Menu"))
)
.insert(SettingsScreenMarker)
.with_children(|parent| {
// RESUME BUTTON
parent.spawn((
ButtonBundle {
commands
.spawn((
NodeBundle {
style: Style {
display: Display::Flex,
width: Val::Percent(100.0),
height: Val::Percent(100.0),
justify_content: JustifyContent::Center,
align_items: AlignItems::Center,
flex_direction: FlexDirection::Column,
..Default::default()
},
background_color: BackgroundColor(Color::NONE),
visibility: Visibility::Hidden,
background_color: BackgroundColor(Color::rgba(0.0, 0.0, 0.0, 0.9)),
focus_policy: FocusPolicy::Block,
..Default::default()
},
Name::new("Resume Button")
Name::new("Settings Menu"),
))
.insert(SettingsScreenActions::Resume)
.insert(SettingsScreenMarker)
.with_children(|parent| {
parent.spawn((TextBundle {
text: Text::from_section("Resume", TextStyle { font_size: 32.0, ..Default::default() }),
..Default::default()
}, Name::new("Resume Button Text")));
// RESUME BUTTON
parent
.spawn((
ButtonBundle {
style: Style {
..Default::default()
},
background_color: BackgroundColor(Color::NONE),
..Default::default()
},
Name::new("Resume Button"),
))
.insert(SettingsScreenActions::Resume)
.with_children(|parent| {
parent.spawn((
TextBundle {
text: Text::from_section(
"Resume",
TextStyle {
font_size: 32.0,
..Default::default()
},
),
..Default::default()
},
Name::new("Resume Button Text"),
));
});
// QUIT BUTTON
parent
.spawn((
ButtonBundle {
style: Style {
..Default::default()
},
background_color: BackgroundColor(Color::NONE),
//focus_policy: FocusPolicy::Block,
..Default::default()
},
Name::new("Quit Button"),
))
.insert(SettingsScreenActions::Quit)
.with_children(|parent| {
parent.spawn((
TextBundle {
text: Text::from_section(
"Quit",
TextStyle {
font_size: 32.0,
..Default::default()
},
),
..Default::default()
},
Name::new("Quit Button text"),
));
});
// END BUTTONS
});
// QUIT BUTTON
parent.spawn((
ButtonBundle {
style: Style {
..Default::default()
},
background_color: BackgroundColor(Color::NONE),
//focus_policy: FocusPolicy::Block,
..Default::default()
},
Name::new("Quit Button")
))
.insert(SettingsScreenActions::Quit)
.with_children(|parent| {
parent.spawn((TextBundle {
text: Text::from_section("Quit", TextStyle { font_size: 32.0, ..Default::default() }),
..Default::default()
}, Name::new("Quit Button text")));
});
// END BUTTONS
});
}
pub fn toggle_settings_screen(
@ -77,7 +99,9 @@ pub fn toggle_settings_screen(
mut settings_screen_query: Query<(&mut Visibility, &mut Style), With<SettingsScreenMarker>>,
) {
if settings.is_changed() {
for (mut settings_screen_visibility, mut settings_screen_style) in settings_screen_query.iter_mut() {
for (mut settings_screen_visibility, mut settings_screen_style) in
settings_screen_query.iter_mut()
{
if settings.settings_menu_shown {
*settings_screen_visibility = Visibility::Visible;
settings_screen_style.display = Display::Flex;
@ -102,15 +126,15 @@ pub fn handle_settings_button_click(
SettingsScreenActions::Quit => {
// QUIT GAME
exit.send(AppExit);
},
}
SettingsScreenActions::Resume => {
// RESUME GAME
settings.settings_menu_shown = false;
mouse_buttons.release(MouseButton::Left);
}
}
},
}
_ => {}
}
}
}
}

View File

@ -1,2 +1,2 @@
pub mod editor;
pub mod game;
pub mod editor;