Skip to content

Project Settings & Window Stretch

What you'll learn

  • Why a UI-only idle game configures the renderer, window size, and stretch mode the way it does.
  • Where in the Godot editor each of those settings actually lives.
  • The difference between canvas_items stretch and the alternatives, and what Aspect = keep does to a window when you resize it.
  • A vocabulary of small terms (Project Settings dialog, Display section, viewport) that every later chapter assumes.

How it applies

Stretch mode is the first decision that shapes how every later player will experience Blood Knight Grove — on a 1366×768 laptop, a 4K monitor, or a streamer's recompressed Twitch capture. The settings below are not abstract: they decide whether your idle game looks like a finished product or a developer prototype across the hardware spread players actually use.

  • Hardware spread. Players run idle games on everything from 1366×768 work laptops to 32" 4K monitors to ultra-wide 21:9 displays. The stretch settings are what make a single base-resolution layout look right across all of them without hand-tuning per device. Skip the choice and the game looks broken on any monitor that isn't the developer's.
  • The "left running in the background" use case. Incremental games are unusually likely to be parked on a second monitor at a non-standard window size while the player works. Squashed UI from Aspect = ignore is jarring in a tab the player glances at all day; letterboxed UI from Aspect = keep is calm and predictable. The game's vibe is partly decided by the stretch dropdown.
  • QA test-matrix size. Every UI bug found at the base resolution stays fixed at all resolutions when Mode = canvas_items is set, because the engine handles the scaling uniformly. Without it, every UI bug has to be retested at every common resolution — a multiplicative explosion of test cases that crushes a small QA team.
  • Streaming & screenshots. Streamers commonly capture in 1080p or 1440p, sometimes with a webcam overlay forcing an oddly-cropped game window. Sharp text under canvas_items survives recompression on Twitch/YouTube; soft viewport-mode text becomes mush. Idle games live or die on readable numbers in screenshots.
  • Accessibility headroom. Players who run Windows display scaling at 125% or 150% (vision-impaired users, very high-DPI laptops) end up with a smaller game window inside the OS-scaled desktop. canvas_items re-rasterizes fonts at the smaller size cleanly; the alternative produces blurry or undersized text that fails accessibility heuristics.
  • project.godot is checked into source control. Every teammate (or future-you) that clones the repo gets these settings automatically. Setting them once at the start prevents the "works on my machine" class of UI bug where a developer forgets to mirror a project-level setting on a fresh clone.

Concepts

The Project Settings dialog

Every Godot project has a single configuration file at its root: project.godot. Most fields in that file are not edited by hand — they are written by the Project Settings dialog, opened from the menu bar with Project → Project Settings…. The dialog is a tree of grouped settings on the left, an inspector pane on the right, and a search box at the top. Save and the file on disk updates.

For an idle game, three groups matter immediately:

  • Application → Config — display name, organization, version. Cosmetic, but worth setting once so your title bar reads "Blood Knight Grove" instead of "godot-idle-learning".
  • Display → Window → Size — the base resolution you design against. Every Control node anchor, every UI margin, is calibrated against these numbers. Pick once at the start, do not change later without rework.
  • Display → Window → Stretch — how the engine resamples that base resolution onto whatever real window the player drags. This is the setting that decides whether your menus go blurry, get letterboxed, or stay crisp at 4K.

Example

You set base resolution to 1280×720 in M1.1 and never revisit it. In M2.1 you anchor a ClickButton 100 pixels from the bottom-center. The button stays 100 pixels from the bottom-center even when the player resizes the window to 2560×1440, because Godot scales the entire 1280×720 canvas as one piece. If you had instead set base resolution to 1920×1080 halfway through M5, every "100 pixels from the bottom-center" anchor coded against the original 1280×720 would sit in a different visual position relative to the new canvas, and the playtest QA pass at the end of M5 would have to re-verify every screen.

Example

