|
|
|
public partial class MovementController : Node, IInitalizable<Player>
|
|
|
|
{
|
|
|
|
[ExportGroup("Movement")]
|
|
|
|
[Export] public float Acceleration { get; set; } = 4.0f;
|
|
|
|
[Export] public float MaxSpeed { get; set; } = 2.1f;
|
|
|
|
[Export] public float FrictionFloor { get; set; } = 12.0f;
|
|
|
|
[Export] public float FrictionAir { get; set; } = 2.0f;
|
|
|
|
public float Gravity { get; } = (float)ProjectSettings.GetSetting("physics/3d/default_gravity");
|
|
|
|
|
|
|
|
[ExportGroup("Jumping")]
|
|
|
|
[Export] public float JumpVelocity { get; set; } = 4.0f;
|
|
|
|
[Export] public float JumpEarlyTime { get; set; } = 0.0f; // Time (in seconds) after pressing the jump button a jump may occur late.
|
|
|
|
[Export] public float JumpCoyoteTime { get; set; } = 0.0f; // Time (in seconds) after leaving a jumpable surface when a jump may still occur.
|
|
|
|
|
|
|
|
public float RealMoveSpeed { get; private set; }
|
|
|
|
public bool IsSprinting { get; private set; }
|
|
|
|
|
|
|
|
public float TimeSinceJumpPressed { get; private set; } = float.PositiveInfinity;
|
|
|
|
public float TimeSinceOnFloor { get; private set; } = float.PositiveInfinity;
|
|
|
|
|
|
|
|
Player _player;
|
|
|
|
public void Initialize(Player player)
|
|
|
|
=> _player = player;
|
|
|
|
|
|
|
|
public override void _UnhandledInput(InputEvent @event)
|
|
|
|
{
|
|
|
|
// TODO: Sprinting.
|
|
|
|
// TODO: Jumping.
|
|
|
|
}
|
|
|
|
|
|
|
|
public override void _PhysicsProcess(double delta)
|
|
|
|
{
|
|
|
|
// Get the (normalized) movement vector from the current input.
|
|
|
|
var input = Input.GetVector("move_strafe_left", "move_strafe_right", "move_forward", "move_back");
|
|
|
|
|
|
|
|
var velocity = _player.Velocity;
|
|
|
|
var horVelocity = velocity with { Y = 0 };
|
|
|
|
|
|
|
|
// TODO: Gravity.
|
|
|
|
// velocity.Y -= Gravity * (float)delta;
|
|
|
|
|
|
|
|
var basis = _player.Basis.Rotated(Vector3.Up, _player.Camera.CurrentYaw);
|
|
|
|
var target = basis * new Vector3(input.X, 0, input.Y) * MaxSpeed;
|
|
|
|
var isMoving = target.Dot(horVelocity) > 0.0f;
|
|
|
|
|
|
|
|
var isOnFloor = true; // _player.IsOnFloor();
|
|
|
|
var accel = isMoving ? Acceleration
|
|
|
|
: isOnFloor ? FrictionFloor
|
|
|
|
: FrictionAir;
|
|
|
|
|
|
|
|
if (IsSprinting) {
|
|
|
|
target *= 5;
|
|
|
|
accel *= 5;
|
|
|
|
}
|
|
|
|
|
|
|
|
horVelocity = horVelocity.Lerp(target, accel * (float)delta);
|
|
|
|
velocity.X = horVelocity.X;
|
|
|
|
velocity.Z = horVelocity.Z;
|
|
|
|
|
|
|
|
if (isOnFloor) TimeSinceOnFloor = 0.0f;
|
|
|
|
else TimeSinceOnFloor += (float)delta;
|
|
|
|
|
|
|
|
if ((TimeSinceJumpPressed <= JumpEarlyTime) && (TimeSinceOnFloor <= JumpCoyoteTime)) {
|
|
|
|
TimeSinceJumpPressed = TimeSinceOnFloor = float.PositiveInfinity;
|
|
|
|
velocity.Y = JumpVelocity;
|
|
|
|
}
|
|
|
|
|
|
|
|
_player.Velocity = velocity;
|
|
|
|
_player.MoveAndSlide();
|
|
|
|
|
|
|
|
RealMoveSpeed = (_player.Velocity with { Y = 0 }).Length();
|
|
|
|
}
|
|
|
|
}
|