High ready + Low ready system. With animations and logic flows with sprinting, shooting, reloading, and aiming

This commit is contained in:
Franklin 2023-11-23 17:28:48 -04:00
parent 1a7a5e6024
commit 24df81424b
12 changed files with 145 additions and 36 deletions

View File

@ -23,12 +23,17 @@ Multiplayer
- [x] Snap back leaning too quick - [x] Snap back leaning too quick
- [x] Issue with moving around quickly - [x] Issue with moving around quickly
- [x] Bring Crouching back - [x] Bring Crouching back
- [ ] Inspect animation (procedural) - [x] Inspect animation & state (procedural)
- [ ] Attachment editor system when in inspect mode
- [x] High Ready & Low Ready system with state
- [x] High ready animation (procedural)
- [x] Low ready animation (procedural)
- [ ] Reload animation (procedural) - [ ] Reload animation (procedural)
- [ ] Real world magazines - [ ] Real world magazines
- [ ] Rewriting bullet physics to use raycasts & kinematic rigidbodies (logic controlled) - [ ] Rewriting bullet physics to use raycasts & kinematic rigidbodies (logic controlled)
- [ ] Low Ready & High ready (low ready == more speed | high ready == more accuracy) - [ ] Low Ready & High ready (low ready == more speed | high ready == more accuracy)
- [ ] Auto Low ready when gun collider hits object OR when player starts sprinting - [ ] Auto Low ready when gun collider hits object OR when player starts sprinting
- [ ] Create a Controls struct that holds mappings to all the game keys and replace them in all the game's code
# Design # Design

Binary file not shown.

View File

@ -2,12 +2,12 @@ use bevy::prelude::*;
use bevy_rapier3d::prelude::*; use bevy_rapier3d::prelude::*;
use crate::{ use crate::{
logic::core::player::{ logic::core::{player::{
player_movement::{ player_movement::{
move_player, PlayerLinearXZState, PlayerLinearYState, PlayerMovementInput, move_player, PlayerLinearXZState, PlayerLinearYState, PlayerMovementInput,
}, },
player_values_state::PlayerValuesState, player_values_state::PlayerValuesState,
}, }, guns::player_firing::PlayerFiringInfo},
ui::game::game_ui_state::GameUiState, ui::game::game_ui_state::GameUiState,
}; };
@ -24,6 +24,7 @@ pub fn capture_input(
&mut PlayerLinearXZState, &mut PlayerLinearXZState,
&mut Transform, &mut Transform,
&mut Damping, &mut Damping,
&mut PlayerFiringInfo,
), ),
With<Player>, With<Player>,
>, >,

View File

@ -0,0 +1,31 @@
use bevy::prelude::*;
use crate::comps::core::markers::{proxy::{character::in_player_hands_parent::InPlayerHandsParent, physics::utils::TransformExt}, player::Player};
use super::player_firing::PlayerFiringInfo;
pub fn inspect_firearm(
//mut commands: Commands,
mut in_player_hands_parent_query: Query<&mut Transform, With<InPlayerHandsParent>>,
mut player_firing_info_query: Query<&mut PlayerFiringInfo, With<Player>>,
time: Res<Time>,
keyboard_input: Res<Input<KeyCode>>,
) {
for mut player_firing_info in player_firing_info_query.iter_mut() {
for mut in_player_hands_parent_transform in in_player_hands_parent_query.iter_mut() {
if player_firing_info.is_inspecting {
let inspect_hand_transform: Transform = Transform {
translation: Vec3 { x: 0.0, y: -0.1, z: -0.8 },
rotation: Quat::from_euler(EulerRot::XYZ, -2.6, -1.0, -2.5),
..Default::default()
};
*in_player_hands_parent_transform = in_player_hands_parent_transform.lerp(inspect_hand_transform, time.delta_seconds() / 0.5);
if keyboard_input.just_pressed(KeyCode::Return) {
player_firing_info.is_inspecting = false;
}
}
}
}
}

View File

