LESSON 3 OF 6

Make an obstacle physically block the route

Build collision bodies from rectangles and use the same rectangles to draw the boundaries.

Godot 4.7.2 stable · standard edition · GDScript · 25 minutes estimated practice
0 of 6 lessons completeGuest progress stays in this browser. Account progress is separate.

Continue your working project from the previous lesson. Each download is the completed version of this lesson, for recovery and comparison. Start lesson one with checkpoint 01.

Describe the room geometry once

Continue from lesson two, or use checkpoint 02 as your starting point. Open game.gd and add the following WALLS constant after START. Each Rect2 contains x, y, width and height in the room’s coordinates.

The first four rectangles form the room’s boundary. The last rectangle is a divider: it begins at y=140 and stops at y=420, leaving a route below it. The courier’s radius is 12 pixels, so a usable gap needs room for its whole collision shape.

const WALLS: Array[Rect2] = [
	Rect2(40, 140, 880, 16), Rect2(40, 564, 880, 16),
	Rect2(40, 140, 16, 440), Rect2(904, 140, 16, 440),
	Rect2(450, 140, 36, 280)
]

Give the rectangles real collision

Add this _add_walls function at the end of game.gd, aligned with the other func declarations. It creates one fixed physics body and one matching rectangle collision shape for each entry.

Then put a single _add_walls() call at the beginning of _ready(), before its status.text assignment. _ready runs when this scene enters the tree, so the wall bodies are created once for the run.

  1. Check that _ready() calls _add_walls() once. Do not put the call in _process or _physics_process; those run repeatedly.
  2. Save and run. The bodies should block movement even before the next drawing edit makes them easy to see.
func _add_walls() -> void:
	for rectangle in WALLS:
		var wall := StaticBody2D.new()
		wall.position = rectangle.get_center()
		var collision := CollisionShape2D.new()
		var shape := RectangleShape2D.new()
		shape.size = rectangle.size
		collision.shape = shape
		wall.add_child(collision)
		add_child(wall)

Draw the same geometry

At the end of the existing _draw() function, after its final draw_string call and before the next func declaration, add the loop below. Preserve one tab of indentation for the loop and two for its draw_rect call.

Using WALLS for both drawing and collision keeps the visible obstacle matched to its physical boundary. A drawn rectangle by itself does not stop a CharacterBody2D.

  1. Run the game. Push into the divider from the left, then find the open route beneath it.
  2. Try each outside edge and a diagonal approach to a corner. Check that the courier stays within the room.
  3. Compare your game.gd with checkpoint 03 if the shapes appear but do not block movement, or block movement but are invisible.
	for rectangle in WALLS:
		draw_rect(rectangle, Color("6e826d"))
OBSERVE THE RESULT

Check your work.

  • The courier stops against the divider.
  • The courier can travel through the gap below the divider.
  • The four outside boundaries prevent leaving the room.
  • Visible walls and their collision edges agree.
This is self-reported practice, not a qualification.

If something went wrong.

  • A drawing has no physics body until _add_walls creates one.
  • Each collision rectangle uses rectangle.get_center() as the body position and rectangle.size as its shape size.
  • The new drawing loop belongs inside _draw; _add_walls is a separate function at the outer indentation level.
TAKE THE CONTEXT TO YOUR OWN CHATGPT

Ask about one small step.

I am on the Godot 4.7.2 One Small Delivery walls lesson. WALLS stores Rect2 entries used to draw rectangles and create StaticBody2D/CollisionShape2D pairs. Help diagnose my observed collision result. Ask for the relevant code and exact symptom, then propose one check that distinguishes drawing, shape size, position or function-call problems.

Source notes & checks.

Checked November 14, 2026 with Godot 4.7.2.stable.official.ed1daf0bf: all six checkpoints passed headless parser/import and 53 engine runtime checks, including actual movement and wall collision, interaction distance, single delivery and restart signal/handler behavior. Six packaged ZIP hashes were checked. Headless tests do not establish editor usability, rendered appearance, physical keyboard/mouse behavior, exported builds, mobile support or compatibility with other engine versions.

Original workshop project code and placeholder shapes are provided under the MIT license. Keep LICENSE.txt with redistributed source. Godot is distributed separately under its own license.

Workshop edition 1.0.0. Source and checkpoint downloads are free.