revamped megajump and air control
This commit is contained in:
@ -50,11 +50,18 @@ blend_mode = 1
|
||||
|
||||
[node name="Player" type="CharacterBody3D"]
|
||||
script = ExtResource("1_poq2x")
|
||||
AccelerationSpeedFactorFloor = 3.0
|
||||
WalkSpeed = 7.5
|
||||
AccelerationAir = 2.0
|
||||
DecelerationAir = 0.1
|
||||
Weight = 5.0
|
||||
SimpleJumpStartVelocity = 7.0
|
||||
HangTimeInFrames = 3
|
||||
GravityLesseningFactorUpward = 2.5
|
||||
SimpleJumpStartVelocity = 8.0
|
||||
SimpleJumpHangTimeInFrames = 3
|
||||
SimpleJumpGravityLesseningFactor = 2.5
|
||||
DoubleJumpStartVelocity = 15.0
|
||||
DoubleJumpGravityLesseningFactor = 1.2
|
||||
MegaJumpStartVelocity = 30.0
|
||||
MegaJumpHangTimeInFrames = 15
|
||||
MegaJumpGravityLesseningFactor = 1.2
|
||||
JumpFromDashSpeedFactor = 4.0
|
||||
WallHugHorizontalDeceleration = 3.0
|
||||
MaxJumpBoostAfterDashing = 0.7
|
||||
@ -452,18 +459,42 @@ initial_state = NodePath("SimpleJump")
|
||||
[node name="SimpleJump" type="Node" parent="StateChart/Root/Movement/Jump"]
|
||||
script = ExtResource("27_34snm")
|
||||
|
||||
[node name="OnMegajump" type="Node" parent="StateChart/Root/Movement/Jump/SimpleJump"]
|
||||
script = ExtResource("28_n7qhm")
|
||||
to = NodePath("../../MegaJump")
|
||||
event = &"megajump"
|
||||
delay_in_seconds = "0.0"
|
||||
|
||||
[node name="OnJumpEnded" type="Node" parent="StateChart/Root/Movement/Jump/SimpleJump"]
|
||||
script = ExtResource("28_n7qhm")
|
||||
to = NodePath("../../../Airborne/DoubleJumpEnabled")
|
||||
event = &"jump_ended"
|
||||
delay_in_seconds = "0.0"
|
||||
|
||||
[node name="Double" type="Node" parent="StateChart/Root/Movement/Jump"]
|
||||
[node name="DoubleJump" type="Node" parent="StateChart/Root/Movement/Jump"]
|
||||
script = ExtResource("27_34snm")
|
||||
|
||||
[node name="Empowered" type="Node" parent="StateChart/Root/Movement/Jump"]
|
||||
[node name="OnMegajump" type="Node" parent="StateChart/Root/Movement/Jump/DoubleJump"]
|
||||
script = ExtResource("28_n7qhm")
|
||||
to = NodePath("../../MegaJump")
|
||||
event = &"megajump"
|
||||
delay_in_seconds = "0.0"
|
||||
|
||||
[node name="OnJumpEnded" type="Node" parent="StateChart/Root/Movement/Jump/DoubleJump"]
|
||||
script = ExtResource("28_n7qhm")
|
||||
to = NodePath("../../../Airborne/Falling")
|
||||
event = &"jump_ended"
|
||||
delay_in_seconds = "0.0"
|
||||
|
||||
[node name="MegaJump" type="Node" parent="StateChart/Root/Movement/Jump"]
|
||||
script = ExtResource("27_34snm")
|
||||
|
||||
[node name="OnJumpEnded" type="Node" parent="StateChart/Root/Movement/Jump/MegaJump"]
|
||||
script = ExtResource("28_n7qhm")
|
||||
to = NodePath("../../../Airborne/Falling")
|
||||
event = &"jump_ended"
|
||||
delay_in_seconds = "0.0"
|
||||
|
||||
[node name="Grounded" type="Node" parent="StateChart/Root/Movement"]
|
||||
script = ExtResource("27_34snm")
|
||||
|
||||
@ -475,7 +506,7 @@ delay_in_seconds = "0.0"
|
||||
|
||||
[node name="OnMegajump" type="Node" parent="StateChart/Root/Movement/Grounded"]
|
||||
script = ExtResource("28_n7qhm")
|
||||
to = NodePath("../../Airborne/Falling")
|
||||
to = NodePath("../../Jump/MegaJump")
|
||||
event = &"megajump"
|
||||
delay_in_seconds = "0.0"
|
||||
|
||||
@ -493,6 +524,12 @@ initial_state = NodePath("CoyoteEnabled")
|
||||
script = ExtResource("41_ruloh")
|
||||
default_state = NodePath("../CoyoteEnabled")
|
||||
|
||||
[node name="OnMegajump" type="Node" parent="StateChart/Root/Movement/Airborne"]
|
||||
script = ExtResource("28_n7qhm")
|
||||
to = NodePath("../../Jump/MegaJump")
|
||||
event = &"megajump"
|
||||
delay_in_seconds = "0.0"
|
||||
|
||||
[node name="OnGrounded" type="Node" parent="StateChart/Root/Movement/Airborne"]
|
||||
script = ExtResource("28_n7qhm")
|
||||
to = NodePath("../../Grounded")
|
||||
@ -531,7 +568,7 @@ script = ExtResource("27_34snm")
|
||||
|
||||
[node name="OnJump" type="Node" parent="StateChart/Root/Movement/Airborne/DoubleJumpEnabled"]
|
||||
script = ExtResource("28_n7qhm")
|
||||
to = NodePath("../../Falling")
|
||||
to = NodePath("../../../Jump/DoubleJump")
|
||||
event = &"jump"
|
||||
delay_in_seconds = "0.0"
|
||||
|
||||
|
@ -60,12 +60,14 @@ public partial class PlayerController : CharacterBody3D
|
||||
[Export(PropertyHint.Range, "0,20,0.1,or_greater")]
|
||||
public float WalkSpeed { get; set; } = 7.0f;
|
||||
[Export(PropertyHint.Range, "0,10,0.1,or_greater")]
|
||||
public float AccelerationSpeedFactorFloor = 5.0f;
|
||||
public float AccelerationFloor = 5.0f;
|
||||
[Export(PropertyHint.Range, "0,10,0.1,or_greater")]
|
||||
public float DecelerationSpeedFactorFloor = 5.0f;
|
||||
public float DecelerationFloor = 5.0f;
|
||||
[ExportGroup("Air")]
|
||||
[Export(PropertyHint.Range, "0,10,0.1,or_greater")]
|
||||
public float DecelerationSpeedFactorAir = 1.0f;
|
||||
public float AccelerationAir = 3.0f;
|
||||
[Export(PropertyHint.Range, "0,10,0.01,or_greater")]
|
||||
public float DecelerationAir = 1.0f;
|
||||
[Export(PropertyHint.Range, "0,10,0.01,or_greater")]
|
||||
public float Weight { get; set; } = 3.0f;
|
||||
|
||||
@ -77,9 +79,29 @@ public partial class PlayerController : CharacterBody3D
|
||||
[Export(PropertyHint.Range, "0,100,1,or_greater")]
|
||||
public float SimpleJumpStartVelocity { get; set; } = 3.0f;
|
||||
[Export(PropertyHint.Range, "0,10,1,or_greater")]
|
||||
public int HangTimeInFrames { get; set; } = 5;
|
||||
public int SimpleJumpHangTimeInFrames { get; set; } = 5;
|
||||
[Export(PropertyHint.Range, "1,10,0.1,or_greater")]
|
||||
public float GravityLesseningFactorUpward { get; set; } = 3f;
|
||||
public float SimpleJumpGravityLesseningFactor { get; set; } = 3f;
|
||||
|
||||
|
||||
// Double jump
|
||||
[ExportSubgroup("Double jump")]
|
||||
[Export(PropertyHint.Range, "0,100,1,or_greater")]
|
||||
public float DoubleJumpStartVelocity { get; set; } = 10.0f;
|
||||
[Export(PropertyHint.Range, "0,10,1,or_greater")]
|
||||
public int DoubleJumpHangTimeInFrames { get; set; } = 5;
|
||||
[Export(PropertyHint.Range, "1,10,0.1,or_greater")]
|
||||
public float DoubleJumpGravityLesseningFactor { get; set; } = 3f;
|
||||
|
||||
|
||||
// Mega jump
|
||||
[ExportSubgroup("Mega jump")]
|
||||
[Export(PropertyHint.Range, "0,100,1,or_greater")]
|
||||
public float MegaJumpStartVelocity { get; set; } = 10.0f;
|
||||
[Export(PropertyHint.Range, "0,10,1,or_greater")]
|
||||
public int MegaJumpHangTimeInFrames { get; set; } = 5;
|
||||
[Export(PropertyHint.Range, "1,10,0.1,or_greater")]
|
||||
public float MegaJumpGravityLesseningFactor { get; set; } = 3f;
|
||||
|
||||
// Other jump
|
||||
[ExportSubgroup("Other jump")]
|
||||
@ -153,6 +175,8 @@ public partial class PlayerController : CharacterBody3D
|
||||
private StateChartState _airborne;
|
||||
private StateChartState _coyoteEnabled;
|
||||
private StateChartState _simpleJump;
|
||||
private StateChartState _doubleJump;
|
||||
private StateChartState _megaJump;
|
||||
private StateChartState _doubleJumpEnabled;
|
||||
private StateChartState _onWall;
|
||||
private StateChartState _onWallHugCanceled;
|
||||
@ -230,6 +254,8 @@ public partial class PlayerController : CharacterBody3D
|
||||
_airborne = StateChartState.Of(GetNode("StateChart/Root/Movement/Airborne"));
|
||||
_coyoteEnabled = StateChartState.Of(GetNode("StateChart/Root/Movement/Airborne/CoyoteEnabled"));
|
||||
_simpleJump = StateChartState.Of(GetNode("StateChart/Root/Movement/Jump/SimpleJump"));
|
||||
_doubleJump = StateChartState.Of(GetNode("StateChart/Root/Movement/Jump/DoubleJump"));
|
||||
_megaJump = StateChartState.Of(GetNode("StateChart/Root/Movement/Jump/MegaJump"));
|
||||
_doubleJumpEnabled = StateChartState.Of(GetNode("StateChart/Root/Movement/Airborne/DoubleJumpEnabled"));
|
||||
_onWall = StateChartState.Of(GetNode("StateChart/Root/Movement/OnWall"));
|
||||
_onWallHugging = StateChartState.Of(GetNode("StateChart/Root/Movement/OnWall/Hugging"));
|
||||
@ -311,18 +337,56 @@ public partial class PlayerController : CharacterBody3D
|
||||
// _empowerOff.StateEntered += EmpowerStopped;
|
||||
// _empowerTimeDownscale.Timeout += EmpowerTimerTimeout;
|
||||
|
||||
_powerFull.StateEntered += StopPowerCooldown;
|
||||
_powerFull.StateExited += StartPowerCooldown;
|
||||
_powerRecharging.StateEntered += StartPowerCooldown;
|
||||
_powerFull.StateEntered += StopPowerCooldown;
|
||||
_powerCooldownTimer.Timeout += PowerCooldownExpired;
|
||||
_powerRecharging.StateProcessing += PowerRecharging;
|
||||
_powerExpired.StateProcessing += PowerRecharging;
|
||||
|
||||
_simpleJump.StateEntered += OnSimpleJumpStarted;
|
||||
_simpleJump.StatePhysicsProcessing += HandleSimpleJump;
|
||||
_simpleJump.StateExited += OnSimpleJumpEnded;
|
||||
|
||||
_doubleJump.StateEntered += OnDoubleJumpStarted;
|
||||
_doubleJump.StatePhysicsProcessing += HandleDoubleJump;
|
||||
|
||||
_megaJump.StateEntered += OnMegaJumpStarted;
|
||||
_megaJump.StatePhysicsProcessing += HandleMegaJump;
|
||||
}
|
||||
|
||||
// Physics processes
|
||||
public void HandleGrounded(float delta)
|
||||
{
|
||||
MoveOnGround(delta);
|
||||
_canDash = true;
|
||||
if (!isOnFloorCustom())
|
||||
_playerState.SendEvent("start_falling");
|
||||
}
|
||||
public void HandleAirborne(float delta)
|
||||
{
|
||||
MoveInAir(delta);
|
||||
if (isOnFloorCustom())
|
||||
_playerState.SendEvent("grounded");
|
||||
if (WallHugSystem.IsWallHugging() && Velocity.Y < 0)
|
||||
_playerState.SendEvent("wall_hug");
|
||||
}
|
||||
public void HandleWallHugging(float delta)
|
||||
{
|
||||
WallHug(delta);
|
||||
if (isOnFloorCustom())
|
||||
_playerState.SendEvent("grounded");
|
||||
if (!WallHugSystem.IsWallHugging())
|
||||
_playerState.SendEvent("start_falling");
|
||||
}
|
||||
|
||||
public void HandleWallHanging(float delta)
|
||||
{
|
||||
WallHang(delta);
|
||||
}
|
||||
|
||||
// Jump
|
||||
private int _framesSinceJumpAtApex = 0;
|
||||
|
||||
public void OnInputJumpStarted()
|
||||
{
|
||||
if (CanMantle())
|
||||
@ -352,6 +416,11 @@ public partial class PlayerController : CharacterBody3D
|
||||
// else if (_onWall.Active)
|
||||
// JumpFromWall(_empowerOn.Active);
|
||||
|
||||
if (_empowerOn.Active && CanPerformEmpoweredAction())
|
||||
{
|
||||
_playerState.SendEvent("megajump");
|
||||
return;
|
||||
}
|
||||
_playerState.SendEvent("jump");
|
||||
}
|
||||
|
||||
@ -364,31 +433,66 @@ public partial class PlayerController : CharacterBody3D
|
||||
_playerState.SendEvent("jump_ended");
|
||||
}
|
||||
|
||||
private int _framesSinceJumpAtApex = 0;
|
||||
public void OnSimpleJumpStarted()
|
||||
public void OnJumpStarted(float verticalVelocity)
|
||||
{
|
||||
_framesSinceJumpAtApex = 0;
|
||||
SetVerticalVelocity(verticalVelocity);
|
||||
}
|
||||
public void OnSimpleJumpStarted()
|
||||
{
|
||||
OnJumpStarted(SimpleJumpStartVelocity);
|
||||
}
|
||||
public void OnDoubleJumpStarted()
|
||||
{
|
||||
OnJumpStarted(DoubleJumpStartVelocity);
|
||||
}
|
||||
public void OnMegaJumpStarted()
|
||||
{
|
||||
OnJumpStarted(MegaJumpStartVelocity);
|
||||
}
|
||||
|
||||
public Vector3 ComputeHVelocity(float delta, float accelerationFactor, float decelerationFactor)
|
||||
{
|
||||
Vector3 direction = HeadSystem.Transform.Basis * _inputMove;
|
||||
var acceleration = direction.Length() > 0 ? accelerationFactor : decelerationFactor;
|
||||
|
||||
float xAcceleration = Mathf.Lerp(Velocity.X, direction.X * _targetSpeed, delta * acceleration);
|
||||
float zAcceleration = Mathf.Lerp(Velocity.Z, direction.Z * _targetSpeed, delta * acceleration);
|
||||
return new Vector3(xAcceleration, 0, zAcceleration);
|
||||
}
|
||||
public Vector3 ComputeHVelocityGround(float delta)
|
||||
{
|
||||
|
||||
return ComputeHVelocity(delta, AccelerationFloor, DecelerationFloor);
|
||||
}
|
||||
public Vector3 ComputeHVelocityAir(float delta)
|
||||
{
|
||||
return ComputeHVelocity(delta, AccelerationAir, DecelerationAir);
|
||||
}
|
||||
|
||||
public void SetVerticalVelocity(float verticalVelocity)
|
||||
{
|
||||
Velocity = new Vector3(
|
||||
x: Velocity.X,
|
||||
y: SimpleJumpStartVelocity,
|
||||
y: verticalVelocity,
|
||||
z: Velocity.Z);
|
||||
}
|
||||
|
||||
public void HandleSimpleJump(float delta)
|
||||
public void HandleJump(float delta, float gravityFactor, int hangFrames)
|
||||
{
|
||||
// Update horizontal velocity
|
||||
var horizontalVelocity = ComputeHVelocityAir(delta);
|
||||
Velocity = new Vector3(horizontalVelocity.X, Velocity.Y, horizontalVelocity.Z);
|
||||
|
||||
// Hang time at the top of the jump
|
||||
if (Velocity.Y <= Mathf.Epsilon)
|
||||
{
|
||||
_framesSinceJumpAtApex++;
|
||||
Velocity = new Vector3(
|
||||
x: Velocity.X,
|
||||
y: 0,
|
||||
z: Velocity.Z);
|
||||
SetVerticalVelocity(0);
|
||||
}
|
||||
|
||||
// Cancel gravity on jump apex
|
||||
var gravity = CalculateGravityForce() / GravityLesseningFactorUpward;
|
||||
var gravity = CalculateGravityForce() / gravityFactor;
|
||||
var isAtApex = _framesSinceJumpAtApex > 0;
|
||||
if (isAtApex)
|
||||
{
|
||||
@ -396,19 +500,27 @@ public partial class PlayerController : CharacterBody3D
|
||||
}
|
||||
// Update velocity accordingly
|
||||
var newVerticalSpeed = Velocity.Y - gravity * delta;
|
||||
Velocity = new Vector3(
|
||||
x: Velocity.X,
|
||||
y: newVerticalSpeed,
|
||||
z: Velocity.Z);
|
||||
|
||||
SetVerticalVelocity(newVerticalSpeed);
|
||||
if (IsHeadTouchingCeiling())
|
||||
{
|
||||
SetVerticalVelocity(Velocity.Y - 2.0f);
|
||||
}
|
||||
|
||||
// Move back to Airborne state management when starting to go down again
|
||||
if (_framesSinceJumpAtApex > HangTimeInFrames)
|
||||
if (_framesSinceJumpAtApex > hangFrames)
|
||||
_playerState.SendEvent("jump_ended");
|
||||
}
|
||||
|
||||
public void OnSimpleJumpEnded()
|
||||
public void HandleSimpleJump(float delta)
|
||||
{
|
||||
HandleJump(delta, SimpleJumpGravityLesseningFactor, SimpleJumpHangTimeInFrames);
|
||||
}
|
||||
public void HandleDoubleJump(float delta)
|
||||
{
|
||||
HandleJump(delta, DoubleJumpGravityLesseningFactor, DoubleJumpHangTimeInFrames);
|
||||
}
|
||||
public void HandleMegaJump(float delta)
|
||||
{
|
||||
HandleJump(delta, MegaJumpGravityLesseningFactor, MegaJumpHangTimeInFrames);
|
||||
}
|
||||
|
||||
public void PowerRecharging(float delta)
|
||||
@ -777,36 +889,6 @@ public partial class PlayerController : CharacterBody3D
|
||||
DashSystem.PrepareDash();
|
||||
}
|
||||
|
||||
// Physics processes
|
||||
public void HandleGrounded(float delta)
|
||||
{
|
||||
MoveOnGround(delta);
|
||||
_canDash = true;
|
||||
if (!isOnFloorCustom())
|
||||
_playerState.SendEvent("start_falling");
|
||||
}
|
||||
public void HandleAirborne(float delta)
|
||||
{
|
||||
MoveInAir(delta);
|
||||
if (isOnFloorCustom())
|
||||
_playerState.SendEvent("grounded");
|
||||
if (WallHugSystem.IsWallHugging() && Velocity.Y < 0)
|
||||
_playerState.SendEvent("wall_hug");
|
||||
}
|
||||
public void HandleWallHugging(float delta)
|
||||
{
|
||||
WallHug(delta);
|
||||
if (isOnFloorCustom())
|
||||
_playerState.SendEvent("grounded");
|
||||
if (!WallHugSystem.IsWallHugging())
|
||||
_playerState.SendEvent("start_falling");
|
||||
}
|
||||
|
||||
public void HandleWallHanging(float delta)
|
||||
{
|
||||
WallHang(delta);
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////
|
||||
// Stateless logic ////////
|
||||
@ -819,33 +901,15 @@ public partial class PlayerController : CharacterBody3D
|
||||
|
||||
public void MoveOnGround(double delta)
|
||||
{
|
||||
Vector3 direction = HeadSystem.Transform.Basis * _inputMove;
|
||||
|
||||
var accelerationFactor = direction.Length() > 0 ? AccelerationSpeedFactorFloor : DecelerationSpeedFactorFloor;
|
||||
|
||||
float xAcceleration = Mathf.Lerp(Velocity.X, direction.X * _targetSpeed,
|
||||
(float)delta * accelerationFactor);
|
||||
float zAcceleration = Mathf.Lerp(Velocity.Z, direction.Z * _targetSpeed,
|
||||
(float)delta * accelerationFactor);
|
||||
Velocity = new Vector3(xAcceleration, Velocity.Y, zAcceleration);
|
||||
var horizontalVelocity = ComputeHVelocityGround((float) delta);
|
||||
Velocity = new Vector3(horizontalVelocity.X, Velocity.Y, horizontalVelocity.Z);
|
||||
}
|
||||
|
||||
public void MoveInAir(double delta)
|
||||
{
|
||||
Velocity = new Vector3(
|
||||
x: Velocity.X,
|
||||
y: Velocity.Y - (CalculateGravityForce() * (float)delta),
|
||||
z: Velocity.Z);
|
||||
|
||||
// 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())
|
||||
{
|
||||
Velocity = new Vector3(
|
||||
x: Velocity.X,
|
||||
y: Velocity.Y - 2.0f,
|
||||
z: Velocity.Z);
|
||||
}
|
||||
var horizontalVelocity = ComputeHVelocityAir((float) delta);
|
||||
var verticalVelocity = Velocity.Y - (CalculateGravityForce() * (float)delta);
|
||||
Velocity = new Vector3(horizontalVelocity.X, verticalVelocity, horizontalVelocity.Z);
|
||||
}
|
||||
|
||||
public void WallHug(float delta)
|
||||
|
Reference in New Issue
Block a user