Fix floating when hitting the ceiling and slope slowdown
This commit is contained in:
parent
5e35fff70c
commit
0c87c2fe19
@ -1,6 +1,10 @@
|
||||
use std::{collections::HashSet, f32::consts::PI, ops::Neg};
|
||||
|
||||
use godot::{classes::ICharacterBody3D, obj::WithBaseField, prelude::*};
|
||||
use godot::{
|
||||
classes::{ICharacterBody3D, KinematicCollision3D},
|
||||
obj::WithBaseField,
|
||||
prelude::*,
|
||||
};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{
|
||||
@ -70,25 +74,56 @@ pub trait PlayerCommon {
|
||||
|
||||
impl<T: IPlayer + ICharacterBody3D + WithBaseField> PlayerCommon for T {
|
||||
fn player_update(&mut self, delta: f64) {
|
||||
// Gravity
|
||||
self.set_y_speed(self.get_y_speed() - 9.8 * delta as f32);
|
||||
if self.base().is_on_floor() && self.get_y_speed() < 0. {
|
||||
self.set_y_speed(0.);
|
||||
}
|
||||
let vertical_velocity = Vector3::UP * self.get_y_speed();
|
||||
|
||||
let speed = Vector3::UP * self.get_y_speed()
|
||||
+ self
|
||||
.get_movement_dir()
|
||||
.try_normalized()
|
||||
.unwrap_or_default()
|
||||
.rotated(Vector3::UP, self.base().get_rotation().y)
|
||||
* self.get_move_speed();
|
||||
// Figure out the ground plane normal (to move on the right plane)
|
||||
let mut up_vector = Vector3::UP;
|
||||
let mut most_upward_coll: Option<Gd<KinematicCollision3D>> = None;
|
||||
for coll in (0..self.base().get_slide_collision_count())
|
||||
.flat_map(|i| self.base().get_slide_collision(i))
|
||||
{
|
||||
let coll_norm_y = coll.get_normal().y;
|
||||
if let Some(prev_most_upward) = &most_upward_coll {
|
||||
if coll_norm_y > prev_most_upward.get_normal().y {
|
||||
most_upward_coll = Some(coll);
|
||||
}
|
||||
} else if coll_norm_y > 0.5 {
|
||||
// sin(30 deg) == 0.5, so this only accepts 30 deg or shallower slopes
|
||||
most_upward_coll = Some(coll);
|
||||
}
|
||||
}
|
||||
if let Some(coll) = most_upward_coll {
|
||||
up_vector = coll.get_normal();
|
||||
}
|
||||
|
||||
// Ground movement (along the plane the player is currently on)
|
||||
let input_move_on_xz = self.get_movement_dir().try_normalized().unwrap_or_default();
|
||||
let ground_plane_basis = Basis::from_axis_angle(up_vector, self.base().get_rotation().y);
|
||||
let input_move_on_ground_plane = ground_plane_basis * input_move_on_xz;
|
||||
|
||||
let move_speed = self.get_move_speed();
|
||||
let ground_plane_velocity = input_move_on_ground_plane * move_speed;
|
||||
|
||||
// Commit
|
||||
if self.is_dead() {
|
||||
self.base_mut().set_velocity(Vector3::ZERO);
|
||||
} else {
|
||||
self.base_mut().set_velocity(speed);
|
||||
self.base_mut()
|
||||
.set_velocity(vertical_velocity + ground_plane_velocity);
|
||||
self.base_mut().move_and_slide();
|
||||
}
|
||||
|
||||
// Check if hitting a ceiling; if so, stop upwards velocity (done here instead of
|
||||
// at the start of the next frame to get the right-after-move_and_slide state
|
||||
// rather than the simulated one).
|
||||
if self.base().get_velocity().y < 0.001 && self.get_y_speed() > 0.001 {
|
||||
self.set_y_speed(0.0);
|
||||
}
|
||||
}
|
||||
|
||||
fn try_jump(&mut self) -> bool {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user