Replaced animation, asset, spawning system with modular system that does all. At this point there is no weapon spawning on the player just yet.

This commit is contained in:
Franklin Blanco 2023-09-18 12:31:20 -07:00
parent 785bd89b6b
commit 57587d1586
21 changed files with 272 additions and 155 deletions

View File

@ -0,0 +1,7 @@
#[allow(unused)]
/// System that checks if player
pub fn equip_firearm() {
}

View File

@ -3,6 +3,7 @@ use bevy::prelude::*;
use super::{caliber::Caliber, spray_pattern::FirearmSprayPattern}; use super::{caliber::Caliber, spray_pattern::FirearmSprayPattern};
#[derive(Component, PartialEq, Eq, PartialOrd, Ord, Clone)]
pub enum Firearm { pub enum Firearm {
M4A1, M4A1,
} }

View File

@ -5,7 +5,7 @@ use bevy::{prelude::*, gltf::Gltf};
use crate::{ use crate::{
comps::core::markers::{holdable::InPlayerHands, player::PlayerHand, firearm::{MagazineData, FirearmData}}, comps::core::markers::{holdable::InPlayerHands, player::PlayerHand, firearm::{MagazineData, FirearmData}},
constants::player_values::DEFAULT_PLAYER_FIREARM, 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}; 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( pub fn spawn_firearm_on_player_hands(
mut commands: Commands, mut commands: Commands,
query: Query<Entity, With<PlayerHand>>, query: Query<Entity, With<PlayerHand>>,
asset_server: Res<AssetServer>,
mut player_firing_info: ResMut<PlayerFiringInfo>, mut player_firing_info: ResMut<PlayerFiringInfo>,
assets_gltf: Res<GltfAssets>, assets_gltf: Res<GltfAssets>,
loaded_gltf_assets: Res<Assets<Gltf>>, loaded_gltf_assets: Res<Assets<Gltf>>,
) { ) {
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) { if let Some(gltf) = loaded_gltf_assets.get(&asset_handle.asset) {
println!("C");
for entity in query.iter() { for entity in query.iter() {
let mut firearm_transform = Transform::from_xyz(0.0, 0.0, 0.0); let mut firearm_transform = Transform::from_xyz(0.0, 0.0, 0.0);
firearm_transform.rotate_y(utils::rad_deg::radians_from_degrees( firearm_transform.rotate_y(utils::rad_deg::radians_from_degrees(
@ -38,7 +36,6 @@ pub fn spawn_firearm_on_player_hands(
..default() ..default()
}, },
DEFAULT_PLAYER_FIREARM.firearm_data(), DEFAULT_PLAYER_FIREARM.firearm_data(),
FirearmAnimations { reload_magazine: todo!() },
DEFAULT_PLAYER_FIREARM.holdable_object_data(), DEFAULT_PLAYER_FIREARM.holdable_object_data(),
MagazineData { rounds_shot: 0, max_capacity: DEFAULT_PLAYER_FIREARM.firearm_data().max_capacity }, MagazineData { rounds_shot: 0, max_capacity: DEFAULT_PLAYER_FIREARM.firearm_data().max_capacity },
InPlayerHands, InPlayerHands,
@ -54,7 +51,7 @@ pub fn spawn_firearm_on_player_hands(
TimerMode::Once, TimerMode::Once,
); );
// Load animations // 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))})
} }
} }
} }

View File

@ -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<Assets<Gltf>>,
asset_server: Res<AssetServer>,
) {
for asset in gltf_assets.iter() {
}
}

View File

@ -18,8 +18,6 @@ pub fn capture_hand_usage(
>, >,
animation_clips: Res<Assets<AnimationClip>>, animation_clips: Res<Assets<AnimationClip>>,
animations: Res<FirearmAnimations>,
mut players: Query<&mut AnimationPlayer>, mut players: Query<&mut AnimationPlayer>,
) { ) {
player_firing_info.full_auto_timer.tick(time.delta()); player_firing_info.full_auto_timer.tick(time.delta());
@ -29,20 +27,20 @@ pub fn capture_hand_usage(
if player_firing_info.is_reloading { if player_firing_info.is_reloading {
for player in &mut players { 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() { if player.elapsed() >= reload_animation.duration() {
magazine_data.rounds_shot = 0; magazine_data.rounds_shot = 0;
player_firing_info.is_reloading = false; player_firing_info.is_reloading = false;
} }
} }*/
} }
} else { // Player is not in a reload animation } else { // Player is not in a reload animation
if keyboard_input.just_pressed(KeyCode::R) { if keyboard_input.just_pressed(KeyCode::R) {
// Start reload animation // Start reload animation
for mut player in &mut players { /*for mut player in &mut players {
player.start(animations.reload_magazine.clone_weak()); player.start(animations.reload_magazine.clone_weak());
player_firing_info.is_reloading = true; player_firing_info.is_reloading = true;
} }*/
// Set is_reloading = true // Set is_reloading = true
// At the end of reload animation, set magazine data to capacity = 0 // At the end of reload animation, set magazine data to capacity = 0
} }

View File

@ -3,4 +3,3 @@ pub mod camera_player_sync;
pub mod hands; pub mod hands;
pub mod player_movement; pub mod player_movement;
pub mod player_vertical_sync; pub mod player_vertical_sync;
pub mod spawn_player;

View File

@ -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<AssetServer>) {
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,
});
}

View File

