player and physics plygins

This commit is contained in:
Back777space
2025-04-05 19:13:16 +02:00
parent 186f642a8a
commit 988bb741ac
3 changed files with 107 additions and 119 deletions

View File

@@ -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::<GameState>()
// 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();
}

72
src/physics_plugin.rs Normal file
View File

@@ -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<Time<Fixed>>,
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<Time<Fixed>>,
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;
}
}

View File

@@ -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<ButtonInput<KeyCode>>,
mut query: Query<(&Transform, &mut AccumulatedInput, &mut Velocity), With<Player>>,
@@ -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<Time<Fixed>>,
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<Time<Fixed>>,
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<Time<Fixed>>,
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;
}
}