Thrust Spring (Stop-Spring)

A subtle “suspension” effect that lets the ship coast a little further than its drag curve would otherwise allow once it gets near a full stop. Named in code as stopSpringAmt — the per-ship stat that controls how much the spring reduces drag in the final approach to zero velocity.

Feel

When you release thrust at any meaningful speed, the configured dragCurve (exponential, linear, front_loaded, back_loaded, or overshoot) bleeds velocity off in the normal way. As the ship drops below a threshold of 15 u/s and is no longer thrusting, the spring kicks in: drag is softened so the ship drifts a bit past where it would have stopped and then settles. The intended sensation is a car’s suspension absorbing the last of the momentum, or a hovercraft easing onto its pad.

This is a physics effect, not a sprite-only tween. The body’s vx/vy themselves decay more slowly during the final glide.

How it works (engine/physics/movement.ts)

The relevant code lives at the end of the per-frame drag block in Physics.update:

// stopSpringAmt: below STOP_SPEED_THRESHOLD, weaken drag so the ship
// coasts a little further before fully stopping.
if ((ship.stopSpringAmt ?? 0) > 0 && !playerInput.isThrusting && currentSpeedForDrag < STOP_SPEED_THRESHOLD) {
  const t = currentSpeedForDrag / STOP_SPEED_THRESHOLD;
  const springMul = 1 - ship.stopSpringAmt * (1 - t);
  dragArg = 1 - (1 - dragArg) * Math.max(0.05, springMul);
}
ship.vx *= dragArg;
ship.vy *= dragArg;

Three gating conditions, all required:

  1. stopSpringAmt > 0 — the ship’s per-hull stat is non-zero.
  2. !playerInput.isThrusting — the player has let go of thrust.
  3. currentSpeedForDrag < STOP_SPEED_THRESHOLD — current speed is under STOP_SPEED_THRESHOLD = 15 u/s (the same threshold that triggers the one-shot stop-shake camera signal on a hard stop).

When gated in, t is a 0→1 progress through the threshold band. springMul starts at 1 - stopSpringAmt at zero speed and rises back to 1 at the threshold. That value multiplies into (1 - dragArg) — the bit of drag the exponential decay was about to apply — and shrinks it, but never below 5% of the original drag (Math.max(0.05, ...)). So the ship still slows; it just slows less in the last fifteen units of speed.

Tuning surface

Defined on the ship def in data/ships.ts:

/** Spring-back amount when stopping. 0 = no overshoot. Small positive values cause
 *  the ship to drift a tiny bit past zero velocity and then settle (like a car's
 *  suspension absorbing momentum). Typical: 0.05-0.15. */
stopSpringAmt: number;
  • 0 — no spring. Drag curve runs cleanly to zero. Current default for every ★1 hull in SHIP_STATS_S1 and every fully-defined ship def in the file.
  • 0.050.15 — typical authored range when a designer wants the feel.
  • Higher values bias the late-stop band toward longer coast; the floor of 0.05 on springMul prevents the ship from becoming undamped (it can never fully stop coasting once gated in).

The field lives on BASELINE_STATS (default 0), is listed in the canonical SHIP_STAT_FIELDS array, and is upgradeable through the standard ★1→★5 stat lerp pipeline.

  • Drag curves — the broader system of how thrust-off deceleration shapes. stopSpringAmt is a final-approach modifier that runs after whichever curve is active.
  • Stop-shake — uses the same STOP_SPEED_THRESHOLD = 15 u/s boundary. Crossing down through it while not thrusting fires the one-shot camera shake; the spring acts on the other side of that crossing to delay the exact moment of full stop.
  • engine/core/types.ts and data/run-config.ts mirror the field on the live ship state and run-config respectively.

Source map

  • src/starship-survivors/engine/physics/movement.tsSTOP_SPEED_THRESHOLD constant (line ~33) + spring branch inside Physics.update (lines ~326–332).
  • src/starship-survivors/data/ships.tsstopSpringAmt field on ShipDef (line ~99), BASELINE_STATS default (line ~198), SHIP_STAT_FIELDS entry (line ~341), and per-hull ★1 entries in SHIP_STATS_S1.
  • src/starship-survivors/engine/core/types.tsstopSpringAmt on the live ship state shape (line ~639).
  • src/starship-survivors/data/run-config.ts — run-config mirror (line ~165).
  • src/starship-survivors/screens/playground/ShipsTab.tsx — designer-facing tuning surface in the dev playground.