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.
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.
Let’s think a moment about how this will work.
We need:
jump_strengths
.jump_number
.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!
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:
jump_number
is less than the
size
of the jump_strengths
array (that means
there are jumps left).jump_strengths[jump_number]
for the strength of
the current jump.jump_number
by 1
.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.
= -jump_strengths[jump_number]
velocity.y += 1
jump_number # ...
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:
= 0.0
velocity.y # While the character is on the floor, restore all jumps.
elif is_on_floor():
= 0
jump_number # ...
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.
= -jump_strengths[jump_number]
velocity.y += 1
jump_number elif is_jump_cancelled:
= 0.0
velocity.y # While the character is on the floor, restore all jumps.
elif is_on_floor():
= 0
jump_number
# ...
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!
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.
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")
= horizontal_direction * speed
velocity.x += gravity * delta
velocity.y 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.
= -jump_strengths[jump_number]
velocity.y += 1
jump_number elif is_jump_cancelled:
= 0.0
velocity.y # While the character is on the floor, restore all jumps.
elif is_on_floor():
= 0
jump_number = move_and_slide(velocity, Vector2.UP) velocity