@ -1,3 +1,4 @@
pub mod despawn_shots; pub mod despawn_shots;
pub mod player_firing; pub mod player_firing;
pub mod shoot; pub mod shoot;
pub mod inspect;

View File

@ -2,6 +2,13 @@ use std::time::Duration;
use bevy::prelude::*; use bevy::prelude::*;
#[derive(Reflect, Default, PartialEq, Eq, PartialOrd, Ord, Clone)]
pub enum GunReadyPose {
#[default]
LowReady,
HighReady,
}
#[derive(Component, Reflect)] #[derive(Component, Reflect)]
#[reflect(Component)] #[reflect(Component)]
pub struct PlayerFiringInfo { pub struct PlayerFiringInfo {
@ -15,6 +22,8 @@ pub struct PlayerFiringInfo {
pub current_round_index: usize, pub current_round_index: usize,
pub full_auto_timer: Timer, pub full_auto_timer: Timer,
pub is_reloading: bool, pub is_reloading: bool,
pub gun_ready_pose: GunReadyPose,
pub is_inspecting: bool,
} }
impl Default for PlayerFiringInfo { impl Default for PlayerFiringInfo {
@ -25,6 +34,8 @@ impl Default for PlayerFiringInfo {
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, is_reloading: false,
gun_ready_pose: GunReadyPose::LowReady,
is_inspecting: false,
} }
} }
} }

View File

