From 7fa31a91a6a4d71da5aa3781ff935bacf412068d Mon Sep 17 00:00:00 2001 From: extrawurst Date: Thu, 27 Mar 2025 00:00:11 +0800 Subject: [PATCH] remove damping * try fix sliding upwards gaining speed --- src/control/collisions.rs | 7 +- src/control/controller.rs | 140 +++++++++----------------------------- src/player.rs | 14 ++-- 3 files changed, 44 insertions(+), 117 deletions(-) diff --git a/src/control/collisions.rs b/src/control/collisions.rs index 6533900..3586052 100644 --- a/src/control/collisions.rs +++ b/src/control/collisions.rs @@ -99,6 +99,7 @@ pub fn kinematic_controller_collisions( // up and down the surface smoothly. if climbable { // Points in the normal's direction in the XZ plane. + let normal_direction_xz = normal.reject_from_normalized(Vector::Y).normalize_or_zero(); @@ -120,7 +121,11 @@ pub fn kinematic_controller_collisions( // *───────────────────* let max_y_speed = -linear_velocity_xz * slope_angle.tan(); - linear_velocity.y = linear_velocity.y.max(max_y_speed); + + // TODO: figure out why this is needed, without it we + // cannot do these crate to crate jumps anymore which is intented. + + // linear_velocity.y = linear_velocity.y.max(max_y_speed); } else { // The character is intersecting an unclimbable object, like a wall. // We want the character to slide along the surface, similarly to diff --git a/src/control/controller.rs b/src/control/controller.rs index 31d3d02..9e06b42 100644 --- a/src/control/controller.rs +++ b/src/control/controller.rs @@ -1,32 +1,21 @@ +use super::{ControllerSet, Controls, collisions::kinematic_controller_collisions}; +use crate::{GameState, player::PlayerRig}; use avian3d::{math::*, prelude::*}; use bevy::{ecs::query::Has, prelude::*}; -use crate::{GameState, player::PlayerRig}; - -use super::{ControllerSet, Controls, collisions::kinematic_controller_collisions}; - pub struct CharacterControllerPlugin; impl Plugin for CharacterControllerPlugin { fn build(&self, app: &mut App) { app.init_resource::(); - app.init_resource::(); - app.register_type::(); - app.register_type::(); + app.register_type::(); app.register_type::(); app.register_type::(); app.add_systems( Update, - ( - set_movement_flag, - brake_on_release, - update_grounded, - apply_gravity, - movement, - apply_movement_damping, - ) + (set_movement_flag, update_grounded, apply_gravity, movement) .chain() .in_set(ControllerSet::ApplyControls) .run_if(in_state(GameState::Playing)), @@ -56,35 +45,11 @@ pub struct PlayerMovement { pub any_direction: bool, } -#[derive(Resource, Reflect)] -#[reflect(Resource)] -struct MovementSettings { - damping_normal: f32, - damping_brake: f32, - damping_brake_air: f32, -} - -// todo some duplicate with player.rs settings -impl Default for MovementSettings { - fn default() -> Self { - Self { - damping_normal: 1.0, - damping_brake: 30.0, - damping_brake_air: 1.0, - } - } -} - /// The acceleration used for character movement. #[derive(Component, Reflect)] #[reflect(Component)] pub struct MovementAcceleration(Scalar); -/// The damping factor used for slowing down movement. -#[derive(Component, Reflect)] -#[reflect(Component)] -pub struct MovementDampingFactor(Scalar); - /// The strength of a jump. #[derive(Component, Reflect)] #[reflect(Component)] @@ -118,35 +83,22 @@ pub struct CharacterControllerBundle { #[derive(Bundle)] pub struct MovementBundle { acceleration: MovementAcceleration, - damping: MovementDampingFactor, jump_impulse: JumpImpulse, max_slope_angle: MaxSlopeAngle, } impl MovementBundle { - pub const fn new( - acceleration: Scalar, - damping: Scalar, - jump_impulse: Scalar, - max_slope_angle: Scalar, - ) -> Self { + pub const fn new(acceleration: Scalar, jump_impulse: Scalar, max_slope_angle: Scalar) -> Self { Self { acceleration: MovementAcceleration(acceleration), - damping: MovementDampingFactor(damping), jump_impulse: JumpImpulse(jump_impulse), max_slope_angle: MaxSlopeAngle(max_slope_angle), } } } -impl Default for MovementBundle { - fn default() -> Self { - Self::new(30.0, 0.9, 7.0, PI * 0.45) - } -} - impl CharacterControllerBundle { - pub fn new(collider: Collider, gravity: Vector) -> Self { + pub fn new(collider: Collider, gravity: Vector, movement: MovementBundle) -> Self { // Create shape caster as a slightly smaller version of collider let mut caster_shape = collider.clone(); caster_shape.set_scale(Vector::ONE * 0.98, 10); @@ -163,39 +115,7 @@ impl CharacterControllerBundle { ) .with_max_distance(0.2), gravity: ControllerGravity(gravity), - movement: MovementBundle::default(), - } - } - - pub fn with_movement( - mut self, - acceleration: Scalar, - damping: Scalar, - jump_impulse: Scalar, - max_slope_angle: Scalar, - ) -> Self { - self.movement = MovementBundle::new(acceleration, damping, jump_impulse, max_slope_angle); - self - } -} - -/// Apply extra friction when no movement input is given -/// In the original you stop instantly in this case -fn brake_on_release( - player_movement: Res, - movement_settings: Res, - mut damping_q: Query<(Entity, &mut MovementDampingFactor)>, - grounded_q: Query<&Grounded>, -) { - for (entity, mut damping) in &mut damping_q { - let is_grounded = grounded_q.get(entity).is_ok(); - - if !player_movement.any_direction && is_grounded { - damping.0 = movement_settings.damping_brake; - } else if !player_movement.any_direction && !is_grounded { - damping.0 = movement_settings.damping_brake_air; - } else { - damping.0 = movement_settings.damping_normal; + movement, } } } @@ -220,8 +140,10 @@ fn update_grounded( }); if is_grounded { + info!("grounded"); commands.entity(entity).insert(Grounded); } else { + info!("not grounded"); commands.entity(entity).remove::(); } } @@ -256,19 +178,22 @@ fn movement( Has, )>, rig_transform_q: Option>>, + mut jump_used: Local, ) { let delta_time = time.delta_secs(); let mut direction = controls.keyboard_state.move_dir; + let mut jump_requested = controls.keyboard_state.jump; if let Some(gamepad) = controls.gamepad_state { direction += gamepad.move_dir; - direction = direction.normalize_or_zero(); jump_requested |= gamepad.jump; } + direction = direction.normalize_or_zero(); + for (movement_acceleration, jump_impulse, mut linear_velocity, is_grounded) in &mut controllers { let mut direction = direction.extend(0.0).xzy(); @@ -278,11 +203,22 @@ fn movement( (rig_transform.forward() * direction.z) + (rig_transform.right() * direction.x); } - linear_velocity.x -= direction.x * movement_acceleration.0 * delta_time; - linear_velocity.z -= direction.z * movement_acceleration.0 * delta_time; + linear_velocity.x = -direction.x * movement_acceleration.0 * delta_time; + linear_velocity.z = -direction.z * movement_acceleration.0 * delta_time; - if is_grounded && jump_requested { + if is_grounded && jump_requested && !*jump_used { linear_velocity.y = jump_impulse.0; + info!("jump"); + *jump_used = true; + } + + if !controls.keyboard_state.jump + && !controls + .gamepad_state + .map(|state| state.jump) + .unwrap_or_default() + { + *jump_used = false; } } } @@ -290,25 +226,13 @@ fn movement( /// Applies [`ControllerGravity`] to character controllers. fn apply_gravity( time: Res