You search the Project Settings tree for stretch instead of clicking through Display → Window. The search box at the top of the dialog filters the entire setting tree in real time and is almost always faster than tree-walking — especially in 4.6 where there are over 400 settings exposed.

Renderer choice — Forward Plus

When you create a new Godot 4.6 project, the Project Manager asks you to pick a renderer. The default is Forward+, the high-end desktop renderer with full Vulkan features. The other choices, Mobile and Compatibility (GLES3), trade visual fidelity for hardware reach.

For a 2D UI-only game, none of the renderer differences are visible to the player — there are no shadows, no global illumination, no PBR materials in the scene. Forward+ is fine and does no harm. We are not going to spend time tuning it.

Example

A 3D dungeon-crawler with PBR materials and dynamic lighting would care: Forward+ runs the full clustered-forward path that handles many lights at once, Mobile uses a simpler renderer, Compatibility uses GLES3 and drops some material features. Blood Knight Grove draws nothing more complex than Label nodes and TextureButton nodes, so the renderer choice is invisible. Pick Forward+ and forget about it.

Stretch mode — canvas_items and Aspect = keep

The two stretch settings you will set are:

Display → Window → Stretch → Mode    = canvas_items
Display → Window → Stretch → Aspect  = keep

These are not the defaults. The defaults are Mode = disabled and Aspect = ignore, which produce a window that re-lays-out wildly when resized — fonts that do not scale, anchors that flap. canvas_items and keep produce the behavior every idle/incremental game player expects: the entire UI scales up and down as one piece, and when the window aspect ratio drifts away from the base aspect ratio, you get black bars on the long edge instead of squashing.

The mental model:

  • Mode = disabled — engine renders to the actual window pixel dimensions. Anchors and margins compute against the real window. Resizing the window re-flows the layout in real time. Useful for productivity-app-style UIs; wrong for games.
  • Mode = viewport — engine renders to a fixed-size off-screen viewport, then blits the whole image to the window like a sprite. Pixel-perfect but you lose subpixel anti-aliasing on text and 2D shapes; everything looks soft.
  • Mode = canvas_items — engine renders 2D nodes against the base resolution, then scales the result before raster. Text re-rasterizes at the new size so fonts stay sharp. This is the one you want for an idle game.

And the aspect setting:

  • Aspect = ignore — when the window aspect drifts, the image stretches to fit. Things look squashed.
  • Aspect = keepletterboxes (or pillarboxes) instead of stretching. The base aspect ratio is locked.
  • Aspect = keep_height / keep_width — locks one axis, lets the other expand and reveal more of the world. Useful for sidescrollers or top-downs that have art beyond the base viewport. Wrong for a UI-only game where anchors assume the base width or height is the truth.

Example

Same settings, different windows. Base resolution is 1280×720, Mode = canvas_items, Aspect = keep.

  • Player resizes to 1920×1080 (16:9, same aspect): UI scales 1.5× cleanly, no bars, fonts re-rasterized sharp at the new size.
  • Player resizes to 1920×1200 (8:5, taller aspect): UI scales to fit width, with thin black letterbox bars top and bottom. Fonts still sharp.
  • Player resizes to 2560×720 (ultra-wide): UI scales to fit height, with thick black pillarbox bars left and right.
  • Player undocks a laptop and the window shrinks to 1024×576: UI scales 0.8× down, fonts re-rasterized at the smaller size, no bars.

In every case the layout the developer reasoned about (1280×720) is what is on screen, just scaled. There is no point at which the developer has to think "what if the window is 1920×1200" — the engine handles it.

Example

Same scenario, the wrong settings. Base resolution 1280×720, Mode = disabled, Aspect = ignore (the defaults).

  • Player resizes to 1920×1080: anchors compute against 1920×1080 directly. A "100 px from bottom-center" button is now 100/1080 ≈ 9% from the bottom instead of 100/720 ≈ 14%. The layout drifted.
  • Player resizes to 1920×1200: same drift, plus fonts at fixed pixel size now look smaller relative to the larger window.
  • Player resizes to 640×480: fonts that were readable at 720p are now overlapping the buttons because nothing scaled.

