Find your way through a maze. A StaticBody2D blocks the player; an Area2D notices a touch without blocking it.
Loading the game engine. This takes a moment the first time.
StaticBody2D nodes. They never move, and the player cannot pass through them. One exception: the gold platforms in the Platformer build, which stop you from one side only. See One Way Collision below.Area2D, so the player CAN pass through it. An Area2D only notices a touch, it never blocks.■ UI node · ■ 2D node · % unique name · .tscn instanced scene
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 = 250.0
# "_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:
$Sprite2D.flip_h = true
if direction.x > 0.0:
$Sprite2D.flip_h = falseextends Area2D
func _ready() -> void:
# "_ready()" runs ONCE, the moment this node joins the running game.
# Godot calls it for you, just like "_physics_process()", but one time
# instead of every frame. That makes it the place for setup.
#
# "body_entered" is a signal Godot builds into every Area2D. We put the
# name "_on_body_entered" inside ".connect()". That is the function
# Godot runs when something touches this goal.
body_entered.connect(_on_body_entered)
# "body" is whatever touched the goal.
func _on_body_entered(body: Node2D) -> void:
# Both players are in the "Player" group. See the Node tab next to the
# Inspector. Without this check, anything at all could finish the maze.
if body.is_in_group("Player"):
# "queue_free()" erases the goal, so it looks collected.
queue_free()extends CharacterBody2D
## How fast the player runs.
@export var speed: float = 250.0
## How hard the player jumps. Negative is up.
@export var jump_velocity: float = -620.0
## How hard gravity pulls down.
@export var gravity: float = 1800.0
# "_physics_process()" runs about 60 times a second. Godot calls it for you.
func _physics_process(delta: float) -> void:
# Gravity pulls a little harder every tick, but only while you are in the
# air. "delta" turns "per tick" into "per second". See Best Practices.
if not is_on_floor():
velocity.y += gravity * delta
# "just_pressed" fires once on the way down, so holding Space does not
# jump over and over.
if Input.is_action_just_pressed("jump") and is_on_floor():
velocity.y = jump_velocity
# Left and right only. Up and down belong to gravity and the jump.
velocity.x = Input.get_axis("ui_left", "ui_right") * speed
move_and_slide()
# The warrior picture only faces right, so walking left mirrors it and
# walking right puts it back.
if velocity.x < 0.0:
$Sprite2D.flip_h = true
if velocity.x > 0.0:
$Sprite2D.flip_h = false