In this lesson, you’ll add a jump to the robot.
First, we define how high the jump should be. Thanks to the
export
keyword, we can change this later in the
Inspector.
Just below the previous export
lines, and before the
velocity
line, add this single line:
export var jump_strength := 1400.0
Your file’s head should now look like this:
extends KinematicBody2D
export var speed := 600.0
export var gravity := 4500.0
export var jump_strength := 1400.0
var velocity := Vector2.ZERO
Note: We always group all exported variables at the
top, then internal variables (like velocity
). There is no
particular reason for this. It is just a common convention. Following
conventions makes it easier to read other people’s code and for other
people to read yours.
As soon as the player presses the jump button, we want our robot to leap into the air. But we only want the robot to be able to jump if they are on the ground.
So, the order of instructions in the _physics_process()
function should be:
x
axis of velocity
.gravity
to the y
axis of
velocity
.strength
to the y
axis of velocity
.velocity
to the robot.If we look at the previous code, we can guess where our new code should be:
func _physics_process(delta: float) -> void:
# Get the horizontal direction as a number between -1.0 and 1.0.
var horizontal_direction := Input.get_axis("move_left", "move_right")
# Multiply the direction by speed, and assign to the velocity's x value.
= horizontal_direction * speed
velocity.x # Add the gravity to the velocity's y value.
+= gravity * delta
velocity.y # ---------------------------
# OUR NEW CODE SHOULD BE HERE
# ---------------------------
# Move this kinematic body based on its velocity.
= move_and_slide(velocity, Vector2.UP) velocity
We create a new variable: is_jumping
.
Every frame, we check to see if the player has just pressed the jump button and if the robot is currently on the floor.
If both of these conditions are true, the character can jump that frame.
func _physics_process(delta: float) -> void:
# ...
var is_jumping := is_on_floor() and Input.is_action_just_pressed("jump")
# ...
The is_on_floor()
function found in objects lets us check if the object
is on the floor.
The engine detects when our robot hits an obstacle. Thanks to the “up
direction” Vector2.UP
we passed to
move_and_slide()
, Godot knows this obstacle is the ground
and sets the robot as on_floor
this frame.
Thanks to that, we can check the robot’s status and set the
is_jumping
variable accordingly.
Note: the is_on_floor()
function only
works when the robot collides with the floor. Because we apply
gravity every frame, the robot falls and may collide with the floor
every frame.
You don’t see it, but under the hood, when the character stands on the ground, this happens every frame:
Let’s use our is_jumping
variable now. Between the
is_jumping
variable definition, and the
move_and_slide()
call, we add this:
func _physics_process(delta: float) -> void:
# ...
if is_jumping:
= -jump_strength
velocity.y # ...
If the robot is jumping, we subtract jump_strength
from
velocity.y
.
The vertical velocity will suddenly be a large negative number, moving the robot up.
But as the _physics_process()
function runs, it
continuously adds gravity to velocity.y
, moving the robot
down once more.
Until now, our function looks like so:
func _physics_process(delta: float) -> void:
# Get the horizontal direction as a number between -1.0 and 1.0.
var horizontal_direction := Input.get_axis("move_left", "move_right")
# Multiply the direction by speed, and assign to the velocity's x value.
= horizontal_direction * speed
velocity.x # Add the gravity to the velocity's y value.
+= gravity * delta
velocity.y var is_jumping := is_on_floor() and Input.is_action_just_pressed("jump")
if is_jumping:
= -jump_strength
velocity.y # Move this kinematic body based on its velocity.
= move_and_slide(velocity, Vector2.UP) velocity
If you run the Level scene now, you’ll be able to jump!
Note: the “jump” action is Space or w by default.
This is good, and we’re almost there.
But the robot might feel strange to control. Even if you barely press the jump button, the robot always does a full-height jump.
Let’s add code to interrupt the jump if the player releases the jump button early.
In many games, such as the Mario games, releasing the jump button early cancels the jump and results in a shorter jump height.
We will allow our players to do that. We introduce another variable:
is_jump_cancelled
.
A jump is considered cancelled if and only if:
velocity.y
is
negative: that means the robot is going up. We don’t need to cancel
anything if the robot is already moving down (velocity.y
would be positive).We can write the condition right under the is_jumping
declaration:
func _physics_process(delta: float) -> void:
# ...
var is_jumping := is_on_floor() and Input.is_action_just_pressed("jump")
# We add the following line
var is_jump_cancelled := velocity.y < 0.0 and Input.is_action_just_released("jump")
# ...
Now that we stored the information, we can use it. Let’s add a second
branch to our if
. If the player has cancelled the jump, we
set velocity.y
to 0.0
and let gravity take
over.
func _physics_process(delta: float) -> void:
# ...
if is_jumping:
= -jump_strength
velocity.y # We add the following lines
elif is_jump_cancelled:
= 0.0
velocity.y # ...
Now, if you play the scene, you’ll be able to jump to different heights!
We’ll improve the jump even more in the next lesson by adding a double jump.
Here’s the complete code for the robot script so far.
extends KinematicBody2D
export var speed := 600.0
export var gravity := 4500.0
export var jump_strength := 1400.0
var velocity := Vector2.ZERO
func _physics_process(delta: float) -> void:
# Get the horizontal direction as a number between -1.0 and 1.0.
var horizontal_direction := Input.get_axis("move_left", "move_right")
# Multiply the direction by speed, and assign to the velocity's x value.
= horizontal_direction * speed
velocity.x # Add the gravity to the velocity's y value.
+= gravity * delta
velocity.y
# Verify if "jump" was pressed while character is on floor.
var is_jumping := is_on_floor() and Input.is_action_just_pressed("jump")
# Verify if "jump" was released while character is rising.
var is_jump_cancelled := velocity.y < 0.0 and Input.is_action_just_released("jump")
# If jumping, subtract jump_strength from velocity.y.
# But if player cancelled jump instead, set velocity.y to 0.0.
# Otherwise, leave velocity.y as it is.
if is_jumping:
= -jump_strength
velocity.y elif is_jump_cancelled:
= 0.0
velocity.y
# Move this kinematic body based on its velocity.
= move_and_slide(velocity, Vector2.UP) velocity