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.0Your 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.ZERONote: 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.
velocity.x = horizontal_direction * speed
# Add the gravity to the velocity's y value.
velocity.y += gravity * delta
# ---------------------------
# OUR NEW CODE SHOULD BE HERE
# ---------------------------
# Move this kinematic body based on its velocity.
velocity = move_and_slide(velocity, Vector2.UP)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:
velocity.y = -jump_strength
# ...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.
velocity.x = horizontal_direction * speed
# Add the gravity to the velocity's y value.
velocity.y += gravity * delta
var is_jumping := is_on_floor() and Input.is_action_just_pressed("jump")
if is_jumping:
velocity.y = -jump_strength
# Move this kinematic body based on its velocity.
velocity = move_and_slide(velocity, Vector2.UP)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:
velocity.y = -jump_strength
# We add the following lines
elif is_jump_cancelled:
velocity.y = 0.0
# ...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.
velocity.x = horizontal_direction * speed
# Add the gravity to the velocity's y value.
velocity.y += gravity * delta
# 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:
velocity.y = -jump_strength
elif is_jump_cancelled:
velocity.y = 0.0
# Move this kinematic body based on its velocity.
velocity = move_and_slide(velocity, Vector2.UP)