mirror of
https://github.com/johndoe6345789/metabuilder.git
synced 2026-05-04 02:34:52 +00:00
feat(gameengine): add player inertia and tune Q3 movement to feel weighty
physics.fps.move was directly setting linearVelocity each frame on the
ground, producing the classic "no inertia" snap-stop feel. Replace with
a CalcFriction-style ramp: velocity accelerates toward target by
ground_accel * dt, decelerates to zero by ground_friction * dt when
input is released.
Tune the quake3 frame loop to match a modern shooter rather than vanilla
Q3 arcade speeds:
- walk 4.5 m/s (was 8.0 — ~30 km/h is a sprint, not a walk)
- sprint 1.5x (was 2.0x — 6.75 m/s top speed)
- jump 0.9m / 0.22s (was 2.0m / 0.4s — Halo-ish hop, not a moon jump)
- air control 0.15 (was 0.5 — less floaty mid-jump)
- gravity_scale 1.6 (was 0.3 — was actually pushing the player UP
when falling because of how the (gravityScale - 1.0) extra-force
multiplier worked)
Defaults for the new ground_accel (35) / ground_friction (30) params
keep other workflows that use physics.fps.move feeling snappy without
having to update them.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -14,13 +14,15 @@
|
||||
"typeVersion": 1,
|
||||
"position": [200, 0],
|
||||
"parameters": {
|
||||
"move_speed": 8.0,
|
||||
"sprint_multiplier": 2.0,
|
||||
"crouch_multiplier": 0.4,
|
||||
"jump_height": 2.0,
|
||||
"jump_duration": 0.4,
|
||||
"air_control": 0.5,
|
||||
"gravity_scale": 0.3,
|
||||
"move_speed": 4.5,
|
||||
"sprint_multiplier": 1.5,
|
||||
"crouch_multiplier": 0.45,
|
||||
"jump_height": 0.9,
|
||||
"jump_duration": 0.22,
|
||||
"air_control": 0.15,
|
||||
"gravity_scale": 1.6,
|
||||
"ground_accel": 30.0,
|
||||
"ground_friction": 24.0,
|
||||
"crouch_height": 0.5,
|
||||
"stand_height": 1.4
|
||||
}
|
||||
|
||||
+31
-2
@@ -42,6 +42,11 @@ void WorkflowPhysicsFpsMoveStep::Execute(
|
||||
const float standHeight = getNum("stand_height", 1.6f);
|
||||
const float airControl = getNum("air_control", 0.3f);
|
||||
const float gravityScale = getNum("gravity_scale", 1.0f);
|
||||
// Acceleration model (CalcFriction-style). Velocity accelerates toward the
|
||||
// target each frame instead of snapping. Equal accel/friction = modern feel.
|
||||
const float groundAccel = getNum("ground_accel", 35.0f);
|
||||
const float groundFriction = getNum("ground_friction", 30.0f);
|
||||
const float dtMove = context.Get<float>("physics_dt", 1.0f / 60.0f);
|
||||
|
||||
// Read input state from context (set by input.poll)
|
||||
bool keyW = context.GetBool("input_key_w", false);
|
||||
@@ -100,8 +105,32 @@ void WorkflowPhysicsFpsMoveStep::Execute(
|
||||
}
|
||||
|
||||
if (grounded) {
|
||||
// Full ground control
|
||||
body->setLinearVelocity(btVector3(moveX, currentVel.y(), moveZ));
|
||||
// Inertia model: accelerate horizontal velocity toward target instead of
|
||||
// snap-setting it. When input released, friction decelerates to zero.
|
||||
float horizX = currentVel.x();
|
||||
float horizZ = currentVel.z();
|
||||
if (len > 0.001f) {
|
||||
float diffX = moveX - horizX;
|
||||
float diffZ = moveZ - horizZ;
|
||||
float diffLen = std::sqrt(diffX * diffX + diffZ * diffZ);
|
||||
float maxStep = groundAccel * dtMove;
|
||||
if (diffLen > maxStep && diffLen > 0.0f) {
|
||||
float k = maxStep / diffLen;
|
||||
diffX *= k;
|
||||
diffZ *= k;
|
||||
}
|
||||
horizX += diffX;
|
||||
horizZ += diffZ;
|
||||
} else {
|
||||
float curSpeed = std::sqrt(horizX * horizX + horizZ * horizZ);
|
||||
if (curSpeed > 0.001f) {
|
||||
float drop = std::min(curSpeed, groundFriction * dtMove);
|
||||
float k = (curSpeed - drop) / curSpeed;
|
||||
horizX *= k;
|
||||
horizZ *= k;
|
||||
}
|
||||
}
|
||||
body->setLinearVelocity(btVector3(horizX, currentVel.y(), horizZ));
|
||||
} else {
|
||||
// Air control: blend input with current horizontal velocity (Quake-style)
|
||||
float curX = currentVel.x();
|
||||
|
||||
Reference in New Issue
Block a user