config/engine_config_basics¶
Goal¶
Understand how Mini Arcade builds runtime config from:
settings files
CLI passthrough overrides
example builder defaults
This tutorial is the reference for EngineConfig + SceneConfig wiring.
For full game scaffolding (entities, systems, draw ops), see ../create_game.md.
Why this example matters¶
Most real projects need:
backend selection per environment (
pygamein dev,nativefor parity tests)runtime tuning (
fps,virtual_resolution, profiler, postfx) without code editsone scene implementation that remains backend-agnostic
This example proves that workflow end-to-end.
Source map¶
Settings profile:
examples/settings/config/engine_config_basics.ymlExample builder:
examples/catalog/config/engine_config_basics/main.pyShared runner:
examples/_shared/runner.pyRuntime scene:
examples/catalog/config/engine_config_basics/scenes/scene.py
Runtime flow (actual)¶
CLI resolves example id
config/engine_config_basics.Shared runner imports
examples.catalog.config.engine_config_basics.main.build_example(**kwargs)loads settings with:Settings.for_example("config/engine_config_basics", required=False).Builder merges:
shared example defaults (
examples/settings/settings.yml)example profile (
examples/settings/config/engine_config_basics.yml)CLI passthrough overrides (
--backend,--fps, etc.)
Runner constructs:
backend instance via
backend_factory()EngineConfigviaengine_config_factory(...)SceneConfigfromExampleSpecfields
Scene renders effective runtime values on screen for inspection.
Config mapping table¶
Input key |
Source section |
Final runtime target |
|---|---|---|
|
settings + CLI |
backend implementation ( |
|
settings + CLI |
|
|
settings + CLI |
|
|
settings + CLI |
|
|
settings + CLI |
|
|
settings + CLI |
|
|
settings |
|
|
settings |
|
|
settings + CLI |
backend window settings |
|
settings |
backend renderer settings |
YAML structure for real games¶
This example uses example-scoped YAML, but the same model is used by games in:
games/<game-id>/settings/settings.yml
Recommended game profile shape:
scene:
initial_scene: menu
scene_registry:
discover_packages:
- my_game.scenes
- mini_arcade_core.scenes
engine_config:
fps: 60
virtual_resolution: [960, 540]
enable_profiler: false
postfx:
enabled: false
active: []
backend:
provider: native # or pygame
window:
width: 960
height: 540
title: My Game
resizable: true
renderer:
background_color: [20, 20, 20]
fonts:
- name: default
path: ${assets_root}/fonts/MyFont.ttf
size: 24
audio:
enable: true
sounds:
select: sfx/select.wav
gameplay:
difficulty:
default: normal
How YAML gets into the engine/game¶
Reference flow from current games (deja-bounce, asteroids, space-invaders):
from mini_arcade.modules.backend_loader import BackendLoader
from mini_arcade.modules.settings import Settings
from mini_arcade_core import run_game
settings = Settings.for_game("my-game", required=True)
backend_cfg = settings.backend_defaults(resolve_paths=True)
backend = BackendLoader.load_backend(backend_cfg)
engine_cfg = settings.engine_config_defaults()
scene_cfg = settings.scene_defaults()
gameplay_cfg = settings.gameplay_defaults()
run_game(
engine_config=engine_cfg,
scene_config=scene_cfg,
backend=backend,
gameplay_config=gameplay_cfg,
)
What the framework does with each payload:
backend_cfg: selects and configures backend implementation frombackend.providerengine_cfg: converted toEngineConfig(fps, virtual resolution, postfx, profiler)scene_cfg: converted toSceneConfig, then scene discovery/import runsgameplay_cfg: injected intoGamePlaySettingsand exposed via runtime context
Deep-dive docs¶
Developer internals:
Config system: ../../concepts/configuration.md
Backend selection/contract: ../../concepts/backends.md
Precedence rules¶
Highest to lowest:
CLI passthrough args
Example-specific settings profile
Shared example settings profile
Hardcoded fallback values in
main.py
Run¶
Default:
mini-arcade run --example config/engine_config_basics
Swap backend:
mini-arcade run --example config/engine_config_basics --pass-through --backend pygame
mini-arcade run --example config/engine_config_basics --pass-through --backend native
Override runtime timing/resolution:
mini-arcade run --example config/engine_config_basics --pass-through --fps 72 --virtual-width 960 --virtual-height 540
Enable profiler + postfx:
mini-arcade run --example config/engine_config_basics --pass-through --enable-profiler --postfx-enabled --postfx-active crt,vignette_noise
What to verify on-screen¶
The scene prints these values directly from runtime config/services:
backend class name
fps target
virtual resolution
postfx enabled + active list
profiler enabled flag
real window size + viewport mode + viewport scale
If a CLI override works, those lines change immediately on next launch.
Practical checks¶
Set
--virtual-width 960 --virtual-height 540and confirm line changes.Run once on
pygameand once onnative; backend line must change, scene code must not.Enable
--postfx-enabledand pass--postfx-activelist; scene should display active ids.Resize window and watch viewport telemetry (
mode,scale).
Common mistakes¶
Passing overrides without
--pass-through: args are consumed by the top-level CLI instead of the example runner.Forgetting discovery package: if
discover_packagesmisses your module, scene registration is not found.Assuming window size equals virtual resolution: they are independent (virtual is simulation/render target, window is presentation).
Controls¶
F1: toggle built-in debug overlayESC: exit
Next step¶
Continue with backend_swap.md to validate parity-focused backend checks.
Continue with ../scene/minimal_scene.md for the smallest scene baseline.