RELOAD SYSTEM WITH ANIMATION DONE!

This commit is contained in:
Franklin Blanco 2023-09-17 18:01:37 -07:00
parent c186019b52
commit 7783c4a165
7 changed files with 89 additions and 71 deletions

Binary file not shown.

View File

@ -14,6 +14,7 @@ pub struct PlayerFiringInfo {
/// Decreases with time, each gun has its own rebound time /// Decreases with time, each gun has its own rebound time
pub current_round_index: usize, pub current_round_index: usize,
pub full_auto_timer: Timer, pub full_auto_timer: Timer,
pub is_reloading: bool,
} }
impl Default for PlayerFiringInfo { impl Default for PlayerFiringInfo {
@ -23,6 +24,7 @@ impl Default for PlayerFiringInfo {
rounds_in_last_spray: Default::default(), rounds_in_last_spray: Default::default(),
current_round_index: Default::default(), current_round_index: Default::default(),
full_auto_timer: Timer::new(Duration::from_secs_f32(0.0), TimerMode::Repeating), full_auto_timer: Timer::new(Duration::from_secs_f32(0.0), TimerMode::Repeating),
is_reloading: false,
} }
} }
} }

View File

@ -45,7 +45,6 @@ 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))})
rock_charging_handle: asset_server.load(format!("{}#Animation1", DEFAULT_PLAYER_FIREARM.firearm_data().asset_path)) })
} }
} }

View File

@ -1,12 +0,0 @@
use bevy::prelude::*;
use crate::setup::animations::FirearmAnimations;
pub fn setup_scene_once_loaded(
animations: Res<FirearmAnimations>,
mut players: Query<&mut AnimationPlayer, Added<AnimationPlayer>>,
) {
for mut player in &mut players {
player.play(animations.reload_magazine.clone_weak()).repeat();
}
}

View File