This is what the chapter is steering you away from.

Anatomy of an editor menu path

Throughout this book and in any Claude session you open alongside it, you will see strings like:

Project → Project Settings → Application → Run → Main Scene

The arrow means click that menu, then click the next thing inside it. The first segment is always a top-level menu (Project, Scene, Debug) or a section in the Project Settings tree. The last segment is the actual setting name as it appears in the dialog. Searching the Project Settings dialog for the last segment usually finds it faster than walking the tree by hand — there is a search box at the top.

Example

The instruction Project → Project Settings → Display → Window → Stretch → Mode means:

  1. Click Project in the top menu bar.
  2. Click Project Settings… in the dropdown.
  3. In the dialog that opens, expand Display in the left tree.
  4. Click Window underneath it.
  5. In the right pane, find the Stretch sub-heading.
  6. Set the Mode field.

Six clicks for one setting. Or: open the dialog, type stretch mode in the search box, and the field shows up directly.

Walkthrough

You will perform these in your own Godot editor, with the godot-idle-learning project open.

  1. From the top menu bar, open Project → Project Settings…. The dialog is modal: nothing else is reachable until you close it.
  2. In the left tree, expand Application → click Config. Set the Name field to whatever your project should be called in window titles (suggested: Blood Knight Grove). Tab out of the field; the change is staged but not yet written.
  3. In the same dialog, expand Display → click Window. The right pane shows a flat list of properties.
  4. Under the Size sub-heading, set:
  5. Viewport Width = 1280
  6. Viewport Height = 720 These are your base-resolution numbers. Every UI layout decision later is against this canvas.
  7. Under the Stretch sub-heading on the same page, set:
  8. Mode = canvas_items (dropdown)
  9. Aspect = keep (dropdown)
  10. Click Close to dismiss the dialog. The settings are persisted to project.godot automatically.
  11. Drag the editor window edge to resize. Wait — the editor window is not your game window; nothing visible has changed yet because the game is not running. To verify the settings, you would need to launch the game (F5) — but with no main scene set, F5 will refuse to run. Setting the main scene is the next chapter. For now, trust that the values are saved.

Optional sanity check. Close the dialog, then re-open it (Project → Project Settings…) and navigate back to Display → Window. The values should be exactly what you set. If they reverted, the dialog rejected them — usually a typo in the field. Re-enter and re-close.

Self-check quiz

Q1 — Which stretch Mode keeps text sharp at non-native window sizes?

A. disabled B. viewport C. canvas_items D. 2d (this is the legacy Godot 3 name; the dropdown does not show it in 4.6)

Reveal answer

C — canvas_items. The engine re-rasterizes 2D nodes at the scaled output size, so font glyphs are drawn at the new pixel resolution. viewport would render once at the base size and then blit-scale the image, softening text. disabled does not scale at all — anchors and font sizes both re-compute against the real window, which is a different problem (your layout flaps around). D is a distractor: 2d was the Godot 3 name for what is now canvas_items; it is not an option in the Godot 4.6 dropdown.

Q2 — You set Aspect = keep, base resolution 1280×720. The player drags the window to 1920×1080. What happens visually?

A. The UI stretches to exactly fill the 1920×1080 area. B. The UI scales up uniformly to fit, with the entire 1920×1080 area covered (1.5× scale, no bars). C. The UI scales up uniformly with letterbox bars on top/bottom. D. The UI stays at 1280×720 in the top-left and the rest of the window is blank.

Reveal answer

