Menu Scenes Internals¶
Purpose¶
Explain how BaseMenuScene works internally, what extension points it exposes,
and how to apply it for main menus and pause overlays.
Core implementation¶
Main file:
packages/mini-arcade-core/src/mini_arcade_core/ui/menu.py
Key types:
MenuItem: menu entry id, static label,command_factory, optionallabel_fnMenuStyle: style/layout options (background, panel, button style, hint, text colors)Menu: render + selection state + layout calculationsBaseMenuScene: scene base class that wires menu systems
BaseMenuScene contract¶
Implement in your scene subclass:
menu_title: title text shown at top (Nonehides title)menu_style(): returnsMenuStylefor look and layoutmenu_items(): returns menu entries and command factories
Optional:
quit_command(): command used whenESCis pressed in menu (default isQuitCommand)
Per-frame system pipeline¶
BaseMenuScene.on_enter() registers these systems in order:
MenuInputSystemMenuNavigationSystemMenuActionSystemMenuRenderSystem
Runtime flow:
input keys become
MenuIntentselection index updates (with cooldown)
selected action enqueues command
menu is rendered as UI draw op
Command model in menus¶
MenuItem.command_factory returns a command instance each selection.
Typical commands:
ChangeSceneCommand(...)for scene transitionsRemoveSceneCommand(...)for dismissing pause overlaysQuitCommand()for full exitcustom commands mutating gameplay settings (difficulty, toggles, etc.)
Dynamic labels¶
label_fn(ctx) is evaluated each tick to resolve display label. This supports
menu text driven by runtime state:
difficulty level
audio on/off state
control profile name
backend/debug options
Pattern:
command mutates runtime state
next frame,
label_fnreads updated statemenu label updates without scene restart
Main menu vs pause overlay¶
Main menu pattern:
usually opaque standalone scene
sets
background_color,panel_color, and button stylesESCoften maps toQuitCommand
Pause overlay pattern:
pushed with overlay
ScenePolicy(as_overlay=True)menu style usually uses
overlay_colordimmingquit_command()typically resumes gameplay, not exit
Policy details for pause overlays:
docs/source/concepts/overlay_policies.md
See real game implementations:
games/deja-bounce/src/deja_bounce/scenes/menu.pygames/deja-bounce/src/deja_bounce/scenes/pause.pygames/asteroids/src/asteroids/scenes/menu.pygames/asteroids/src/asteroids/scenes/pause.pygames/space-invaders/src/space_invaders/scenes/menu.pygames/space-invaders/src/space_invaders/scenes/pause.py
Common mistakes¶
forgetting scene discovery package: menu scene never registers
returning a command class that needs args without wrapping it in a factory
mutating menu labels manually instead of using
label_fnassuming pause overlay should use default
quit_command(which exits game)
Related tutorial¶
docs/source/tutorials/scene/menu_scene_base.md