@ -38,24 +38,26 @@ pub fn shoot_bullet(
}, },
MuzzleFlashMarker(Timer::new(Duration::from_millis(10), TimerMode::Once)), MuzzleFlashMarker(Timer::new(Duration::from_millis(10), TimerMode::Once)),
)); ));
// Spawn Line
commands.spawn( // Spawn Line
MaterialMeshBundle { if player_settings.shot_lines_enabled {
mesh: { commands.spawn(
let mut mesh = Mesh::new(PrimitiveTopology::LineStrip); MaterialMeshBundle {
mesh.insert_attribute(Mesh::ATTRIBUTE_POSITION, Vec::from([Vec3::ZERO, forward * caliber.range()])); mesh: {
meshes.add(mesh) let mut mesh = Mesh::new(PrimitiveTopology::LineStrip);
}, mesh.insert_attribute(Mesh::ATTRIBUTE_POSITION, Vec::from([Vec3::ZERO, forward * caliber.range()]));
material: materials.add(StandardMaterial { meshes.add(mesh)
base_color: Color::GREEN, },
material: materials.add(StandardMaterial {
base_color: Color::GREEN,
..Default::default()
}),
visibility: Visibility::Visible,
transform: firing_point,
..Default::default() ..Default::default()
}), }
visibility: Visibility::Visible, );
transform: firing_point, }
..Default::default()
}
);
spawn_bullet( spawn_bullet(
commands, commands,

View File

@ -1,4 +1,4 @@
use bevy::{ecs::system::SystemParam, prelude::*, gltf::Gltf}; use bevy::{ecs::system::SystemParam, prelude::*, gltf::Gltf, input::mouse::MouseWheel};
use bevy_rapier3d::prelude::*; use bevy_rapier3d::prelude::*;
use crate::{ use crate::{
@ -9,10 +9,10 @@ use crate::{
camera::MainCamera, camera::MainCamera,
holdable::InPlayerHands, holdable::InPlayerHands,
interactable::Interactable, interactable::Interactable,
player::Player, proxy::{character::in_player_hands_parent::InPlayerHandsParent, physics::rapier::LinkToPlayer}, player::Player, proxy::{character::in_player_hands_parent::InPlayerHandsParent, physics::{rapier::LinkToPlayer, utils::TransformExt}},
}, weapons::{firearm::Firearm, firearm_state::FirearmState, parts::firing_point::FiringPoint}, }, weapons::{firearm::Firearm, firearm_state::FirearmState, parts::firing_point::FiringPoint},
}, },
logic::core::guns::{player_firing::PlayerFiringInfo, shoot::shoot_bullet}, logic::core::guns::{player_firing::{PlayerFiringInfo, GunReadyPose}, shoot::shoot_bullet},
setup::{ setup::{
equipment::{Equipment, EquipmentChangeEvent}, equipment::{Equipment, EquipmentChangeEvent},
load_state::GameLoadState, assets::GltfAssets, //animations::AllAnimations, load_state::GameLoadState, assets::GltfAssets, //animations::AllAnimations,
@ -21,7 +21,7 @@ use crate::{
utils::{rad_deg::radians_from_degrees, hierarchy::find_child_in_parent_children}, utils::{rad_deg::radians_from_degrees, hierarchy::find_child_in_parent_children},
}; };
use super::player_settings::PlayerSettings; use super::{player_settings::PlayerSettings, player_movement::PlayerLinearXZState};
#[derive(SystemParam)] #[derive(SystemParam)]
pub struct CaptureHandUsageResourcesParams<'w> { pub struct CaptureHandUsageResourcesParams<'w> {
@ -45,7 +45,7 @@ pub struct CaptureHandUsageQueryParams<'w, 's> {
in_hand_query: Query<'w, 's, (&'static Parent, &'static mut Transform), (With<InPlayerHands>, Without<InPlayerHandsParent>, Without<PlayerInventory>)>, in_hand_query: Query<'w, 's, (&'static Parent, &'static mut Transform), (With<InPlayerHands>, Without<InPlayerHandsParent>, Without<PlayerInventory>)>,
firearms_query: Query<'w, 's, (Entity, &'static GlobalTransform, &'static Firearm, &'static mut FirearmState),>, firearms_query: Query<'w, 's, (Entity, &'static GlobalTransform, &'static Firearm, &'static mut FirearmState),>,
firing_point_query: Query<'w, 's, (&'static GlobalTransform, &'static Parent), With<FiringPoint>>, firing_point_query: Query<'w, 's, (&'static GlobalTransform, &'static Parent), With<FiringPoint>>,
player_query: Query<'w, 's, (&'static Player, &'static mut PlayerInventory, Entity, &'static Transform, &'static mut PlayerFiringInfo), Without<InPlayerHands>>, player_query: Query<'w, 's, (&'static Player, &'static mut PlayerInventory, Entity, &'static Transform, &'static mut PlayerFiringInfo, &'static PlayerLinearXZState), Without<InPlayerHands>>,
children: Query<'w, 's, &'static Children>, children: Query<'w, 's, &'static Children>,
} }
@ -58,6 +58,7 @@ pub fn capture_hand_usage(
mut equipment_change_event_writer: EventWriter<EquipmentChangeEvent>, mut equipment_change_event_writer: EventWriter<EquipmentChangeEvent>,
mut inventory_changed_events: EventWriter<PlayerInventoryChangedEvent>, mut inventory_changed_events: EventWriter<PlayerInventoryChangedEvent>,
mut mouse_wheel_events: EventReader<MouseWheel>,
) { ) {
if !resources.game_load_state.player_loaded { if !resources.game_load_state.player_loaded {
return; return;
@ -65,9 +66,32 @@ pub fn capture_hand_usage(
// Equipping stuff // Equipping stuff
for (player, mut player_inventory, player_entity, player_transform, mut player_firing_info) in queries.player_query.iter_mut() { for (player, mut player_inventory, player_entity, player_transform, mut player_firing_info, player_linear_xz_state) in queries.player_query.iter_mut() {
// Equipping gun // Equipping gun
// Validate player has primary item, and secondary item in inventory // Validate player has primary item, and secondary item in inventory
if player_firing_info.is_inspecting {
continue;
}
for (mut hand_transform, _) in queries.hand_query.iter_mut() {
let default_hand_transform: Transform = match player_firing_info.gun_ready_pose {
GunReadyPose::LowReady => {
Transform {
translation: Vec3 { x: -0.2, y: -0.3, z: -0.8 },
rotation: Quat::from_euler(EulerRot::XYZ, -3.6, -0.6, -3.3),
..Default::default()
}
},
GunReadyPose::HighReady => {
Transform {
translation: Vec3 { x: 0.039, y: -0.193, z: -0.453 },
rotation: Quat::from_euler(EulerRot::XYZ, -180.0f32.to_radians(), 0.0, -180.0f32.to_radians()),
..Default::default()
}
},
};
*hand_transform = hand_transform.lerp(default_hand_transform, resources.time.delta_seconds() / 0.25);
}
if !resources.game_ui_state.any_window() && !player_firing_info.is_reloading { if !resources.game_ui_state.any_window() && !player_firing_info.is_reloading {
if resources.keyboard_input.just_pressed(KeyCode::Key1) { if resources.keyboard_input.just_pressed(KeyCode::Key1) {
if let Some(primary_item) = player_inventory.get_primary() { if let Some(primary_item) = player_inventory.get_primary() {
@ -113,6 +137,20 @@ pub fn capture_hand_usage(
}, },
None => {}, None => {},
} }
} else if resources.keyboard_input.just_pressed(KeyCode::I) {
if player.0.equipment.is_firearm() {
player_firing_info.is_inspecting = true;
}
} else if !mouse_wheel_events.is_empty() {
if player.0.equipment.is_firearm() {
for mouse_wheel_event in mouse_wheel_events.read() {
if mouse_wheel_event.y >= 0.0 {
player_firing_info.gun_ready_pose = GunReadyPose::HighReady;
} else {
player_firing_info.gun_ready_pose = GunReadyPose::LowReady;
}
}
}
} }
} }
@ -158,8 +196,9 @@ pub fn capture_hand_usage(
} }
}; };
if resources.mouse_buttons.pressed(MouseButton::Right) if resources.mouse_buttons.pressed(MouseButton::Right)
&& !resources.game_ui_state.any_window() && !resources.game_ui_state.any_window() && !player_linear_xz_state.is_sprinting()
{ {
player_firing_info.gun_ready_pose = GunReadyPose::HighReady;
let rotation_lerp_quat = in_hand_transform.rotation.lerp( let rotation_lerp_quat = in_hand_transform.rotation.lerp(
firearm_data.final_aimed_rotation + resources.player_settings.rot_aimed_offset, firearm_data.final_aimed_rotation + resources.player_settings.rot_aimed_offset,
(resources.time.delta_seconds() (resources.time.delta_seconds()
@ -191,7 +230,7 @@ pub fn capture_hand_usage(
// SHOOTING & RECOIL // SHOOTING & RECOIL
if resources.mouse_buttons.pressed(MouseButton::Left) if resources.mouse_buttons.pressed(MouseButton::Left)
&& !resources.game_ui_state.any_window() && !resources.game_ui_state.any_window() && player_firing_info.gun_ready_pose == GunReadyPose::HighReady
{ {
if let Some(magazine_data) = &mut firearm_state.magazine_data { if let Some(magazine_data) = &mut firearm_state.magazine_data {
if player_firing_info.full_auto_timer.finished() { if player_firing_info.full_auto_timer.finished() {

View File

@ -1,7 +1,7 @@
use bevy::prelude::*; use bevy::prelude::*;
use bevy_rapier3d::prelude::*; use bevy_rapier3d::prelude::*;
use crate::comps::core::markers::player::Player; use crate::{comps::core::markers::player::Player, logic::core::guns::player_firing::{PlayerFiringInfo, GunReadyPose}};
use super::player_values_state::PlayerValuesState; use super::player_values_state::PlayerValuesState;
@ -111,6 +111,7 @@ pub fn move_player(
&mut PlayerLinearXZState, &mut PlayerLinearXZState,
&mut Transform, &mut Transform,
&mut Damping, &mut Damping,
&mut PlayerFiringInfo,
), ),
With<Player>, With<Player>,
>, >,
@ -124,16 +125,21 @@ pub fn move_player(
mut player_linear_xz_state, mut player_linear_xz_state,
player_transform, player_transform,
mut player_damping, mut player_damping,
mut player_firing_info,
) in &mut query ) in &mut query
{ {
if player_linear_xz_state.is_sprinting() {
player_firing_info.gun_ready_pose = GunReadyPose::LowReady;
}
if player_movement_input.down { if player_movement_input.down {
player_linear_xz_state.toggle_crouch(time.elapsed().as_secs_f32()); player_linear_xz_state.toggle_crouch(time.elapsed().as_secs_f32());
} }
let crouch_multiplier = if player_linear_xz_state.is_crouched() { let crouch_multiplier =
player_values_state.player_crouch_speed_multiplier if player_linear_xz_state.is_crouched() {
} else { player_values_state.player_crouch_speed_multiplier
1.0 } else {
}; 1.0
};
let sprint_multiplier = let sprint_multiplier =
if player_movement_input.sprint && !player_linear_xz_state.is_crouched() { if player_movement_input.sprint && !player_linear_xz_state.is_crouched() {
player_values_state.player_sprint_speed_multiplier player_values_state.player_sprint_speed_multiplier

View File

@ -8,7 +8,7 @@ pub struct PlayerSettings {
//pub gun_offset: f32, //pub gun_offset: f32,
pub fov: f32, pub fov: f32,
/// Debug thing for me /// Debug things for me
pub pos_aimed_offset: Vec3, pub pos_aimed_offset: Vec3,
pub pos_offset: Vec3, pub pos_offset: Vec3,
@ -16,6 +16,8 @@ pub struct PlayerSettings {
pub rot_offset: Quat, pub rot_offset: Quat,
pub third_person_toggle: bool, pub third_person_toggle: bool,
pub shot_lines_enabled: bool,
} }
impl Default for PlayerSettings { impl Default for PlayerSettings {
@ -26,7 +28,8 @@ impl Default for PlayerSettings {
pos_offset: Vec3::ZERO, pos_offset: Vec3::ZERO,
rot_aimed_offset: Quat::default(), rot_aimed_offset: Quat::default(),
rot_offset: Quat::default(), rot_offset: Quat::default(),
third_person_toggle: false third_person_toggle: false,
shot_lines_enabled: false,
} }
} }
} }

View File

@ -7,7 +7,7 @@ use crate::{
spawners::{player::player_spawner, spawn::SpawnerPlugin}, spawners::{player::player_spawner, spawn::SpawnerPlugin},
}, },
logic::core::{ logic::core::{
guns::despawn_shots::{despawn_muzzle_flashes, despawn_stray_bullets}, guns::{despawn_shots::{despawn_muzzle_flashes, despawn_stray_bullets}, inspect::inspect_firearm},
player::{ player::{
camera_player_sync::{ camera_player_sync::{
follow_cursor_with_camera, update_camera_vertical_position, MouseMovementSettings, follow_cursor_with_camera, update_camera_vertical_position, MouseMovementSettings,
@ -59,6 +59,7 @@ pub fn load_scene(application: &mut App) {
application.add_systems(Update, change_equipment.before(player_spawner)); application.add_systems(Update, change_equipment.before(player_spawner));
application.add_systems(Update, (despawn_muzzle_flashes, despawn_stray_bullets)); application.add_systems(Update, (despawn_muzzle_flashes, despawn_stray_bullets));
application.add_systems(Update, inspect_firearm);
//application.add_systems(Update, animate_player); //application.add_systems(Update, animate_player);
//application.add_systems(Update, register_bullet_hits); //application.add_systems(Update, register_bullet_hits);

View File

@ -23,6 +23,15 @@ pub enum Equipment {
Nothing, Nothing,
} }
impl Equipment {
pub fn is_firearm(&self) -> bool {
match self {
Equipment::Firearm(_, _) => true,
Equipment::Nothing => false,
}
}
}
/// Called whenever player wants to change equipment /// Called whenever player wants to change equipment
pub fn change_equipment( pub fn change_equipment(
mut commands: Commands, mut commands: Commands,