Lesson 01

Top-Down Movement

Walk around using arrow keys. The starting lesson: one player, four directions, and the code that reads the keyboard.

Loading the game engine. This takes a moment the first time.

Top-down only

This is the starting lesson. All it does is let you walk around, and everything that makes that happen is in this one file.

New code in this lesson

None of the earlier lessons use these. Each one shows the line where it appears here.

extends

The first line of a script. It says which kind of node the script goes on, so the script can do everything that node already does.

player.gd
extends CharacterBody2D

var

Makes a variable: a name that holds a value you can change later.

player.gd
@export var speed: float = 200.0

: float

After a variable name, says what kind of value it holds: float for a decimal, int for a whole number, bool for true or false.

player.gd
@export var speed: float = 200.0

@export

Puts a variable in the Inspector, so you can change it there without opening the script.

player.gd
@export var speed: float = 200.0

@onready

Waits until the scene is built, then grabs a node once and keeps it in the variable.

player.gd
@onready var sprite: Sprite2D = $Sprite2D

$Name

Grabs the node with that name sitting directly under this one.

player.gd
@onready var sprite: Sprite2D = $Sprite2D

func

Makes a function: a set of steps with a name. -> void means it hands nothing back when it is done.

player.gd
func _physics_process(_delta: float) -> void:

_physics_process(delta)

Godot runs this about 60 times a second. Movement and physics go in here.

player.gd
func _physics_process(_delta: float) -> void:

Vector2

Two numbers, x and y. It can be a spot on the screen or an arrow pointing some way.

player.gd
var direction: Vector2 = Input.get_vector("ui_left", "ui_right", "ui_up", "ui_down")

Input.get_vector()

Reads four keys at once as one Vector2 arrow. Its length is never more than 1, so going diagonally is not faster.

player.gd
var direction: Vector2 = Input.get_vector("ui_left", "ui_right", "ui_up", "ui_down")

velocity

Built into CharacterBody2D: how fast the body moves and which way, in pixels per second.

player.gd
velocity = direction * speed

move_and_slide()

Moves the body by its velocity, and slides it along walls instead of stopping dead.

player.gd
move_and_slide()

if

Runs the lines indented under it only when the condition is true.

player.gd
if direction.x < 0.0:

.x and .y

The left-right number and the up-down number inside a Vector2. Down is positive y in Godot.

player.gd
if direction.x < 0.0:

flip_h

Mirrors a sprite left to right, so it faces the other way.

player.gd
sprite.flip_h = true

The scenes

■ UI node · ■ 2D node · % unique name · .tscn instanced scene

game.tscn
  • Game Node2D
  • Player CharacterBody2D player.tscn
  • Borders Node2D
  • Top StaticBody2D hidden block.tscn
  • Bottom StaticBody2D hidden block.tscn
  • Left StaticBody2D hidden block.tscn
  • Right StaticBody2D hidden block.tscn
player.tscn
  • Player CharacterBody2D player.gd
  • Sprite2D
  • CollisionShape2D
block.tscn
  • Block StaticBody2D
  • Polygon2D
  • CollisionPolygon2D

FileSystem

  • game.tscn
  • player.tscn
  • player.gd
  • block.tscn

The code

extends CharacterBody2D

## How fast the player moves. "@export" puts "speed" at the top of the
## Inspector panel, so you can change it there instead of in this file.
@export var speed: float = 200.0

# Grab the picture once, here at the top, and use the name "sprite" below.
# Every script in the course reaches for a node this way. Spell the node name
# wrong and the game says so the moment it starts, instead of much later.
@onready var sprite: Sprite2D = $Sprite2D

# "_physics_process()" runs about 60 times a second. Godot calls it for you.
func _physics_process(_delta: float) -> void:
	# "Input.get_vector(...)" checks all four keys at once and turns them
	# into one arrow pointing where you want to go. The names in quotes are
	# Godot's built-in names for the arrow keys.
	var direction: Vector2 = Input.get_vector("ui_left", "ui_right", "ui_up", "ui_down")
	# "direction" is only WHICH WAY (its length is always 1).
	# "direction * speed" stretches it, so "velocity" is also HOW FAST.
	velocity = direction * speed
	# Nothing moves until "move_and_slide()" runs.
	# "Slide" means we slide along walls instead of sticking to them.
	move_and_slide()

	# The warrior picture only faces right, so walking left mirrors it and
	# walking right puts it back. Neither "if" runs when you stand still,
	# which is what keeps the warrior facing the way you last walked.
	if direction.x < 0.0:
		sprite.flip_h = true
	if direction.x > 0.0:
		sprite.flip_h = false