@ -10,14 +10,12 @@ use crate::{
}, },
hands::capture_hand_usage, hands::capture_hand_usage,
player_vertical_sync::sync_player_y_state, 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::{ use super::{
ground::spawn_ground, lighting::setup_lighting, obstacles::spawn_obstacles, ground::spawn_ground, lighting::setup_lighting, obstacles::spawn_obstacles, skybox::set_skybox_if_loaded, spawn_points::set_spawn_points,
skybox::asset_loaded,
}; };
pub fn load_scene(application: &mut App) { 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(PreStartup, load_all_assets);
application.add_systems(Startup, spawn_ground); application.add_systems(Startup, spawn_ground);
application.add_systems(Startup, spawn_obstacles); 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, setup_lighting);
application.add_systems(Startup, set_spawn_points);
application.add_systems( application.add_systems(
PostStartup, PostStartup,
spawn_firearm_on_player_hands, spawn_firearm_on_player_hands,
); );
// Update // Update
add_all_spawners(application);
application.add_systems(Update, capture_input); application.add_systems(Update, capture_input);
//application.add_systems(Update, capture_cursor);
application.add_systems(Update, sync_player_y_state); application.add_systems(Update, sync_player_y_state);
application.add_systems(Update, follow_cursor_with_camera); 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, update_camera_vertical_position);
application.add_systems(Update, capture_hand_usage); application.add_systems(Update, capture_hand_usage);
} }

View File

@ -4,3 +4,4 @@ pub mod ground;
pub mod lighting; pub mod lighting;
pub mod obstacles; pub mod obstacles;
pub mod skybox; pub mod skybox;
pub mod spawn_points;

View File

@ -8,6 +8,8 @@ use bevy::{
}, },
}; };
use crate::comps::core::markers::camera::MainCamera;
pub const CUBEMAPS: &[(&str, CompressedImageFormats)] = pub const CUBEMAPS: &[(&str, CompressedImageFormats)] =
&[("skybox/skybox.png", CompressedImageFormats::NONE)]; &[("skybox/skybox.png", CompressedImageFormats::NONE)];
@ -17,11 +19,12 @@ pub struct Cubemap {
pub image_handle: Handle<Image>, pub image_handle: Handle<Image>,
} }
pub fn asset_loaded( pub fn set_skybox_if_loaded(
asset_server: Res<AssetServer>, asset_server: Res<AssetServer>,
mut commands: Commands,
mut images: ResMut<Assets<Image>>, mut images: ResMut<Assets<Image>>,
mut cubemap: ResMut<Cubemap>, mut cubemap: ResMut<Cubemap>,
mut skyboxes: Query<&mut Skybox>, mut camera_query: Query<Entity, With<MainCamera>>,
) { ) {
if !cubemap.is_loaded && asset_server.get_load_state(&cubemap.image_handle) == LoadState::Loaded 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 { for camera_entity in camera_query.iter_mut() {
skybox.0 = cubemap.image_handle.clone(); commands.entity(camera_entity).insert(Skybox(cubemap.image_handle.clone()));
}
cubemap.is_loaded = true; cubemap.is_loaded = true;
} }
}
} }

View File

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

View File

@ -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)] #[derive(Resource)]
pub struct AllFirearmAnimations {
pub animations: Vec<FirearmAnimations>,
}
pub struct FirearmAnimations { pub struct FirearmAnimations {
pub firearm: Firearm,
pub reload_magazine: Handle<AnimationClip>, pub reload_magazine: Handle<AnimationClip>,
} }
/// System to load animations once the Gltf file is loaded.
pub fn load_animations(
mut commands: Commands,
assets_gltf: Res<GltfAssets>,
loaded_gltf_assets: Res<Assets<Gltf>>,
mut game_load_state: ResMut<GameLoadState>,
) {
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;
}

58
src/setup/assets.rs Normal file
View File

@ -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<GltfAsset>
}
pub struct GltfAsset {
pub asset_type: GltfAssetType,
pub asset: Handle<Gltf>,
}
pub fn load_all_assets(
mut commands: Commands,
asset_server: Res<AssetServer>,
mut game_load_state: ResMut<GameLoadState>,
) {
let skybox_handle: Handle<Image> = 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"),
}
}
}

View File

@ -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<GltfAsset>
}
pub struct GltfAsset {
pub id: String,
pub asset: Handle<Gltf>
}
pub fn load_all_assets(
mut commands: Commands,
asset_server: Res<AssetServer>,
mut game_load_state: ResMut<GameLoadState>,
) {
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;
}

View File

@ -4,4 +4,12 @@ use bevy::prelude::*;
pub struct GameLoadState { pub struct GameLoadState {
pub assets_loaded: bool, pub assets_loaded: bool,
pub animations_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
}
} }

View File

@ -1,3 +1,5 @@
pub mod gltf_assets; pub mod assets;
pub mod animations; pub mod animations;
pub mod load_state; pub mod load_state;
pub mod spawn;
pub mod spawners;

14
src/setup/spawn.rs Normal file
View File

@ -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<T: Bundle> {
pub at: Transform,
pub what: T
}
pub fn add_all_spawners(application: &mut App) {
application.add_systems(Update, (player_spawner, firearm_spawner));
}

View File

@ -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<Firearm>)>,
mut game_load_state: ResMut<GameLoadState>,
) {
}

View File

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

View File

@ -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<Player>)>,
mut game_load_state: ResMut<GameLoadState>,
) {
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;
}
}