remove damping
* try fix sliding upwards gaining speed
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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::<PlayerMovement>();
|
||||
app.init_resource::<MovementSettings>();
|
||||
app.register_type::<MovementSettings>();
|
||||
app.register_type::<MovementDampingFactor>();
|
||||
|
||||
app.register_type::<JumpImpulse>();
|
||||
app.register_type::<ControllerGravity>();
|
||||
app.register_type::<MovementAcceleration>();
|
||||
|
||||
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<PlayerMovement>,
|
||||
movement_settings: Res<MovementSettings>,
|
||||
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::<Grounded>();
|
||||
}
|
||||
}
|
||||
@@ -256,19 +178,22 @@ fn movement(
|
||||
Has<Grounded>,
|
||||
)>,
|
||||
rig_transform_q: Option<Single<&GlobalTransform, With<PlayerRig>>>,
|
||||
mut jump_used: Local<bool>,
|
||||
) {
|
||||
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<Time>,
|
||||
mut controllers: Query<(&ControllerGravity, &mut LinearVelocity)>,
|
||||
mut controllers: Query<(&ControllerGravity, &mut LinearVelocity, Option<&Grounded>)>,
|
||||
) {
|
||||
let delta_time = time.delta_secs();
|
||||
|
||||
for (gravity, mut linear_velocity) in &mut controllers {
|
||||
for (gravity, mut linear_velocity, grounded) in &mut controllers {
|
||||
if grounded.is_none() {
|
||||
linear_velocity.0 += gravity.0 * delta_time;
|
||||
}
|
||||
}
|
||||
|
||||
/// Slows down movement in the XZ plane.
|
||||
fn apply_movement_damping(
|
||||
time: Res<Time>,
|
||||
mut query: Query<(&MovementDampingFactor, &mut LinearVelocity)>,
|
||||
) {
|
||||
let delta_time = time.delta_secs();
|
||||
|
||||
for (damping_factor, mut linear_velocity) in &mut query {
|
||||
// We could use `LinearDamping`, but we don't want to dampen movement along the Y axis
|
||||
linear_velocity.x *= 1.0 - damping_factor.0 * delta_time;
|
||||
linear_velocity.z *= 1.0 - damping_factor.0 * delta_time;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ use crate::{
|
||||
cash::{Cash, CashCollectEvent},
|
||||
control::{
|
||||
Controls,
|
||||
controller::{CharacterControllerBundle, PlayerMovement},
|
||||
controller::{CharacterControllerBundle, MovementBundle, PlayerMovement},
|
||||
},
|
||||
heads_ui::HeadChanged,
|
||||
loading_assets::GameAssets,
|
||||
@@ -87,8 +87,7 @@ fn spawn(
|
||||
|
||||
let gravity = Vector::NEG_Y * 40.0;
|
||||
let collider = Collider::capsule(0.9, 1.2);
|
||||
let acceleration = 30.0;
|
||||
let damping = 0.95;
|
||||
let acceleration = 30.0 * 60.;
|
||||
let jump_impulse = 18.0;
|
||||
let max_slope_angle = (60.0 as Scalar).to_radians();
|
||||
|
||||
@@ -101,11 +100,10 @@ fn spawn(
|
||||
Visibility::default(),
|
||||
// LockedAxes::ROTATION_LOCKED, todo
|
||||
CollisionLayers::new(LayerMask(GameLayer::Player.to_bits()), LayerMask::ALL),
|
||||
CharacterControllerBundle::new(collider, gravity).with_movement(
|
||||
acceleration,
|
||||
damping,
|
||||
jump_impulse,
|
||||
max_slope_angle,
|
||||
CharacterControllerBundle::new(
|
||||
collider,
|
||||
gravity,
|
||||
MovementBundle::new(acceleration, jump_impulse, max_slope_angle),
|
||||
),
|
||||
))
|
||||
.with_children(|parent| {
|
||||
|
||||
Reference in New Issue
Block a user