Variable-height platformer jumps


In a lot of platformers, tapping the jump button produces a short hop and holding it produces a long jump. Despite the feature’s apparent simplicity, implementing a system like this can be tricky.

The simplest way to implement a jump feature would be via an instantaneous velocity change:

if jump_button_just_pressed then
    player.velocity.y = JUMP_VELOCITY
end

For a short hop, we’d just define a different velocity value:

if jump_button_just_pressed then
    if long_jump then
        player.velocity.y = JUMP_VELOCITY_LONG
    else
        player.velocity.y = JUMP_VELOCITY_SHORT
    end
end

The problem should be obvious. We can’t know which velocity to apply with this technique until after the long-jump velocity time has passed. Waiting to check if the player’s holding down the button before applying the jump velocity would be sluggish for all but the shortest of time differences between the two jumps.

The tension in implementing a variable-height jump mechanic is that it appears to be based on knowledge of a player’s intent before there’s evidence for it. When a jump starts, how can your code know whether the player’s going to be still holding the button 100 milliseconds from now?

In the past, I’ve solved this problem with a fast-ticking timer to apply fractions of a total jump velocity depending on how long the button is held. With this approach, for example, you’d apply a tenth of the velocity on the first frame, then another tenth on the second, climbing all the way up to a full jump at 10 frames.

This approach works; however, it can be difficult to tune and produces an unappealing acceleration effect when the fraction is small.

To a player, a short hop versus a long jump appears to be a difference in the character’s jump force. But we can reproduce that behavior by going in the opposite direction: instead of applying more force for a higher jump, we can apply more deceleration during the jump if the jump button is released.

if player_state == "jumping" then
    if jump_button_just_released then
        player.velocity.y = player.velocity.y * HOP_MULTIPLIER
        player_state = "falling"
    elseif player.velocity.y >= 0 then
        player_state = "falling"
    end
end

Assuming HOP_MULTIPLIER here is somewhere between 0 and 1, this’ll instantly decelerate the player’s vertical velocity when they release the jump button. If we’re near the top of our jump arc, this effect will be barely noticeable. If we’re toward the bottom of it, however, we’ll slash our jump arc by a good bit. The closer to 0 this multiplier is, the more pronounced the difference between a short hop and a long jump is.

Variable height jump example Look at that fancy looking variable-height jump