Skip to content

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.