diff --git a/src/comps/core/markers/player.rs b/src/comps/core/markers/player.rs index eb1aa9f..1bf0f91 100644 --- a/src/comps/core/markers/player.rs +++ b/src/comps/core/markers/player.rs @@ -4,4 +4,4 @@ use bevy::prelude::Component; pub struct Player; #[derive(Component)] -pub struct PlayerHand; +pub struct PlayerHand; \ No newline at end of file diff --git a/src/logic/core/guns/equip_firearm.rs b/src/logic/core/guns/equip_firearm.rs index e69de29..bfa1366 100644 --- a/src/logic/core/guns/equip_firearm.rs +++ b/src/logic/core/guns/equip_firearm.rs @@ -0,0 +1,7 @@ + +#[allow(unused)] + +/// System that checks if player +pub fn equip_firearm() { + +} \ No newline at end of file diff --git a/src/logic/core/guns/firearm.rs b/src/logic/core/guns/firearm.rs index 0345498..b2c5723 100644 --- a/src/logic/core/guns/firearm.rs +++ b/src/logic/core/guns/firearm.rs @@ -3,6 +3,7 @@ use bevy::prelude::*; use super::{caliber::Caliber, spray_pattern::FirearmSprayPattern}; +#[derive(Component, PartialEq, Eq, PartialOrd, Ord, Clone)] pub enum Firearm { M4A1, } diff --git a/src/logic/core/guns/spawn_firearm.rs b/src/logic/core/guns/spawn_firearm.rs index b778f51..2c6ae81 100644 --- a/src/logic/core/guns/spawn_firearm.rs +++ b/src/logic/core/guns/spawn_firearm.rs @@ -5,7 +5,7 @@ use bevy::{prelude::*, gltf::Gltf}; use crate::{ comps::core::markers::{holdable::InPlayerHands, player::PlayerHand, firearm::{MagazineData, FirearmData}}, constants::player_values::DEFAULT_PLAYER_FIREARM, - utils, setup::{animations::FirearmAnimations, gltf_assets::GltfAssets}, + utils, setup::{animations::FirearmAnimations, assets::{GltfAssets, GltfAssetType}}, }; use super::{player_firing::PlayerFiringInfo, firearm::Firearm}; @@ -13,14 +13,12 @@ use super::{player_firing::PlayerFiringInfo, firearm::Firearm}; pub fn spawn_firearm_on_player_hands( mut commands: Commands, query: Query>, - asset_server: Res, mut player_firing_info: ResMut, assets_gltf: Res, loaded_gltf_assets: Res>, ) { - if let Some(asset_handle) = assets_gltf.assets.iter().find(|asset| asset.id == Firearm::M4A1.firearm_data().identifier) { + if let Some(asset_handle) = assets_gltf.assets.iter().find(|asset| asset.asset_type == GltfAssetType::Firearm(Firearm::M4A1)) { if let Some(gltf) = loaded_gltf_assets.get(&asset_handle.asset) { - println!("C"); for entity in query.iter() { let mut firearm_transform = Transform::from_xyz(0.0, 0.0, 0.0); firearm_transform.rotate_y(utils::rad_deg::radians_from_degrees( @@ -38,7 +36,6 @@ pub fn spawn_firearm_on_player_hands( ..default() }, DEFAULT_PLAYER_FIREARM.firearm_data(), - FirearmAnimations { reload_magazine: todo!() }, DEFAULT_PLAYER_FIREARM.holdable_object_data(), MagazineData { rounds_shot: 0, max_capacity: DEFAULT_PLAYER_FIREARM.firearm_data().max_capacity }, InPlayerHands, @@ -54,7 +51,7 @@ pub fn spawn_firearm_on_player_hands( TimerMode::Once, ); // Load animations - commands.insert_resource(FirearmAnimations { reload_magazine: asset_server.load(format!("{}#Animation0", DEFAULT_PLAYER_FIREARM.firearm_data().asset_path))}) + //commands.insert_resource(FirearmAnimations { reload_magazine: asset_server.load(format!("{}#Animation0", DEFAULT_PLAYER_FIREARM.firearm_data().asset_path))}) } } } diff --git a/src/logic/core/player/camera_effects.rs b/src/logic/core/player/camera_effects.rs index 3220062..e69de29 100644 --- a/src/logic/core/player/camera_effects.rs +++ b/src/logic/core/player/camera_effects.rs @@ -1,11 +0,0 @@ -use bevy::{prelude::*, gltf::Gltf}; - -// Once the scene is loaded, start the animation -pub fn setup_scene_once_loaded( - gltf_assets: Res>, - asset_server: Res, -) { - for asset in gltf_assets.iter() { - - } -} \ No newline at end of file diff --git a/src/logic/core/player/hands.rs b/src/logic/core/player/hands.rs index 84c07a3..448fe10 100644 --- a/src/logic/core/player/hands.rs +++ b/src/logic/core/player/hands.rs @@ -18,8 +18,6 @@ pub fn capture_hand_usage( >, animation_clips: Res>, - - animations: Res, mut players: Query<&mut AnimationPlayer>, ) { player_firing_info.full_auto_timer.tick(time.delta()); @@ -29,20 +27,20 @@ pub fn capture_hand_usage( if player_firing_info.is_reloading { for player in &mut players { - if let Some(reload_animation) = animation_clips.get(&animations.reload_magazine) { + /*if let Some(reload_animation) = animation_clips.get(&animations.reload_magazine) { if player.elapsed() >= reload_animation.duration() { magazine_data.rounds_shot = 0; player_firing_info.is_reloading = false; } - } + }*/ } } else { // Player is not in a reload animation if keyboard_input.just_pressed(KeyCode::R) { // Start reload animation - for mut player in &mut players { + /*for mut player in &mut players { player.start(animations.reload_magazine.clone_weak()); player_firing_info.is_reloading = true; - } + }*/ // Set is_reloading = true // At the end of reload animation, set magazine data to capacity = 0 } diff --git a/src/logic/core/player/mod.rs b/src/logic/core/player/mod.rs index afef187..0fffd3b 100644 --- a/src/logic/core/player/mod.rs +++ b/src/logic/core/player/mod.rs @@ -3,4 +3,3 @@ pub mod camera_player_sync; pub mod hands; pub mod player_movement; pub mod player_vertical_sync; -pub mod spawn_player; diff --git a/src/logic/core/player/spawn_player.rs b/src/logic/core/player/spawn_player.rs deleted file mode 100644 index 2bf54e0..0000000 --- a/src/logic/core/player/spawn_player.rs +++ /dev/null @@ -1,83 +0,0 @@ -use bevy::{core_pipeline::Skybox, prelude::*}; -use bevy_rapier3d::prelude::*; - -use crate::{ - comps::core::markers::{ - camera::MainCamera, - player::{Player, PlayerHand}, - }, - constants::player_values::{ - PLAYER_GRAVITY_SCALE, PLAYER_HEIGHT, PLAYER_INITIAL_WEIGHT, PLAYER_LINEAR_DAMPING, - }, - scenes::scene1::skybox::{Cubemap, CUBEMAPS}, -}; - -use super::player_movement::{PlayerLinearXZState, PlayerLinearYState}; - -pub fn spawn_player(mut commands: Commands, asset_server: Res) { - let player_hand = commands - .spawn(PlayerHand) - .insert(TransformBundle::from(Transform::from_xyz(0.6, -0.45, -20.0))) - .insert(VisibilityBundle { - visibility: Visibility::Inherited, - ..Default::default() - }) - .id(); - - let skybox_handle = asset_server.load(CUBEMAPS[0].0); - let camera = commands - .spawn(MainCamera) - .insert(Camera3dBundle { - transform: Transform::from_xyz(0.0, 0.0, 0.0).looking_at(Vec3::ZERO, Vec3::Y), - ..Default::default() - }) - .insert(Skybox(skybox_handle.clone())) - .insert(VisibilityBundle { - visibility: Visibility::Inherited, - ..Default::default() - }) - .push_children(&[player_hand]) - .id(); - - commands - .spawn(Player) - .insert(RigidBody::Dynamic) - .insert(GravityScale(PLAYER_GRAVITY_SCALE)) - .insert(Collider::capsule_y(PLAYER_HEIGHT, 2.0)) - .insert(Restitution::coefficient(0.0)) - .insert(Friction { - coefficient: 0.0, - combine_rule: CoefficientCombineRule::Multiply, - }) - .insert(TransformBundle { - local: Transform::from_xyz(3.0, 5.0, 2.0), - global: Default::default(), - }) - .insert(Velocity::zero()) - .insert(Damping { - linear_damping: PLAYER_LINEAR_DAMPING, - angular_damping: 1.0, - }) - .insert( - LockedAxes::ROTATION_LOCKED_Z - | LockedAxes::ROTATION_LOCKED_X - | LockedAxes::ROTATION_LOCKED_Y, - ) - .insert(ColliderMassProperties::Mass(PLAYER_INITIAL_WEIGHT)) - .insert(ExternalImpulse { - impulse: Vec3::ZERO, - torque_impulse: Vec3::ZERO, - }) - .insert(PlayerLinearYState::Falling) - .insert(PlayerLinearXZState::Stopped) - .insert(VisibilityBundle { - visibility: Visibility::Visible, - ..Default::default() - }) - .push_children(&[camera]); - - commands.insert_resource(Cubemap { - is_loaded: false, - image_handle: skybox_handle, - }); -} diff --git a/src/scenes/scene1/init.rs b/src/scenes/scene1/init.rs index dea9032..e03b92b 100644 --- a/src/scenes/scene1/init.rs +++ b/src/scenes/scene1/init.rs @@ -10,14 +10,12 @@ use crate::{ }, hands::capture_hand_usage, player_vertical_sync::sync_player_y_state, - spawn_player::spawn_player, }, - }, setup::{gltf_assets::load_all_assets, load_state::GameLoadState}, + }, setup::{assets::load_all_assets, load_state::GameLoadState, spawn::add_all_spawners, animations::load_animations}, }; use super::{ - ground::spawn_ground, lighting::setup_lighting, obstacles::spawn_obstacles, - skybox::asset_loaded, + ground::spawn_ground, lighting::setup_lighting, obstacles::spawn_obstacles, skybox::set_skybox_if_loaded, spawn_points::set_spawn_points, }; pub fn load_scene(application: &mut App) { @@ -28,20 +26,22 @@ pub fn load_scene(application: &mut App) { application.add_systems(PreStartup, load_all_assets); application.add_systems(Startup, spawn_ground); application.add_systems(Startup, spawn_obstacles); - application.add_systems(Startup, spawn_player.after(load_all_assets)); application.add_systems(Startup, setup_lighting); + application.add_systems(Startup, set_spawn_points); application.add_systems( PostStartup, spawn_firearm_on_player_hands, ); // Update - + add_all_spawners(application); application.add_systems(Update, capture_input); - //application.add_systems(Update, capture_cursor); application.add_systems(Update, sync_player_y_state); application.add_systems(Update, follow_cursor_with_camera); - application.add_systems(Update, asset_loaded); + 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); } diff --git a/src/scenes/scene1/mod.rs b/src/scenes/scene1/mod.rs index 3c16ac2..ef4f1c3 100644 --- a/src/scenes/scene1/mod.rs +++ b/src/scenes/scene1/mod.rs @@ -4,3 +4,4 @@ pub mod ground; pub mod lighting; pub mod obstacles; pub mod skybox; +pub mod spawn_points; \ No newline at end of file diff --git a/src/scenes/scene1/skybox.rs b/src/scenes/scene1/skybox.rs index 8f3678b..9fefb92 100644 --- a/src/scenes/scene1/skybox.rs +++ b/src/scenes/scene1/skybox.rs @@ -8,6 +8,8 @@ use bevy::{ }, }; +use crate::comps::core::markers::camera::MainCamera; + pub const CUBEMAPS: &[(&str, CompressedImageFormats)] = &[("skybox/skybox.png", CompressedImageFormats::NONE)]; @@ -17,11 +19,12 @@ pub struct Cubemap { pub image_handle: Handle, } -pub fn asset_loaded( +pub fn set_skybox_if_loaded( asset_server: Res, + mut commands: Commands, mut images: ResMut>, mut cubemap: ResMut, - mut skyboxes: Query<&mut Skybox>, + mut camera_query: Query>, ) { if !cubemap.is_loaded && asset_server.get_load_state(&cubemap.image_handle) == LoadState::Loaded { @@ -38,10 +41,9 @@ pub fn asset_loaded( }); } - for mut skybox in &mut skyboxes { - skybox.0 = cubemap.image_handle.clone(); + for camera_entity in camera_query.iter_mut() { + commands.entity(camera_entity).insert(Skybox(cubemap.image_handle.clone())); + cubemap.is_loaded = true; } - - cubemap.is_loaded = true; } } diff --git a/src/scenes/scene1/spawn_points.rs b/src/scenes/scene1/spawn_points.rs new file mode 100644 index 0000000..e1d9e02 --- /dev/null +++ b/src/scenes/scene1/spawn_points.rs @@ -0,0 +1,8 @@ +use bevy::prelude::*; + +use crate::{setup::spawn::SpawnPoint, comps::core::markers::player::Player}; + +pub fn set_spawn_points(mut commands: Commands) { + commands.spawn(SpawnPoint { at: Transform::from_xyz(3.0, 5.0, 2.0), what: Player }); + +} \ No newline at end of file diff --git a/src/setup/animations.rs b/src/setup/animations.rs index 179bca7..0083344 100644 --- a/src/setup/animations.rs +++ b/src/setup/animations.rs @@ -1,7 +1,44 @@ -use bevy::prelude::*; +use bevy::{prelude::*, gltf::Gltf}; + +use crate::logic::core::guns::firearm::Firearm; + +use super::{assets::GltfAssets, load_state::GameLoadState}; #[derive(Resource)] +pub struct AllFirearmAnimations { + pub animations: Vec, +} + pub struct FirearmAnimations { + pub firearm: Firearm, pub reload_magazine: Handle, +} + +/// System to load animations once the Gltf file is loaded. +pub fn load_animations( + mut commands: Commands, + assets_gltf: Res, + loaded_gltf_assets: Res>, + mut game_load_state: ResMut, +) { + if game_load_state.animations_loaded || !game_load_state.assets_loaded { + return; + } + + if assets_gltf.assets.len() != loaded_gltf_assets.len() { + return; + } + 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() }) + } + } + } + commands.insert_resource(all_firearm_animations); + game_load_state.animations_loaded = true; } \ No newline at end of file diff --git a/src/setup/assets.rs b/src/setup/assets.rs new file mode 100644 index 0000000..ee4adce --- /dev/null +++ b/src/setup/assets.rs @@ -0,0 +1,58 @@ +use bevy::{prelude::*, gltf::Gltf}; + +use crate::{logic::core::guns::firearm::Firearm, scenes::scene1::skybox::{CUBEMAPS, Cubemap}}; + +use super::load_state::GameLoadState; + +#[derive(PartialEq, Eq, PartialOrd, Ord)] +pub enum GltfAssetType { + Firearm(Firearm), + #[allow(unused)] + Enemy, +} +#[derive(Resource)] +pub struct GltfAssets { + pub assets: Vec +} +pub struct GltfAsset { + pub asset_type: GltfAssetType, + pub asset: Handle, +} + + +pub fn load_all_assets( + mut commands: Commands, + asset_server: Res, + mut game_load_state: ResMut, +) { + let skybox_handle: Handle = asset_server.load(CUBEMAPS[0].0); + commands.insert_resource(Cubemap { + 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) } ; + + commands.insert_resource(GltfAssets { + assets: Vec::from([ + m4a1_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. + // Meaning assets will be finished loading as soon as the first update system runs. +} + +impl GltfAssetType { + pub fn is_firearm(&self) -> bool { + match self { + GltfAssetType::Firearm(_) => true, + _ => false + } + } + pub fn get_firearm(&self) -> &Firearm { + match self { + GltfAssetType::Firearm(firearm) => firearm, + _ => panic!("Called get_firearm on Non-Firearm GltfAssetType"), + } + } +} \ No newline at end of file diff --git a/src/setup/gltf_assets.rs b/src/setup/gltf_assets.rs deleted file mode 100644 index 2a84e3a..0000000 --- a/src/setup/gltf_assets.rs +++ /dev/null @@ -1,30 +0,0 @@ -use bevy::{prelude::*, gltf::Gltf}; - -use crate::logic::core::guns::firearm::Firearm; - -use super::load_state::GameLoadState; - -#[derive(Resource)] -pub struct GltfAssets { - pub assets: Vec -} -pub struct GltfAsset { - pub id: String, - pub asset: Handle -} - - -pub fn load_all_assets( - mut commands: Commands, - asset_server: Res, - mut game_load_state: ResMut, -) { - let m4a1_gltf_asset = GltfAsset { id: Firearm::M4A1.firearm_data().identifier, asset: asset_server.load(Firearm::M4A1.firearm_data().asset_path) } ; - - commands.insert_resource(GltfAssets { - assets: Vec::from([ - m4a1_gltf_asset - ]) - }); - game_load_state.assets_loaded = true; -} \ No newline at end of file diff --git a/src/setup/load_state.rs b/src/setup/load_state.rs index 9bec042..26a8153 100644 --- a/src/setup/load_state.rs +++ b/src/setup/load_state.rs @@ -4,4 +4,12 @@ use bevy::prelude::*; pub struct GameLoadState { pub assets_loaded: bool, pub animations_loaded: bool, + pub player_loaded: bool, +} + +impl GameLoadState { + pub fn is_everything_except_player_loaded(&self) -> bool { + self.assets_loaded && + self.animations_loaded + } } \ No newline at end of file diff --git a/src/setup/mod.rs b/src/setup/mod.rs index 29b64f0..477898b 100644 --- a/src/setup/mod.rs +++ b/src/setup/mod.rs @@ -1,3 +1,5 @@ -pub mod gltf_assets; +pub mod assets; pub mod animations; -pub mod load_state; \ No newline at end of file +pub mod load_state; +pub mod spawn; +pub mod spawners; \ No newline at end of file diff --git a/src/setup/spawn.rs b/src/setup/spawn.rs new file mode 100644 index 0000000..4c1b552 --- /dev/null +++ b/src/setup/spawn.rs @@ -0,0 +1,14 @@ +use bevy::prelude::*; + +use super::spawners::{player::player_spawner, firearm::firearm_spawner}; + +/// Where some Bundle T will replace this. +#[derive(Component)] +pub struct SpawnPoint { + pub at: Transform, + pub what: T +} + +pub fn add_all_spawners(application: &mut App) { + application.add_systems(Update, (player_spawner, firearm_spawner)); +} \ No newline at end of file diff --git a/src/setup/spawners/firearm.rs b/src/setup/spawners/firearm.rs new file mode 100644 index 0000000..8691637 --- /dev/null +++ b/src/setup/spawners/firearm.rs @@ -0,0 +1,12 @@ +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)>, + mut game_load_state: ResMut, +) { + +} \ No newline at end of file diff --git a/src/setup/spawners/mod.rs b/src/setup/spawners/mod.rs new file mode 100644 index 0000000..b9163ef --- /dev/null +++ b/src/setup/spawners/mod.rs @@ -0,0 +1,2 @@ +pub mod player; +pub mod firearm; \ No newline at end of file diff --git a/src/setup/spawners/player.rs b/src/setup/spawners/player.rs new file mode 100644 index 0000000..e185d2c --- /dev/null +++ b/src/setup/spawners/player.rs @@ -0,0 +1,95 @@ +use bevy::prelude::*; +use bevy_rapier3d::prelude::*; + +use crate::{ + comps::core::markers::{ + camera::MainCamera, + player::{Player, PlayerHand}, + }, + constants::player_values::{ + PLAYER_GRAVITY_SCALE, PLAYER_HEIGHT, PLAYER_INITIAL_WEIGHT, PLAYER_LINEAR_DAMPING, + }, logic::core::player::player_movement::{PlayerLinearYState, PlayerLinearXZState}, setup::load_state::GameLoadState, +}; + +use crate::setup::spawn::SpawnPoint; + +/// System that runs every fame checking if player has been spawned. +/// For player to spawn, everything inside GameLoadState must be loaded Except player. +pub fn player_spawner( + mut commands: Commands, + player_sp_query: Query<(Entity, &SpawnPoint)>, + mut game_load_state: ResMut, +) { + if game_load_state.player_loaded || !game_load_state.is_everything_except_player_loaded() { + return; + } + + for (player_spawn_point_entity, player_spawn_point) in player_sp_query.iter() { + // Spawn hand + let player_hand = commands + .spawn(PlayerHand) + .insert(TransformBundle::from(Transform::from_xyz(0.6, -0.45, -20.0))) + .insert(VisibilityBundle { + visibility: Visibility::Inherited, + ..Default::default() + }) + .id(); + + // Spawn camera + let camera = commands + .spawn(MainCamera) + .insert(Camera3dBundle { + transform: Transform::from_xyz(0.0, 0.0, 0.0).looking_at(Vec3::ZERO, Vec3::Y), + ..Default::default() + }) + //s.insert(Skybox(skybox_handle.clone())) + .insert(VisibilityBundle { + visibility: Visibility::Inherited, + ..Default::default() + }) + .push_children(&[player_hand]) + .id(); + + // Spawn player + commands + .spawn(Player) + .insert(RigidBody::Dynamic) + .insert(GravityScale(PLAYER_GRAVITY_SCALE)) + .insert(Collider::capsule_y(PLAYER_HEIGHT, 2.0)) + .insert(Restitution::coefficient(0.0)) + .insert(Friction { + coefficient: 0.0, + combine_rule: CoefficientCombineRule::Multiply, + }) + .insert(TransformBundle { + local: player_spawn_point.at, + ..Default::default() + }) + .insert(Velocity::zero()) + .insert(Damping { + linear_damping: PLAYER_LINEAR_DAMPING, + angular_damping: 1.0, + }) + .insert( + LockedAxes::ROTATION_LOCKED_Z + | LockedAxes::ROTATION_LOCKED_X + | LockedAxes::ROTATION_LOCKED_Y, + ) + .insert(ColliderMassProperties::Mass(PLAYER_INITIAL_WEIGHT)) + .insert(ExternalImpulse { + impulse: Vec3::ZERO, + torque_impulse: Vec3::ZERO, + }) + .insert(PlayerLinearYState::Falling) + .insert(PlayerLinearXZState::Stopped) + .insert(VisibilityBundle { + visibility: Visibility::Visible, + ..Default::default() + }) + .push_children(&[camera]); + + + commands.entity(player_spawn_point_entity).despawn(); + game_load_state.player_loaded = true; + } +} \ No newline at end of file