Now that we have the level and the robot scenes, we can start coding the character’s movement.
In this lesson, we will:
speed
and gravity
values
that we can change in the editor without touching the code.Now we have a script attached, we can start moving our robot. We want two values to affect the robot’s movement.
speed
variable. This will decide how fast our robot
moves when we press left or right.gravity
variable. This will decide how fast our robot
falls.We use the export
keyword when defining these variables
to edit their values in the Inspector.
As with the other moving scenes you’ve created in this course, we
have a velocity
vector.
export var speed := 600.0
export var gravity := 4500.0
var velocity := Vector2.ZERO
We will use these values in the _physics_process()
function. We always use _physics_process()
when we need to
detect collisions with other physics objects in the level (floor, walls,
platforms, and enemies).
For this chapter, the entire function will be a few lines, but we will go into detail to make sure everything is clear before we move on to jumping.
The export
keyword allows us to change properties in the
Inspector.
Writing export
before any var
will show the
value in the editor, where you can modify it without touching the
code.
This has two benefits:
We’re going to handle each axis of the robot’s velocity separately in
the _physics_process()
function:
x
axis).y
axis).Let’s implement each!
The horizontal axis (the x
axis) of the
velocity
will use player controls and the
speed
variable.
To obtain the strength of the left and right inputs, we use the
Input.get_axis()
function.
Previously, you’ve used the Input.get_vector()
function
to get a vector that represents the player’s input in all directions.
Input.get_axis()
is similar, but it only deals with one
axis.
func _physics_process(delta: float) -> void:
var horizontal_direction := Input.get_axis("move_left", "move_right")
= horizontal_direction * speed velocity.x
Instead of taking two axes into account, the
Input.get_axis()
function looks at one.
It takes two actions and returns a value between -1.0
and 1.0
based on the strength of those actions.
In our case, if the player is holding "move_right"
on an
analog joystick, the value will be between 0
and
1
.
If the player holds "move_left"
, the value will be
between 0
and -1
.
That’s specific to analog joysticks, as you control how far you push them.
There are no intermediate values on a keyboard: the
Input.get_axis()
function will return exactly
-1
, 0
, or 1
depending on the keys
the player presses.
The vertical axis (the y
axis) of the
velocity
uses the gravity
variable.
func _physics_process(delta: float) -> void:
# ...
+= gravity * delta velocity.y
We add gravity
to the velocity
’s
y
direction because we want it to always move the robot
toward the ground. You’ll see why this is important when coding the
jump.
In our script, the gravity
value represents an
acceleration while the velocity
is a
speed.
An acceleration is a change in speed over time. To convert
the gravity
value into a change in velocity since the
previous frame, we need to multiply it by the time elapsed since the
last frame.
That is why we multiply the gravity
by
delta
.
We’ve calculated the velocity
’s x
and
y
axes. All that’s left is applying this velocity to the
robot. Like in previous series, we use
move_and_slide()
.
func _physics_process(delta: float) -> void:
# ...
= move_and_slide(velocity, Vector2.UP) velocity
With this, your _physics_process()
function is complete.
We have all we need to move the robot and have it fall. Press
F6 to run the scene and move using left and right. Be proud
of your work!
Let’s look again at move_and_slide()
.
func _physics_process(delta: float) -> void:
# ...
= move_and_slide(velocity, Vector2.UP) velocity
Do you notice something different here?
We assign the return value to the velocity
variable, and
we have a second argument compared to the previous series.
The move_and_slide()
function does many things to your
. It moves it, checks for collisions,
tries to slide against the ground or walls, and calculates a leftover
velocity
after all collisions.
Sometimes we want to store that leftover velocity
, and
sometimes we do not. That is why we did not assign the value to our
velocity
variable in the previous series.
Here, the returned velocity
resets the y
value to 0.0
when the character is on the ground.
Without that, because we add the gravity
every frame,
the velocity.y
value would eventually get so big that the
character would fall through the floor.
Also, we called the move_and_slide()
function with a
second argument: Vector2.UP
.
When you point “up” in real life, you point to the sky. This is because what we think of as “up” is relative to the gravity we feel, which pulls us toward the floor.
In games, gravity can be in any direction, and without telling Godot which direction is “up,” the engine will not know if the robot is on the ground or a wall.
To implement jumping in the next lesson, we need Godot to know the “up” direction.
Note: The extra argument, Vector2.UP
,
is shorthand for Vector2(0, -1)
. To make it easier to
remember, values we often use like that are provided in Godot as
ready-to-use variables. There’s also Vector2.DOWN
,
Vector2.RIGHT
, and Vector2.LEFT
.
Note 2: As you write a call to a function in the code editor, if you pause for a second, you’ll see hints from Godot giving the name of this parameter. These editor hints can often help you.
In the next lesson, we will make the character jump.
So far, your script should contain the following code.
extends KinematicBody2D
export var speed := 600.0
export var gravity := 4500.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
= move_and_slide(velocity, Vector2.UP) velocity