B — uniform 1.5× scale, no bars. 1280:720 simplifies to 16:9; 1920:1080 is also 16:9. The aspect ratios match exactly, so Aspect = keep finds no aspect drift to compensate for, and the image scales 1.5× cleanly. Letterboxing (C) only kicks in when the window aspect differs from the base aspect — try resizing to 1920×1200 instead and you will see the bars.

Q3 — Which menu path opens the renderer choice for an existing project?

A. Project → Project Settings → Rendering → Renderer B. Project Manager → Edit → Renderer C. There is no in-editor toggle — the renderer is fixed at project creation and only changeable by editing project.godot by hand. D. Editor → Editor Settings → Display → Renderer

Reveal answer

A — Project → Project Settings → Rendering → Renderer (under Rendering Method in 4.6). The setting can be changed any time, though switching renderers may invalidate shader caches and reset some material defaults; for this project the choice does not matter visually. B is a distractor: the Project Manager only sets the default at creation. C is wrong — there is an in-editor toggle. D confuses Editor Settings (which configure the editor itself, like font size) with Project Settings (which configure your game).

Integration question

Q4 — open

You set base resolution 1280×720 and Aspect = keep. In the next chapter, you will configure a folder layout for scenes, scripts, and resources. Why does the folder layout decision belong in the same module (M1) as the stretch decision, rather than later when you have actual UI to organize?

Reveal expected answer

Both are decisions that calibrate every later module against fixed coordinates. A stretch setting determines the meaning of every anchor value you will type from M1.4 onward; a folder layout determines the meaning of every res:// path you will type from M2 onward. Picking either of them in the wrong place means rewriting the chapters that depended on it. M1 is "lock the coordinate systems" — once locked, M2+ does not have to revisit them.

Glossary

Glossary

project.godot
The text-format INI-style file at the root of every Godot project. Stores all editor-configurable settings; checked into source control so the project re-opens identically on every clone.
Project Settings dialog
The modal editor window opened with Project → Project Settings…. The canonical surface for editing project.godot. Tree of categories on the left, inspector on the right, search box at the top.
base resolution
The width × height the game's UI is designed against (this project: 1280×720). Anchors and margins are calibrated to these numbers; the stretch mode scales this canvas to whatever real window the player drags.
renderer
The graphics back-end Godot uses to draw the scene. Decided at project creation, changeable later under Project Settings → Rendering. Choices: Forward+, Mobile, Compatibility (GLES3).
Forward+
Godot 4.6's high-end desktop renderer. Vulkan-based, clustered-forward shading, supports all engine visual features. Overkill for 2D UI games but harmless.
stretch mode
How the engine maps the base resolution onto the actual window. disabled = render to real pixels; viewport = render once to a buffer then blit; canvas_items = render 2D nodes against base then scale (sharp text). For UI games: canvas_items.
stretch aspect
How the engine handles aspect-ratio drift between the base and the actual window. ignore = stretch; keep = letterbox; keep_height/keep_width = expand one axis to reveal more world. For UI games: keep.
letterbox / pillarbox
Black bars added when the window aspect differs from the base. Letterbox = top + bottom (window is taller). Pillarbox = left + right (window is wider). Preserves aspect without distortion.
anchor
A Control node property defining its position relative to the parent rect, expressed as 0–1 along each edge. Anchors compute against the base resolution when canvas_items stretch is active.
viewport (render target)
An off-screen buffer the engine can render into. Distinct from the player's window. In viewport stretch mode the whole game draws into one of these at the base size, then blits it to the window.
### Ask Claude (side-channel) Try one of these in a Claude Code session if a piece did not land: - `Re-explain canvas_items vs viewport stretch using an analogy from a different domain — not games.` - `What changes in project.godot when I set Aspect = keep? Show me the diff.` - `Quiz me on stretch modes again with different distractors than the textbook used.` - `Open the Godot 4.6 class reference for ProjectSettings (https://docs.godotengine.org/en/stable/classes/class_projectsettings.html) and find the method that reads a setting value at runtime. What's the difference from getting the value via the dialog?`