refacto: moved systems from player controller physics process to their own signal based systems
This commit is contained in:
184
systems/move/MoveSystem.cs
Normal file
184
systems/move/MoveSystem.cs
Normal file
@ -0,0 +1,184 @@
|
||||
using Godot;
|
||||
using PolarBears.PlayerControllerAddon;
|
||||
|
||||
public partial class MoveSystem : Node3D
|
||||
{
|
||||
public record MoveSystemParameters(
|
||||
CharacterBody3D Parent,
|
||||
Gravity Gravity,
|
||||
MantleSystem MantleSystem,
|
||||
TweenQueueSystem TweenQueueSystem,
|
||||
HeadSystem HeadSystem,
|
||||
CapsuleCollider CapsuleCollider);
|
||||
|
||||
[Export(PropertyHint.Range, "0,20,0.1,or_greater")]
|
||||
public float WalkSpeed { get; set; } = 5.0f;
|
||||
[Export(PropertyHint.Range, "0,20,0.1,or_greater")]
|
||||
public float SprintSpeed { get; set; } = 7.2f;
|
||||
[Export(PropertyHint.Range, "0,10,0.1,or_greater")]
|
||||
public float CrouchSpeed { get; set; } = 2.5f;
|
||||
[Export(PropertyHint.Range, "0,100,0.1,or_greater")]
|
||||
|
||||
public float _currentSpeed;
|
||||
private const float DecelerationSpeedFactorFloor = 15.0f;
|
||||
private const float DecelerationSpeedFactorAir = 7.0f;
|
||||
|
||||
public float CrouchTransitionSpeed { get; set; } = 20.0f;
|
||||
[Export(PropertyHint.Range, "0,5,0.1,or_greater")]
|
||||
public float DoubleJumpSpeedFactor { get; set; } = 2f;
|
||||
|
||||
private bool _canDoubleJump = true;
|
||||
private float _lastFrameWasOnFloor = -Mathf.Inf;
|
||||
|
||||
private Gravity _gravity;
|
||||
private CharacterBody3D _parent;
|
||||
private MantleSystem _mantleSystem;
|
||||
private TweenQueueSystem _tweenQueueSystem;
|
||||
private CapsuleCollider _capsuleCollider;
|
||||
private HeadSystem _headSystem;
|
||||
public void Init(MoveSystemParameters parameters)
|
||||
{
|
||||
_parent = parameters.Parent;
|
||||
_gravity = parameters.Gravity;
|
||||
_mantleSystem = parameters.MantleSystem;
|
||||
_tweenQueueSystem = parameters.TweenQueueSystem;
|
||||
_capsuleCollider = parameters.CapsuleCollider;
|
||||
_headSystem = parameters.HeadSystem;
|
||||
|
||||
_currentSpeed = WalkSpeed;
|
||||
}
|
||||
|
||||
public void MoveAround(double delta, Vector3 movementDirection, bool isOnFloor, bool isDead, bool isHeadTouchingCeiling)
|
||||
{
|
||||
var doesCapsuleHaveCrouchingHeight = _capsuleCollider.IsCrouchingHeight();
|
||||
var doesCapsuleHaveDefaultHeight = _capsuleCollider.IsDefaultHeight();
|
||||
|
||||
// Adding the gravity
|
||||
if (!isOnFloor)
|
||||
{
|
||||
_parent.Velocity = new Vector3(
|
||||
x: _parent.Velocity.X,
|
||||
y: _parent.Velocity.Y - (_gravity.CalculateGravityForce() * (float)delta),
|
||||
z: _parent.Velocity.Z);
|
||||
}
|
||||
|
||||
if (isOnFloor)
|
||||
{
|
||||
_lastFrameWasOnFloor = Engine.GetPhysicsFrames();
|
||||
_canDoubleJump = true;
|
||||
}
|
||||
|
||||
// The code below is required to quickly adjust player's position on Y-axis when there's a ceiling on the
|
||||
// trajectory of player's jump and player is standing
|
||||
if (isHeadTouchingCeiling && doesCapsuleHaveDefaultHeight)
|
||||
{
|
||||
_parent.Velocity = new Vector3(
|
||||
x: _parent.Velocity.X,
|
||||
y: _parent.Velocity.Y - 2.0f,
|
||||
z: _parent.Velocity.Z);
|
||||
}
|
||||
|
||||
|
||||
if (!isDead)
|
||||
{
|
||||
|
||||
// Used both for detecting the moment when we enter into crouching mode and the moment when we're already
|
||||
// in the crouching mode
|
||||
if (Input.IsActionPressed("crouch") ||
|
||||
(doesCapsuleHaveCrouchingHeight && isHeadTouchingCeiling))
|
||||
{
|
||||
_capsuleCollider.Crouch((float)delta, CrouchTransitionSpeed);
|
||||
_currentSpeed = CrouchSpeed;
|
||||
}
|
||||
// Used both for the moment when we exit the crouching mode and for the moment when we just walk
|
||||
else
|
||||
{
|
||||
_capsuleCollider.UndoCrouching((float)delta, CrouchTransitionSpeed);
|
||||
_currentSpeed = WalkSpeed;
|
||||
}
|
||||
}
|
||||
|
||||
// Each component of the boolean statement for sprinting is required
|
||||
if (Input.IsActionPressed("sprint") && !isHeadTouchingCeiling &&
|
||||
!doesCapsuleHaveCrouchingHeight && !isDead)
|
||||
{
|
||||
_currentSpeed = SprintSpeed;
|
||||
}
|
||||
|
||||
// Basis is a 3x4 matrix. It contains information about scaling and rotation of head.
|
||||
// By multiplying our Vector3 by this matrix we're doing multiple things:
|
||||
// a) We start to operate in global space;
|
||||
// b) We're applying to Vector3 the current rotation of "head" object;
|
||||
// c) We're applying to Vector3 the current scaling of "head" object;
|
||||
Vector3 direction = _headSystem.Transform.Basis * movementDirection;
|
||||
|
||||
if (isDead)
|
||||
{
|
||||
direction = Vector3.Zero;
|
||||
}
|
||||
|
||||
|
||||
if (isOnFloor)
|
||||
{
|
||||
// Set velocity based on input direction when on the floor
|
||||
if (direction.Length() > 0)
|
||||
{
|
||||
float newX = direction.X * _currentSpeed;
|
||||
float newZ = direction.Z * _currentSpeed;
|
||||
|
||||
_parent.Velocity = new Vector3(newX, _parent.Velocity.Y, newZ);
|
||||
}
|
||||
// If there is no input, smoothly decelerate the character on the floor
|
||||
else
|
||||
{
|
||||
float xDeceleration = Mathf.Lerp(_parent.Velocity.X, direction.X * _currentSpeed,
|
||||
(float)delta * DecelerationSpeedFactorFloor);
|
||||
float zDeceleration = Mathf.Lerp(_parent.Velocity.Z, direction.Z * _currentSpeed,
|
||||
(float)delta * DecelerationSpeedFactorFloor);
|
||||
|
||||
_parent.Velocity = new Vector3(xDeceleration, _parent.Velocity.Y, zDeceleration);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
float xDeceleration = Mathf.Lerp(_parent.Velocity.X, direction.X * _currentSpeed,
|
||||
(float)delta * DecelerationSpeedFactorAir);
|
||||
float zDeceleration = Mathf.Lerp(_parent.Velocity.Z, direction.Z * _currentSpeed,
|
||||
(float)delta * DecelerationSpeedFactorAir);
|
||||
|
||||
_parent.Velocity = new Vector3(xDeceleration, _parent.Velocity.Y, zDeceleration);
|
||||
}
|
||||
|
||||
if (isDead)
|
||||
{
|
||||
_parent.MoveAndSlide();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
public void Jump(bool isOnFloor)
|
||||
{
|
||||
var mantleLocationResult = _mantleSystem.FindMantleInFrontOfPlayer();
|
||||
if (mantleLocationResult.IsSome(out var mantleLocation))
|
||||
{
|
||||
var duration = 0.1f * mantleLocation.DistanceTo(_parent.Position);
|
||||
_tweenQueueSystem.QueueTween(mantleLocation, duration);
|
||||
}
|
||||
else if (isOnFloor)
|
||||
{
|
||||
_parent.Velocity = new Vector3(
|
||||
x: _parent.Velocity.X,
|
||||
y: _gravity.CalculateJumpForce(),
|
||||
z: _parent.Velocity.Z);
|
||||
}
|
||||
else if (_canDoubleJump)
|
||||
{
|
||||
_canDoubleJump = false;
|
||||
_parent.Velocity = new Vector3(
|
||||
x: _parent.Velocity.X,
|
||||
y: _gravity.CalculateJumpForce() * DoubleJumpSpeedFactor,
|
||||
z: _parent.Velocity.Z);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
1
systems/move/MoveSystem.cs.uid
Normal file
1
systems/move/MoveSystem.cs.uid
Normal file
@ -0,0 +1 @@
|
||||
uid://dyy5njw6pxoh4
|
Reference in New Issue
Block a user