gd: game feel improvement, dash limit, improved jump while aiming for dash

This commit is contained in:
2025-06-16 16:13:29 +02:00
parent b214441b45
commit 107c7622d5
8 changed files with 669 additions and 101 deletions

View File

@ -6,6 +6,13 @@ namespace Movementtests.systems;
public partial class MoveSystem : Node3D
{
public enum JumpTypes
{
SIMPLE_JUMP,
DOUBLE_JUMP,
JUMP_FROM_DASH
}
public record MoveSystemParameters(
CharacterBody3D Parent,
Gravity Gravity,
@ -33,13 +40,19 @@ public partial class MoveSystem : Node3D
[Export(PropertyHint.Range, "0,100,0.1,or_greater")]
public float _currentSpeed;
private const float DecelerationSpeedFactorFloor = 5.0f;
private const float DecelerationSpeedFactorAir = 1.0f;
[Export(PropertyHint.Range, "0,10,0.1,or_greater")]
public float AccelerationSpeedFactorFloor = 5.0f;
[Export(PropertyHint.Range, "0,10,0.1,or_greater")]
public float DecelerationSpeedFactorFloor = 5.0f;
[Export(PropertyHint.Range, "0,10,0.1,or_greater")]
public float DecelerationSpeedFactorAir = 1.0f;
[Export(PropertyHint.Range, "0,1,0.01,or_greater")]
public float ApexHoldTime = 0.0f;
private float _timeLeftAtApex = 0.0f;
private bool _wasGoingUpLastFrame = false;
public float CrouchTransitionSpeed { get; set; } = 20.0f;
[Export(PropertyHint.Range, "0,5,0.1,or_greater")]
public float DoubleJumpSpeedFactor { get; set; } = 2f;
[Export(PropertyHint.Range, "0,1,0.01,or_greater")]
public float WallHugGravityReducingFactor { get; set; } = 0.1f;
@ -61,6 +74,11 @@ public partial class MoveSystem : Node3D
_currentSpeed = WalkSpeed;
}
private bool IsGoingUp()
{
return _parent.Velocity.Y > 0;
}
public void MoveAround(MoveAroundParameters param)
{
var (delta, movementDirection, isOnFloor, isDead, isHeadTouchingCeiling, isHanging, isWallHugging) = param;
@ -68,6 +86,12 @@ public partial class MoveSystem : Node3D
var doesCapsuleHaveCrouchingHeight = _capsuleCollider.IsCrouchingHeight();
var doesCapsuleHaveDefaultHeight = _capsuleCollider.IsDefaultHeight();
if (IsGoingUp() || isOnFloor)
{
_wasGoingUpLastFrame = true;
_timeLeftAtApex = ApexHoldTime;
}
if (isHanging)
{
_parent.Velocity = Vector3.Zero;
@ -86,10 +110,21 @@ public partial class MoveSystem : Node3D
// 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 (!IsGoingUp() && _wasGoingUpLastFrame && _timeLeftAtApex > 0)
{
_parent.Velocity = new Vector3(
x: _parent.Velocity.X,
y: 0,
z: _parent.Velocity.Z);
_timeLeftAtApex -= (float) delta;
}
else
{
_parent.Velocity = new Vector3(
x: _parent.Velocity.X,
y: _parent.Velocity.Y - (_gravity.CalculateGravityForce() * (float)delta),
z: _parent.Velocity.Z);
}
}
// The code below is required to quickly adjust player's position on Y-axis when there's a ceiling on the
@ -139,38 +174,15 @@ public partial class MoveSystem : Node3D
{
direction = Vector3.Zero;
}
var accelerationFloorFactor = direction.Length() > 0 ? AccelerationSpeedFactorFloor : DecelerationSpeedFactorFloor;
var accelerationFactor = isOnFloor ? accelerationFloorFactor : DecelerationSpeedFactorAir;
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);
}
float xAcceleration = Mathf.Lerp(_parent.Velocity.X, direction.X * _currentSpeed,
(float)delta * accelerationFactor);
float zAcceleration = Mathf.Lerp(_parent.Velocity.Z, direction.Z * _currentSpeed,
(float)delta * accelerationFactor);
_parent.Velocity = new Vector3(xAcceleration, _parent.Velocity.Y, zAcceleration);
if (isDead)
{
@ -178,12 +190,25 @@ public partial class MoveSystem : Node3D
}
}
public void Jump(bool isDoubleJump, Vector3? jumpDirection = null, float boost = 1.0f)
public void Jump(JumpTypes jumpType, Vector3? jumpDirection = null, float boost = 1.0f)
{
var effectiveJumpDirection = jumpDirection ?? Vector3.Up;
var jumpForce = isDoubleJump
? _gravity.CalculateJumpForce() * DoubleJumpSpeedFactor
: _gravity.CalculateJumpForce();
var jumpForce = 0.0f;
switch (jumpType)
{
case JumpTypes.DOUBLE_JUMP:
jumpForce = _gravity.CalculateDoubleJumpForce();
break;
case JumpTypes.SIMPLE_JUMP:
jumpForce = _gravity.CalculateJumpForce();
break;
case JumpTypes.JUMP_FROM_DASH:
jumpForce = _gravity.CalculateJumpFromDashForce();
break;
default:
jumpForce = _gravity.CalculateJumpForce();
break;
}
var currentHorizontalVelocity = new Vector3(_parent.Velocity.X, 0, _parent.Velocity.Z);
var jumpVelocity = jumpForce * effectiveJumpDirection * boost;