Jump: hold right A to charge (legs bend), release to jump
Tap hops ~0.16 m, full charge ~0.68 m, a real crouch charges too. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
537e72c207
commit
0bddcf4517
3 files changed
+52
-49
No files matched your search
+32
-27
@@ -64,15 +64,16 @@ public partial class PlayerRagdoll : Node3D
|
||||
// ~0.3 m from 1 m, legs fully folded from a big fall (Boneworks) — then the normal rise.
|
||||
public const float LandingReach = 0.05f; // m past the pose's hip height
|
||||
public const float AbsorbTime = 0.4f; // s after a hard touchdown the head guide stays off (it would hold the dip up)
|
||||
// Jump (right A): a short countermovement dip, then the legs push JumpForce over the stroke up to
|
||||
// full extension. Takeoff speed is physics — v² = 2·(F/m − g)·stroke — so a crouch before
|
||||
// the press (real or stick) jumps higher: ~0.45 m standing, ~0.7 m from a deep crouch.
|
||||
public const float JumpForce = 2.4f; // × body weight
|
||||
public const float JumpDip = 0.2f; // m the hips drop first when pressed from standing
|
||||
// Jump (right A, Boneworks-style hold to charge, release to jump): holding bends the legs — the
|
||||
// support goal sinks at ChargeSpeed down to JumpMaxStroke below full extension — and releasing
|
||||
// pushes JumpForce over that stroke up to extension. Takeoff speed is physics,
|
||||
// v² = 2·(F/m − g)·stroke: a tap hops, a full charge (or a real/stick crouch) jumps ~0.7 m.
|
||||
public const float JumpForce = 2.2f; // × body weight
|
||||
public const float ChargeSpeed = 1.2f; // m/s the hips sink while A is held
|
||||
public const float JumpExtension = 0.06f; // m above the standing hips at toe-off
|
||||
public const float JumpMaxStroke = 0.5f;
|
||||
public const float JumpBuffer = 0.15f; // s a press is remembered before touchdown
|
||||
public const float CoyoteTime = 0.12f; // s after leaving the ground a jump still works
|
||||
public const float JumpMinStroke = 0.08f; // a tap still hops
|
||||
public const float CoyoteTime = 0.12f; // s after leaving the ground a release still jumps
|
||||
public const float MaxSlopeDegrees = 35f; // steeper ground gives no support (Nimso: "slopes beyond an angle can't be run up") // higher ground under the hips isn't stood on unless the body got up there
|
||||
public const float BracedAirControl = 150f; // N of horizontal hip carry while airborne but braced on the hands (mantling)
|
||||
public const float CrawlCarry = 300f;
|
||||
@@ -197,12 +198,13 @@ public partial class PlayerRagdoll : Node3D
|
||||
return GetWorld3D().DirectSpaceState.IntersectShape(_legsQuery, 1).Count == 0;
|
||||
}
|
||||
private Vector3 _goalVelocity;
|
||||
private enum JumpPhase { None, Dip, Push, Flight }
|
||||
private enum JumpPhase { None, Charge, Push, Flight }
|
||||
private JumpPhase _jump;
|
||||
private float _jumpT, _jumpRequest, _airT, _jumpFromY, _sinceLanding = float.MaxValue;
|
||||
private float _jumpT, _airT, _jumpFromY, _sinceLanding = float.MaxValue;
|
||||
private bool _jumpHeld;
|
||||
|
||||
// Right A. Buffered, so a press just before touchdown still jumps.
|
||||
public void Jump() => _jumpRequest = JumpBuffer;
|
||||
// Right A, every tick. Holding while landing starts the charge on touchdown.
|
||||
public bool JumpHeld { set => _jumpHeld = value; }
|
||||
|
||||
private float _standingHip; // hips of the standing pose above the feet = the legs' full extension
|
||||
|
||||
@@ -349,7 +351,7 @@ public partial class PlayerRagdoll : Node3D
|
||||
_arms[i] = new Arm();
|
||||
Built = false;
|
||||
_jump = JumpPhase.None;
|
||||
_jumpRequest = 0f;
|
||||
_jumpHeld = false;
|
||||
_sinceLanding = float.MaxValue;
|
||||
}
|
||||
|
||||
@@ -931,7 +933,7 @@ public partial class PlayerRagdoll : Node3D
|
||||
// tiptoes, a reach up — would otherwise float the body off the ground).
|
||||
goal.Y = Mathf.Min(goal.Y, _footY + _standingHip + JumpExtension);
|
||||
_supportGoalY = goal.Y;
|
||||
if (_jump == JumpPhase.Dip)
|
||||
if (_jump == JumpPhase.Charge)
|
||||
goal.Y = Mathf.Min(goal.Y, _jumpFromY);
|
||||
float w = Mathf.Tau * GroundFrequency;
|
||||
Vector3 accel = (goal - pos) * (w * w) + (targetVelocity - Pelvis.LinearVelocity) * (2f * GroundDamping * w);
|
||||
@@ -984,35 +986,38 @@ public partial class PlayerRagdoll : Node3D
|
||||
}
|
||||
}
|
||||
|
||||
// Jump state: request → Dip (countermovement, the support goal drops) → Push (full leg force up to
|
||||
// extension) → Flight (no ground until falling again) → None on touchdown.
|
||||
// Jump state: held → Charge (the support goal sinks: the legs bend) → released → Push (full leg
|
||||
// force up to extension) → Flight (no ground until falling again) → None on touchdown.
|
||||
private void UpdateJump(float dt, bool wasGrounded)
|
||||
{
|
||||
_airT = Grounded ? 0f : _airT + dt;
|
||||
_jumpRequest -= dt;
|
||||
_jumpT += dt;
|
||||
float pos = Pelvis.GlobalPosition.Y;
|
||||
float top = _footY + _standingHip + JumpExtension;
|
||||
switch (_jump)
|
||||
{
|
||||
case JumpPhase.None:
|
||||
if (_jumpRequest > 0f && (Grounded || _airT < CoyoteTime) && !Climbing)
|
||||
if (_jumpHeld && Grounded && !Climbing)
|
||||
{
|
||||
_jumpRequest = 0f;
|
||||
_jump = JumpPhase.Charge;
|
||||
_jumpT = 0f;
|
||||
// Stroke at least JumpDip + JumpExtension: from standing, dip first.
|
||||
_jumpFromY = Mathf.Max(top - JumpMaxStroke, Mathf.Min(pos, top - JumpDip - JumpExtension));
|
||||
_jump = pos > _jumpFromY + 0.02f && Grounded ? JumpPhase.Dip : JumpPhase.Push;
|
||||
_jumpFromY = Mathf.Min(_jumpFromY, pos);
|
||||
_jumpFromY = Mathf.Min(pos, top);
|
||||
}
|
||||
break;
|
||||
case JumpPhase.Dip:
|
||||
if (pos <= _jumpFromY + 0.02f || _jumpT > 0.2f || !Grounded)
|
||||
case JumpPhase.Charge:
|
||||
if (!Grounded && _airT > CoyoteTime || Climbing)
|
||||
{
|
||||
_jump = JumpPhase.Push;
|
||||
_jumpFromY = pos;
|
||||
_jumpT = 0f;
|
||||
_jump = JumpPhase.None; // walked off or grabbed something while charging
|
||||
break;
|
||||
}
|
||||
if (_jumpHeld)
|
||||
{
|
||||
_jumpFromY = Mathf.Max(top - JumpMaxStroke, _jumpFromY - ChargeSpeed * dt);
|
||||
break;
|
||||
}
|
||||
_jump = JumpPhase.Push;
|
||||
_jumpFromY = Mathf.Min(pos, top - JumpMinStroke);
|
||||
_jumpT = 0f;
|
||||
break;
|
||||
case JumpPhase.Push:
|
||||
if (pos >= top || pos - _jumpFromY >= JumpMaxStroke || _jumpT > 0.35f)
|
||||
|
||||
Reference in new issue
Block a user