03.coding-the-robot-base-movement

Coding the robot’s base movement

Now that we have the level and the robot scenes, we can start coding the character’s movement.

In this lesson, we will:

  1. Learn to make speed and gravity values that we can change in the editor without touching the code.
  2. Make keyboard inputs move our robot.
  3. Make gravity affect our robot.

Moving the Robot

Now we have a script attached, we can start moving our robot. We want two values to affect the robot’s movement.

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

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:

How we’ll handle axes

We’re going to handle each axis of the robot’s velocity separately in the _physics_process() function:

Let’s implement each!

Taking input from the player

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")
    velocity.x = horizontal_direction * speed

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.

Gravity

The vertical axis (the y axis) of the velocity uses the gravity variable.

func _physics_process(delta: float) -> void:
    # ...
    velocity.y += gravity * delta

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.

Why do we multiply the gravity by delta?

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.

Moving the robot

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:
    # ...
    velocity = move_and_slide(velocity, Vector2.UP)

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!

Changes in how we use move_and_slide()

Let’s look again at move_and_slide().

func _physics_process(delta: float) -> void:
    # ...
    velocity = move_and_slide(velocity, Vector2.UP)

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’s return value

The move_and_slide() function does many things to your KinematicBody2D. 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.

Which way is up?

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.

The code

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")
    velocity.x = horizontal_direction * speed
    velocity.y += gravity * delta

    velocity = move_and_slide(velocity, Vector2.UP)