From 988bb741acf6d911361fe4a8fb5721bbeb29ffc7 Mon Sep 17 00:00:00 2001 From: Back777space Date: Sat, 5 Apr 2025 19:13:16 +0200 Subject: [PATCH] player and physics plygins --- src/main.rs | 21 ++--- src/physics_plugin.rs | 72 +++++++++++++++ src/{player.rs => player_plugin.rs} | 133 ++++++---------------------- 3 files changed, 107 insertions(+), 119 deletions(-) create mode 100644 src/physics_plugin.rs rename src/{player.rs => player_plugin.rs} (53%) diff --git a/src/main.rs b/src/main.rs index a07614e..bd8733a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,26 +1,19 @@ use asset_loading::ImageAssets; -use bevy::{prelude::*, state::app::StatesPlugin}; +use bevy::prelude::*; +use player_plugin::PlayerPlugin; +use physics_plugin::PhysicsPlugin; mod asset_loading; - -pub mod player; +mod player_plugin; +mod physics_plugin; fn main() { App::new() - .add_plugins((DefaultPlugins, asset_loading::plugin)) + .add_plugins((DefaultPlugins, asset_loading::plugin, PlayerPlugin, PhysicsPlugin)) .init_state::() // We need to register components to make them visible to Blenvy + .add_systems(Startup, setup) .add_systems(OnExit(GameState::Loading), debug_our_king) - .add_systems(Startup, (setup, player::init_player)) - .add_systems(Update, player::move_camera) - .add_systems(FixedUpdate, player::advance_physics) - .add_systems( - RunFixedMainLoop, - ( - player::handle_input.in_set(RunFixedMainLoopSystem::BeforeFixedMainLoop), - player::interpolate_rendered_transform.in_set(RunFixedMainLoopSystem::AfterFixedMainLoop), - ), - ) .run(); } diff --git a/src/physics_plugin.rs b/src/physics_plugin.rs new file mode 100644 index 0000000..65199db --- /dev/null +++ b/src/physics_plugin.rs @@ -0,0 +1,72 @@ +use bevy::prelude::*; + +#[derive(Debug, Component, Clone, Copy, PartialEq, Default, Deref, DerefMut)] +pub struct Velocity(pub Vec3); + +/// The actual position of the player in the physics simulation. +/// This is separate from the `Transform`, which is merely a visual representation. +/// +/// If you want to make sure that this component is always initialized +/// with the same value as the `Transform`'s translation, you can +/// use a [component lifecycle hook](https://docs.rs/bevy/0.14.0/bevy/ecs/component/struct.ComponentHooks.html) +#[derive(Debug, Component, Clone, Copy, PartialEq, Default, Deref, DerefMut)] +pub struct PhysicalTranslation(pub Vec3); + +/// The value [`PhysicalTranslation`] had in the last fixed timestep. +/// Used for interpolation in the `interpolate_rendered_transform` system. +#[derive(Debug, Component, Clone, Copy, PartialEq, Default, Deref, DerefMut)] +pub struct PreviousPhysicalTranslation(pub Vec3); + +#[derive(Debug, Component, Clone, Copy, PartialEq, Default, Deref, DerefMut)] +pub struct AccumulatedInput(pub Vec3); + +pub struct PhysicsPlugin; +impl Plugin for PhysicsPlugin { + fn build(&self, app: &mut App) { + app.add_systems(RunFixedMainLoop, interpolate_rendered_transform.in_set(RunFixedMainLoopSystem::AfterFixedMainLoop)) + .add_systems(FixedUpdate, step); + } +} + +pub fn interpolate_rendered_transform( + fixed_time: Res>, + mut query: Query<( + &mut Transform, + &PhysicalTranslation, + &PreviousPhysicalTranslation, + )>, +) { + for (mut transform, current_physical_translation, previous_physical_translation) in + query.iter_mut() + { + let previous = previous_physical_translation.0; + let current = current_physical_translation.0; + // The overstep fraction is a value between 0 and 1 that tells us how far we are between two fixed timesteps. + let alpha = fixed_time.overstep_fraction(); + + let rendered_translation = previous.lerp(current, alpha); + transform.translation = rendered_translation; + } +} + +pub fn step( + fixed_time: Res>, + mut query: Query<( + &mut PhysicalTranslation, + &mut PreviousPhysicalTranslation, + &mut AccumulatedInput, + &Velocity, + )>, +) { + for ( + mut current_physical_translation, + mut previous_physical_translation, + mut input, + velocity, + ) in query.iter_mut() + { + previous_physical_translation.0 = current_physical_translation.0; + current_physical_translation.0 += velocity.0 * fixed_time.delta_secs(); + input.0 = Vec3::ZERO; + } +} \ No newline at end of file diff --git a/src/player.rs b/src/player_plugin.rs similarity index 53% rename from src/player.rs rename to src/player_plugin.rs index 8a9daae..78a5e58 100644 --- a/src/player.rs +++ b/src/player_plugin.rs @@ -1,8 +1,5 @@ -use bevy::{ - input::mouse::AccumulatedMouseMotion, pbr::NotShadowCaster, - prelude::*, render::view::RenderLayers, -}; - +use bevy::{prelude::*, render::view::RenderLayers, input::mouse::AccumulatedMouseMotion, pbr::NotShadowCaster}; +use crate::physics_plugin::{AccumulatedInput, Velocity, PhysicalTranslation, PreviousPhysicalTranslation}; #[derive(Debug, Component)] pub struct Player; @@ -20,32 +17,14 @@ impl Default for CameraSensitivity { #[derive(Debug, Component)] struct WorldModelCamera; - -#[derive(Debug, Component, Clone, Copy, PartialEq, Default, Deref, DerefMut)] -pub struct AccumulatedInput(Vec3); - - -#[derive(Debug, Component, Clone, Copy, PartialEq, Default, Deref, DerefMut)] -pub struct Velocity(Vec3); - - - -/// The actual position of the player in the physics simulation. -/// This is separate from the `Transform`, which is merely a visual representation. -/// -/// If you want to make sure that this component is always initialized -/// with the same value as the `Transform`'s translation, you can -/// use a [component lifecycle hook](https://docs.rs/bevy/0.14.0/bevy/ecs/component/struct.ComponentHooks.html) -#[derive(Debug, Component, Clone, Copy, PartialEq, Default, Deref, DerefMut)] -pub struct PhysicalTranslation(Vec3); - -/// The value [`PhysicalTranslation`] had in the last fixed timestep. -/// Used for interpolation in the `interpolate_rendered_transform` system. -#[derive(Debug, Component, Clone, Copy, PartialEq, Default, Deref, DerefMut)] -pub struct PreviousPhysicalTranslation(Vec3); - - - +pub struct PlayerPlugin; +impl Plugin for PlayerPlugin { + fn build(&self, app: &mut App) { + app.add_systems(Startup, init_player) + .add_systems(Update, move_camera) + .add_systems(RunFixedMainLoop, handle_input.in_set(RunFixedMainLoopSystem::BeforeFixedMainLoop)); + } +} @@ -113,6 +92,7 @@ pub fn init_player( }); } + use std::f32::consts::FRAC_PI_2; const PITCH_LIMIT: f32 = FRAC_PI_2 - 0.01; @@ -136,10 +116,6 @@ pub fn move_camera( } } - - -// PLAYER MOVEMENT - pub fn handle_input( keyboard_input: Res>, mut query: Query<(&Transform, &mut AccumulatedInput, &mut Velocity), With>, @@ -149,79 +125,26 @@ pub fn handle_input( let forward = transform.forward(); // Forward direction (z axis) let right = transform.right(); // Right direction (x axis) - if keyboard_input.pressed(KeyCode::KeyW) { input.x += 1.0; } - if keyboard_input.pressed(KeyCode::KeyS) { input.x -= 1.0; } - if keyboard_input.pressed(KeyCode::KeyA) { input.z -= 1.0; } - if keyboard_input.pressed(KeyCode::KeyD) { input.z += 1.0; } + if keyboard_input.pressed(KeyCode::KeyW) { + input.x += forward.x; + input.z += forward.z; + } + if keyboard_input.pressed(KeyCode::KeyS) { + input.x -= forward.x; + input.z -= forward.z; + } + if keyboard_input.pressed(KeyCode::KeyA) { + input.x -= right.x; + input.z -= right.z; + } + if keyboard_input.pressed(KeyCode::KeyD) { + input.x += right.x; + input.z += right.z; + } if keyboard_input.pressed(KeyCode::Space) { input.y += 1.0; } if keyboard_input.pressed(KeyCode::ShiftLeft) { input.y -= 1.0; } - // velocity.0 = input * SPEED; + velocity.0 = input.normalize_or_zero() * SPEED; } } -pub fn step( - fixed_time: Res>, - mut query: Query<( - &mut PhysicalTranslation, - &mut PreviousPhysicalTranslation, - &mut AccumulatedInput, - &Velocity, - )>, -) { - for ( - mut current_physical_translation, - mut previous_physical_translation, - mut input, - velocity, - ) in query.iter_mut() - { - previous_physical_translation.0 = current_physical_translation.0; - current_physical_translation.0 += velocity.0 * fixed_time.delta_secs(); - input.0 = Vec3::ZERO; - } -} -pub fn interpolate_rendered_transform( - fixed_time: Res>, - mut query: Query<( - &mut Transform, - &PhysicalTranslation, - &PreviousPhysicalTranslation, - )>, -) { - for (mut transform, current_physical_translation, previous_physical_translation) in - query.iter_mut() - { - let previous = previous_physical_translation.0; - let current = current_physical_translation.0; - // The overstep fraction is a value between 0 and 1 that tells us how far we are between two fixed timesteps. - let alpha = fixed_time.overstep_fraction(); - - let rendered_translation = previous.lerp(current, alpha); - transform.translation = rendered_translation; - } -} - -pub fn advance_physics( - fixed_time: Res>, - mut query: Query<( - &mut PhysicalTranslation, - &mut PreviousPhysicalTranslation, - &mut AccumulatedInput, - &Velocity, - )>, -) { - for ( - mut current_physical_translation, - mut previous_physical_translation, - mut input, - velocity, - ) in query.iter_mut() - { - previous_physical_translation.0 = current_physical_translation.0; - current_physical_translation.0 += velocity.0 * fixed_time.delta_secs(); - - // Reset the input accumulator, as we are currently consuming all input that happened since the last fixed timestep. - input.0 = Vec3::ZERO; - } -} \ No newline at end of file