@ -2,11 +2,12 @@ use bevy::prelude::*;
use crate::{ use crate::{
comps::core::markers::{firearm::{FirearmData, MagazineData}, holdable::InPlayerHands, player::PlayerHand}, comps::core::markers::{firearm::{FirearmData, MagazineData}, holdable::InPlayerHands, player::PlayerHand},
logic::core::guns::player_firing::PlayerFiringInfo, utils::rad_deg::radians_from_degrees, logic::core::guns::player_firing::PlayerFiringInfo, utils::rad_deg::radians_from_degrees, setup::animations::FirearmAnimations,
}; };
pub fn capture_hand_usage( pub fn capture_hand_usage(
mouse_buttons: Res<Input<MouseButton>>, mouse_buttons: Res<Input<MouseButton>>,
keyboard_input: Res<Input<KeyCode>>,
mut hand_query: Query<&mut Transform, With<PlayerHand>>, mut hand_query: Query<&mut Transform, With<PlayerHand>>,
time: Res<Time>, time: Res<Time>,
@ -15,69 +16,97 @@ pub fn capture_hand_usage(
(&mut Transform, &'static FirearmData, &mut MagazineData), (&mut Transform, &'static FirearmData, &mut MagazineData),
(With<InPlayerHands>, Without<PlayerHand>), (With<InPlayerHands>, Without<PlayerHand>),
>, >,
animation_clips: Res<Assets<AnimationClip>>,
animations: Res<FirearmAnimations>,
mut players: Query<&mut AnimationPlayer>,
) { ) {
player_firing_info.full_auto_timer.tick(time.delta()); player_firing_info.full_auto_timer.tick(time.delta());
for (mut _firearm_transform, firearm_data, mut magazine_data) in firearm_query.iter_mut() { for (mut _firearm_transform, firearm_data, mut magazine_data) in firearm_query.iter_mut() {
for mut hand_transform in hand_query.iter_mut() { for mut hand_transform in hand_query.iter_mut() {
// AIMING IN/OUT
if mouse_buttons.pressed(MouseButton::Right) {
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),
);
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),
);
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));
hand_transform.translation = hand_transform.translation.lerp(
firearm_data.final_position,
(time.delta_seconds() / firearm_data.rebound_time_seconds).clamp(0.0, 1.0),
);
}
// SHOOTING & RECOIL
if mouse_buttons.pressed(MouseButton::Left) {
if player_firing_info.full_auto_timer.finished() {
if magazine_data.rounds_shot < magazine_data.max_capacity {
// Get recoil numbers from patterns
let vertical_recoil_number: f32 = match firearm_data.recoil_pattern.vertical.get(player_firing_info.current_round_index) {
Some(vert_recoil_number) => *vert_recoil_number,
None => {
*firearm_data.recoil_pattern.vertical.last().expect("FOUND A FIREARM_DATA WITHOUT ANY FIREARM_RECOIL_PATTERN.")
},
};
let horizontal_recoil_number: f32 = match firearm_data.recoil_pattern.horizontal.get(player_firing_info.current_round_index) {
Some(horizontal_recoil_number) => *horizontal_recoil_number,
None => {
*firearm_data.recoil_pattern.horizontal.last().expect("FOUND A FIREARM_DATA WITHOUT ANY FIREARM_RECOIL_PATTERN.")
},
};
// Increment indexes and timers
player_firing_info.current_round_index += 1;
player_firing_info.last_shot_timestamp = time.elapsed_seconds();
player_firing_info.full_auto_timer.reset();
magazine_data.rounds_shot += 1;
// Apply recoil if player_firing_info.is_reloading {
hand_transform for mut player in &mut players {
.rotate_x(radians_from_degrees(firearm_data.vertical_recoil_modifier * vertical_recoil_number)); if let Some(reload_animation) = animation_clips.get(&animations.reload_magazine) {
hand_transform.rotate_y(radians_from_degrees(firearm_data.horizontal_recoil_modifier * horizontal_recoil_number)); if player.elapsed() >= reload_animation.duration() {
} else { magazine_data.rounds_shot = 0;
//TODO: play magazine empty sound 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 {
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
} }
} else { // AIMING IN/OUT
if player_firing_info.full_auto_timer.finished() { if mouse_buttons.pressed(MouseButton::Right) {
player_firing_info.current_round_index = 0; 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),
);
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),
);
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));
hand_transform.translation = hand_transform.translation.lerp(
firearm_data.final_position,
(time.delta_seconds() / firearm_data.rebound_time_seconds).clamp(0.0, 1.0),
);
}
// SHOOTING & RECOIL
if mouse_buttons.pressed(MouseButton::Left) {
if player_firing_info.full_auto_timer.finished() {
if magazine_data.rounds_shot < magazine_data.max_capacity {
// Get recoil numbers from patterns
let vertical_recoil_number: f32 = match firearm_data.recoil_pattern.vertical.get(player_firing_info.current_round_index) {
Some(vert_recoil_number) => *vert_recoil_number,
None => {
*firearm_data.recoil_pattern.vertical.last().expect("FOUND A FIREARM_DATA WITHOUT ANY FIREARM_RECOIL_PATTERN.")
},
};
let horizontal_recoil_number: f32 = match firearm_data.recoil_pattern.horizontal.get(player_firing_info.current_round_index) {
Some(horizontal_recoil_number) => *horizontal_recoil_number,
None => {
*firearm_data.recoil_pattern.horizontal.last().expect("FOUND A FIREARM_DATA WITHOUT ANY FIREARM_RECOIL_PATTERN.")
},
};
// Increment indexes and timers
player_firing_info.current_round_index += 1;
player_firing_info.last_shot_timestamp = time.elapsed_seconds();
player_firing_info.full_auto_timer.reset();
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));
} else {
//TODO: play magazine empty sound
}
}
} else {
if player_firing_info.full_auto_timer.finished() {
player_firing_info.current_round_index = 0;
}
} }
} }
} }
} }

View File

@ -10,7 +10,7 @@ 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, camera_effects::setup_scene_once_loaded, spawn_player::spawn_player,
}, },
}, },
}; };
@ -43,6 +43,6 @@ pub fn load_scene(application: &mut App) {
application.add_systems(Update, capture_hand_usage); application.add_systems(Update, capture_hand_usage);
application.add_systems(Startup, setup_lighting); application.add_systems(Startup, setup_lighting);
application.add_systems(Update, setup_scene_once_loaded); //application.add_systems(Update, setup_scene_once_loaded);
//application.add_systems(Update, play_animation); //application.add_systems(Update, play_animation);
} }

View File

@ -3,5 +3,5 @@ use bevy::prelude::*;
#[derive(Resource)] #[derive(Resource)]
pub struct FirearmAnimations { pub struct FirearmAnimations {
pub reload_magazine: Handle<AnimationClip>, pub reload_magazine: Handle<AnimationClip>,
pub rock_charging_handle: Handle<AnimationClip>,
} }