Double jump and triple jump
const MAX_JUMPS = 2 // set to 3 for a triple jump — same code either way
const AIR_JUMP_VELOCITY = 420.0 // can differ from the grounded JUMP_VELOCITY_FULL
state jumps_used = 0
function reset_jump_count():
if is_grounded:
jumps_used = 0
function handle_multi_jump_input():
if not input.was_pressed("jump"):
return
if coyote_timer > 0.0:
// Ground jump (or coyote-forgiven ground jump) — doesn't consume an air jump.
start_jump()
coyote_timer = 0.0
jumps_used = 1 // the ground jump itself counts toward the total
elif jumps_used < MAX_JUMPS:
perform_air_jump()
function perform_air_jump():
// Cancel existing vertical velocity before applying the new impulse, rather
// than adding on top of it — otherwise an air jump thrown while already
// falling fast feels weak or gets partially "eaten" by residual fall speed.
velocity.y = -AIR_JUMP_VELOCITY
jumps_used += 1
jump_time_elapsed = 0.0 // re-arm variable-height cutting (section 5) for this jump
jump_held = true
function update(dt):
is_grounded = check_grounded()
update_coyote_timer(dt)
reset_jump_count()
handle_multi_jump_input()
handle_jump_release() // section 5 — variable height applies per-jump
apply_variable_gravity(dt)
integrate_vertical(dt)
How it works¶
The mechanical change from a single jump to a double (or triple) jump is small: track jumps_used, reset it to 0 only when grounded, and allow additional in-air jumps up to MAX_JUMPS as long as the counter hasn't been reached. The one detail worth calling out is overwriting velocity.y rather than adding to it in perform_air_jump. If a player double-jumps while already falling at high speed, adding the jump impulse on top of that downward velocity produces a jump that's visibly weaker than the first one (or barely rises at all) — overwriting guarantees every jump in the chain looks and feels the same regardless of when in the fall it's thrown.
jumps_used is set to 1 (not incremented from 0) on a ground/coyote jump specifically so the first jump of a sequence always counts against the total — otherwise a player could jump normally, then still get MAX_JUMPS additional air jumps on top, silently turning a "double jump" into a triple.
Where "more jumps" stops adding fun is a genuine design question, not just a numbers tweak. Going from one jump to two is usually a clear win: it opens up vertical traversal options, forgives mistimed jumps mid-air, and gives players a tool to actively solve platforming puzzles ("I have one correction available"). Going from two to three tends to have diminishing — sometimes negative — returns in a straightforward platformer: with three jumps available, precise timing and commitment to a single jump arc matter much less, floaty extended airtime can start to feel less grounded and more like flying, and a lot of platforming challenges built around "you get one shot at this gap" simply stop being challenges. Games that do ship a third jump successfully (Mario 64's actual triple jump is the canonical example) usually differentiate it rather than just stacking the same jump again — a longer/higher arc as a reward for a run-jump-jump input chain, or tying it to a combo/momentum condition rather than making it unconditionally available like the first two. If you want a third air option and it's starting to feel trivializing, it's often better designed as a different move (an air dash, a slam) than a literal third instance of the same jump.