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.
|
// up and down the surface smoothly.
|
||||||
if climbable {
|
if climbable {
|
||||||
// Points in the normal's direction in the XZ plane.
|
// Points in the normal's direction in the XZ plane.
|
||||||
|
|
||||||
let normal_direction_xz =
|
let normal_direction_xz =
|
||||||
normal.reject_from_normalized(Vector::Y).normalize_or_zero();
|
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();
|
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 {
|
} else {
|
||||||
// The character is intersecting an unclimbable object, like a wall.
|
// The character is intersecting an unclimbable object, like a wall.
|
||||||
// We want the character to slide along the surface, similarly to
|
// 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 avian3d::{math::*, prelude::*};
|
||||||
use bevy::{ecs::query::Has, prelude::*};
|
use bevy::{ecs::query::Has, prelude::*};
|
||||||
|
|
||||||
use crate::{GameState, player::PlayerRig};
|
|
||||||
|
|
||||||
use super::{ControllerSet, Controls, collisions::kinematic_controller_collisions};
|
|
||||||
|
|
||||||
pub struct CharacterControllerPlugin;
|
pub struct CharacterControllerPlugin;
|
||||||
|
|
||||||
impl Plugin for CharacterControllerPlugin {
|
impl Plugin for CharacterControllerPlugin {
|
||||||
fn build(&self, app: &mut App) {
|
fn build(&self, app: &mut App) {
|
||||||
app.init_resource::<PlayerMovement>();
|
app.init_resource::<PlayerMovement>();
|
||||||
app.init_resource::<MovementSettings>();
|
|
||||||
app.register_type::<MovementSettings>();
|
|
||||||
app.register_type::<MovementDampingFactor>();
|
|
||||||
app.register_type::<JumpImpulse>();
|
app.register_type::<JumpImpulse>();
|
||||||
app.register_type::<ControllerGravity>();
|
app.register_type::<ControllerGravity>();
|
||||||
app.register_type::<MovementAcceleration>();
|
app.register_type::<MovementAcceleration>();
|
||||||
|
|
||||||
app.add_systems(
|
app.add_systems(
|
||||||
Update,
|
Update,
|
||||||
(
|
(set_movement_flag, update_grounded, apply_gravity, movement)
|
||||||
set_movement_flag,
|
|
||||||
brake_on_release,
|
|
||||||
update_grounded,
|
|
||||||
apply_gravity,
|
|
||||||
movement,
|
|
||||||
apply_movement_damping,
|
|
||||||
)
|
|
||||||
.chain()
|
.chain()
|
||||||
.in_set(ControllerSet::ApplyControls)
|
.in_set(ControllerSet::ApplyControls)
|
||||||
.run_if(in_state(GameState::Playing)),
|
.run_if(in_state(GameState::Playing)),
|
||||||
@@ -56,35 +45,11 @@ pub struct PlayerMovement {
|
|||||||
pub any_direction: bool,
|
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.
|
/// The acceleration used for character movement.
|
||||||
#[derive(Component, Reflect)]
|
#[derive(Component, Reflect)]
|
||||||
#[reflect(Component)]
|
#[reflect(Component)]
|
||||||
pub struct MovementAcceleration(Scalar);
|
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.
|
/// The strength of a jump.
|
||||||
#[derive(Component, Reflect)]
|
#[derive(Component, Reflect)]
|
||||||
#[reflect(Component)]
|
#[reflect(Component)]
|
||||||
@@ -118,35 +83,22 @@ pub struct CharacterControllerBundle {
|
|||||||
#[derive(Bundle)]
|
#[derive(Bundle)]
|
||||||
pub struct MovementBundle {
|
pub struct MovementBundle {
|
||||||
acceleration: MovementAcceleration,
|
acceleration: MovementAcceleration,
|
||||||
damping: MovementDampingFactor,
|
|
||||||
jump_impulse: JumpImpulse,
|
jump_impulse: JumpImpulse,
|
||||||
max_slope_angle: MaxSlopeAngle,
|
max_slope_angle: MaxSlopeAngle,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MovementBundle {
|
impl MovementBundle {
|
||||||
pub const fn new(
|
pub const fn new(acceleration: Scalar, jump_impulse: Scalar, max_slope_angle: Scalar) -> Self {
|
||||||
acceleration: Scalar,
|
|
||||||
damping: Scalar,
|
|
||||||
jump_impulse: Scalar,
|
|
||||||
max_slope_angle: Scalar,
|
|
||||||
) -> Self {
|
|
||||||
Self {
|
Self {
|
||||||
acceleration: MovementAcceleration(acceleration),
|
acceleration: MovementAcceleration(acceleration),
|
||||||
damping: MovementDampingFactor(damping),
|
|
||||||
jump_impulse: JumpImpulse(jump_impulse),
|
jump_impulse: JumpImpulse(jump_impulse),
|
||||||
max_slope_angle: MaxSlopeAngle(max_slope_angle),
|
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 {
|
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
|
// Create shape caster as a slightly smaller version of collider
|
||||||
let mut caster_shape = collider.clone();
|
let mut caster_shape = collider.clone();
|
||||||
caster_shape.set_scale(Vector::ONE * 0.98, 10);
|
caster_shape.set_scale(Vector::ONE * 0.98, 10);
|
||||||
@@ -163,39 +115,7 @@ impl CharacterControllerBundle {
|
|||||||
)
|
)
|
||||||
.with_max_distance(0.2),
|
.with_max_distance(0.2),
|
||||||
gravity: ControllerGravity(gravity),
|
gravity: ControllerGravity(gravity),
|
||||||
movement: MovementBundle::default(),
|
movement,
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -220,8 +140,10 @@ fn update_grounded(
|
|||||||
});
|
});
|
||||||
|
|
||||||
if is_grounded {
|
if is_grounded {
|
||||||
|
info!("grounded");
|
||||||
commands.entity(entity).insert(Grounded);
|
commands.entity(entity).insert(Grounded);
|
||||||
} else {
|
} else {
|
||||||
|
info!("not grounded");
|
||||||
commands.entity(entity).remove::<Grounded>();
|
commands.entity(entity).remove::<Grounded>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -256,19 +178,22 @@ fn movement(
|
|||||||
Has<Grounded>,
|
Has<Grounded>,
|
||||||
)>,
|
)>,
|
||||||
rig_transform_q: Option<Single<&GlobalTransform, With<PlayerRig>>>,
|
rig_transform_q: Option<Single<&GlobalTransform, With<PlayerRig>>>,
|
||||||
|
mut jump_used: Local<bool>,
|
||||||
) {
|
) {
|
||||||
let delta_time = time.delta_secs();
|
let delta_time = time.delta_secs();
|
||||||
|
|
||||||
let mut direction = controls.keyboard_state.move_dir;
|
let mut direction = controls.keyboard_state.move_dir;
|
||||||
|
|
||||||
let mut jump_requested = controls.keyboard_state.jump;
|
let mut jump_requested = controls.keyboard_state.jump;
|
||||||
|
|
||||||
if let Some(gamepad) = controls.gamepad_state {
|
if let Some(gamepad) = controls.gamepad_state {
|
||||||
direction += gamepad.move_dir;
|
direction += gamepad.move_dir;
|
||||||
direction = direction.normalize_or_zero();
|
|
||||||
|
|
||||||
jump_requested |= gamepad.jump;
|
jump_requested |= gamepad.jump;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
direction = direction.normalize_or_zero();
|
||||||
|
|
||||||
for (movement_acceleration, jump_impulse, mut linear_velocity, is_grounded) in &mut controllers
|
for (movement_acceleration, jump_impulse, mut linear_velocity, is_grounded) in &mut controllers
|
||||||
{
|
{
|
||||||
let mut direction = direction.extend(0.0).xzy();
|
let mut direction = direction.extend(0.0).xzy();
|
||||||
@@ -278,11 +203,22 @@ fn movement(
|
|||||||
(rig_transform.forward() * direction.z) + (rig_transform.right() * direction.x);
|
(rig_transform.forward() * direction.z) + (rig_transform.right() * direction.x);
|
||||||
}
|
}
|
||||||
|
|
||||||
linear_velocity.x -= direction.x * 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;
|
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;
|
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.
|
/// Applies [`ControllerGravity`] to character controllers.
|
||||||
fn apply_gravity(
|
fn apply_gravity(
|
||||||
time: Res<Time>,
|
time: Res<Time>,
|
||||||
mut controllers: Query<(&ControllerGravity, &mut LinearVelocity)>,
|
mut controllers: Query<(&ControllerGravity, &mut LinearVelocity, Option<&Grounded>)>,
|
||||||
) {
|
) {
|
||||||
let delta_time = time.delta_secs();
|
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;
|
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},
|
cash::{Cash, CashCollectEvent},
|
||||||
control::{
|
control::{
|
||||||
Controls,
|
Controls,
|
||||||
controller::{CharacterControllerBundle, PlayerMovement},
|
controller::{CharacterControllerBundle, MovementBundle, PlayerMovement},
|
||||||
},
|
},
|
||||||
heads_ui::HeadChanged,
|
heads_ui::HeadChanged,
|
||||||
loading_assets::GameAssets,
|
loading_assets::GameAssets,
|
||||||
@@ -87,8 +87,7 @@ fn spawn(
|
|||||||
|
|
||||||
let gravity = Vector::NEG_Y * 40.0;
|
let gravity = Vector::NEG_Y * 40.0;
|
||||||
let collider = Collider::capsule(0.9, 1.2);
|
let collider = Collider::capsule(0.9, 1.2);
|
||||||
let acceleration = 30.0;
|
let acceleration = 30.0 * 60.;
|
||||||
let damping = 0.95;
|
|
||||||
let jump_impulse = 18.0;
|
let jump_impulse = 18.0;
|
||||||
let max_slope_angle = (60.0 as Scalar).to_radians();
|
let max_slope_angle = (60.0 as Scalar).to_radians();
|
||||||
|
|
||||||
@@ -101,11 +100,10 @@ fn spawn(
|
|||||||
Visibility::default(),
|
Visibility::default(),
|
||||||
// LockedAxes::ROTATION_LOCKED, todo
|
// LockedAxes::ROTATION_LOCKED, todo
|
||||||
CollisionLayers::new(LayerMask(GameLayer::Player.to_bits()), LayerMask::ALL),
|
CollisionLayers::new(LayerMask(GameLayer::Player.to_bits()), LayerMask::ALL),
|
||||||
CharacterControllerBundle::new(collider, gravity).with_movement(
|
CharacterControllerBundle::new(
|
||||||
acceleration,
|
collider,
|
||||||
damping,
|
gravity,
|
||||||
jump_impulse,
|
MovementBundle::new(acceleration, jump_impulse, max_slope_angle),
|
||||||
max_slope_angle,
|
|
||||||
),
|
),
|
||||||
))
|
))
|
||||||
.with_children(|parent| {
|
.with_children(|parent| {
|
||||||
|
|||||||
Reference in New Issue
Block a user