doc 4 of 9

Stage 02 — Fences and camera: the field has edges

You will build: world boundaries and rocks the farmer collides with, and a camera that follows without ever showing the void beyond the field. You'll learn: collision shapes & layers · Camera2D Warm-up — from memory, before opening the project:

  1. Why does movement code live in _physics_process and not _process?
  2. Why is diagonal movement not faster than straight, given your stage-01 code?
  3. Which project setting keeps pixels square when the window scales — and which keeps them crisp?

Why this exists#

Physics bodies only interact when the engine knows what they are and what they look for. Layers say what a body is; masks say what it scans for — a deliberate pair, not decoration (Physics introduction). And a camera glued to the player shows the void past the field edge; Camera2D limits clamp the view to the world (Camera2D).

Build it#

A — Name your collision layers#

Project Settings → Layer Names → 2D Physics: layer 1 → world, layer 2 → player. Named layers turn checkbox grids into sentences you can read in six months.

B — The world scene grows#

Restructure main.tscn toward the architecture's tree:

Main (Node2D)
└── World (Node2D)
    ├── Bounds (StaticBody2D)      ← 4 CollisionShape2D rects framing the field
    ├── Rocks (StaticBody2D)       ← a few rect/circle shapes inside the field
    └── Player (instance)
  • StaticBody2D is the immovable kind — the docs' four body types are worth 60 seconds now.
  • Bounds: four RectangleShape2Ds just outside a field of, say, 40×22 tiles (1280×704 px). Rocks: 2–3 shapes anywhere inside.
  • Layers: Bounds and Rocks are layer world, mask nothing (walls don't look for anyone). Player is layer player, mask world (the mover does the looking).

Predict before you run: with Player's mask set to world, what happens if you uncheck Player's own layer entirely? Walk into a rock and find out — then explain why nothing changed for movement.

C — Camera with limits#

Add a Camera2D as a child of Player (it inherits position — that's the whole "follow" implementation, zero code). In the Inspector:

  • limit_left/top = 0, limit_right = 1280, limit_bottom = 704 (match your field)
  • position_smoothing/enabled = on, speed ≈ 8 — then walk to a corner and watch the camera stop while the farmer keeps going.

D — Commit#

git add . && git commit -m "stage 02: world bounds, rocks, camera limits"

Checkpoint — definition of done#

  • Farmer cannot leave the field on any side
  • Walking diagonally into a wall slides along it rather than sticking (that's move_and_slide earning its name — watch it happen)
  • Camera follows, smooths, and never shows past the field edge in any corner
  • Zero warnings; committed
  • You can explain: what would break if Player's mask didn't include world?

Before stage 03: walk the field once more with Debug → Visible Collision Shapes on and narrate what every shape is for. If any shape surprises you, that's the one to understand before moving on.

Stretch (no instructions)#

A pond: an obstacle with a non-rectangular collision shape the farmer walks around.

If you get stuck#

  • Farmer walks through rocks → open both nodes' Collision sections side by side; whose layer and whose mask overlap? Say the sentence out loud: "player looks for world."
  • Camera shows beyond the edge → limits are in pixels of world space; is your field really the size you think? Run with Debug → Visible Collision Shapes on.
  • Camera jitters → smoothing fights physics interpolation occasionally; try toggling position_smoothing to isolate which layer of motion is jittering before changing anything.