05.adding-a-double-jump

Adding a double jump

In this lesson, we’ll add a double jump mechanic to our character.

Sometimes it’s fun to break rules in games, and being able to jump in the air certainly breaks the rules of gravity.

It also gives the player more control. If they misjudge a jump, they can correct the landing by doing a small jump in the air.

Breaking rules is fun, but we also need to think about how we’re going to restrict the player’s jumps.

After all, if the player can jump in the air continually, they’ll easily avoid all the game’s obstacles.

In this lesson, we’ll code a scalable double jump mechanic that you can tweak yourself. If you’d rather give the robot ten air jumps instead of two, then this system will allow for it.

Double jump properties

Previously, we used one jump strength value:

export var jump_strength := 1400.0

If we had two jumps, we could do something like:

export var jump_strength_1 := 1400.0
export var jump_strength_2 := 1000.0

But that isn’t very easy to extend and change. What if we want three jumps?

Instead of having one strength value, we’re going to use an array to store jump strengths.

The multi-jump algorithm

Let’s think a moment about how this will work.

We need:

Each time the player jumps, we will increase the jump_number value. We will use jump_number as an index to the current jump strength in the array.

For example, if our array looks like this:

var jump_strengths := [2000.0, 1000.0, 500.0]
var jump_number := 0

Let’s imagine what happens if the player presses “jump” four times.

The first time the player jumps, we access the first jump strength: jump_strengths[jump_number]. Since jump_number is 0, we get the array’s first value, 2000.0.

We then increment jump_number, which becomes equal to 1.

The second time the player jumps, we use jump_strengths[jump_number] again. Since jump_number is 1, we get the array’s second value, 1000.0. We increment jump_number, which becomes equal to 2.

We keep going until we get past the array’s size. After the third jump, we look at jump_number, which should be equal to jump_strengths.size().

That means there are no allowed jumps left, so we do nothing.

When the robot character touches the ground, we restore all the jumps by setting jump_number back to 0. Next time the player leaves the ground, they can jump three times again.

Please make sure to take your time with the above. Once you feel it makes sense, let’s jump in and write the code!

Allowing double jumps

First, let’s declare our two jumps. We will write this instead of the previous jump_strength property.

Remove this line:

export var jump_strength := 1400.0

And instead, write this line:

export var jump_strengths := [1400.0, 1000.0]

The first jump has a strength of 1400.0 and the second 1000.0.

You’ll get an error in the _physics_process() function that we will fix shortly.

Then, below that, before velocity, write:

var jump_number := 0

The head of our document should now look like this:

extends KinematicBody2D

export var speed := 600.0
export var gravity := 4500.0
export var jump_strengths := [1400.0, 1000.0]

var jump_number := 0
var velocity := Vector2.ZERO

Once again, we write the exported variables first, and the variables we’ll only use inside the class after.

We’re done with our file header. To get the robot double jumping, we’ll make some changes to _physics_process() now.

Every time the player presses the “jump” command:

  1. We verify jump_number is less than the size of the jump_strengths array (that means there are jumps left).
  2. If so:
    1. We use jump_strengths[jump_number] for the strength of the current jump.
    2. We make the robot jump (even if not on the ground).
    3. We increase jump_number by 1 .
  3. When the robot falls back on the ground, jump_number goes back to 0.

Let’s start.

We need to remove the restriction of jumping only when on the floor. Update the is_jumping variable not to use is_on_floor():

func _physics_process(delta: float) -> void:
    # ...
    var is_jumping := Input.is_action_just_pressed("jump")
    # ...

When checking for the is_jumping state, we make sure jump_number is less than the size of the jump_strengths array.

Update the existing if statement like so:

func _physics_process(delta: float) -> void:
    # ...
    if is_jumping and jump_number < jump_strengths.size():
    # ...

Every time the player makes a successful jump, we use jump_number as the array’s index to get the current jump strength. Then we increase jump_number by 1.

func _physics_process(delta: float) -> void:
    # ...
    # If the character is jumping and there are jumps remaining.
    if is_jumping and jump_number < jump_strengths.size():
        # Apply the current jump's strength and increment the jump number.
        velocity.y = -jump_strengths[jump_number]
        jump_number += 1
    # ...

Finally, we reset jump_number when the character is on the floor so it can use its jumps again. We’ll use a second elif for that.

func _physics_process(delta: float) -> void:
    # ...
    elif is_jump_cancelled:
        velocity.y = 0.0
    # While the character is on the floor, restore all jumps.
    elif is_on_floor():
        jump_number = 0
    # ...

Your updated conditions should look like this now.

func _physics_process(delta: float) -> void:
    # ...
    # If the character is jumping and there are jumps remaining.
    if is_jumping and jump_number < jump_strengths.size():
        # Apply the current jump's strength and increment the jump number.
        velocity.y = -jump_strengths[jump_number]
        jump_number += 1
    elif is_jump_cancelled:
        velocity.y = 0.0
    # While the character is on the floor, restore all jumps.
    elif is_on_floor():
        jump_number = 0

    # ...

If you run the scene now, you’ll be able to double jump!

Feel free to use the tile map to draw a stage you can jump around in.

Since jump_strengths is exported, you can add more jumps or change each jump’s strength by editing the array in the Inspector. Have fun changing values!

Practice: Adding the double jump

Open the practice Adding the double jump.

This practice helps you verify you retained the information in this tutorial.

In the next lesson, we’ll test the player’s skills and reactions by adding the first hazard: a disappearing platform.

The code

Here’s the complete code for the robot character script so far.

extends KinematicBody2D

export var speed := 600.0
export var gravity := 4500.0
export var jump_strengths := [1400.0, 1000.0]

var jump_number := 0
var velocity := Vector2.ZERO


func _physics_process(delta: float) -> void:
    var horizontal_direction := Input.get_axis("move_left", "move_right")
    velocity.x = horizontal_direction * speed
    velocity.y += gravity * delta
    var is_jumping := Input.is_action_just_pressed("jump")
    # Verify if "jump" was released while character is rising.
    var is_jump_cancelled := Input.is_action_just_released("jump") and velocity.y < 0.0
    # If the character is jumping and there are jumps remaining.
    if is_jumping and jump_number < jump_strengths.size():
        # Apply the current jump's strength and increment the jump number.
        velocity.y = -jump_strengths[jump_number]
        jump_number += 1
    elif is_jump_cancelled:
        velocity.y = 0.0
    # While the character is on the floor, restore all jumps.
    elif is_on_floor():
        jump_number = 0
    velocity = move_and_slide(velocity, Vector2.UP)