Skip to content

Implement deferred features: in-game options menu + level editor#2

Merged
kennethsinder merged 1 commit into
masterfrom
feat/deferred-features
Jun 14, 2026
Merged

Implement deferred features: in-game options menu + level editor#2
kennethsinder merged 1 commit into
masterfrom
feat/deferred-features

Conversation

@kennethsinder

Copy link
Copy Markdown
Owner

Implements the two features that were deferred during the modernization (and documented in CLAUDE.md as "good next tasks"). Both are reachable from the title screen — O for options, E for the editor.

Options menu — scenes/options.py + ui/widgets.py

  • A small keyboard-driven menu toolkit: Toggle / Slider / Choice / Action rows + a Menu that owns navigation and rendering. Fully unit-tested without any mouse hit-testing.
  • The scene edits the live Settings and persists them on exit.
  • No dead toggles: it only surfaces settings that actually do something — music, volume, fullscreen, decorations, and a developer overlay. Audio and fullscreen apply immediately; the legacy antialiasing/resolution/vsync knobs are launch-only or vestigial and stay out of the UI.
  • Wires developer_mode to a real debug HUD in LevelScene (player pos/vel, lives, coin/key state, entity counts), so that toggle is meaningful.

Level editor — scenes/editor.py over world/editing.py

  • A schematic, mouse-driven editor: number keys pick a tool (platform / coin / block / pool / ledge / door), left-click places, right-click erases, [/] size the brush, arrows pan, S/L save & load lvl_custom.dat (in the user data dir), P test-plays.
  • The display-free EditorModel holds the records, enforces the .dat 25-slot limits, round-trips through world/loader.py, and exposes playability().
  • playability() encodes the structural rules World.from_level_data needs to build a level without crashing or hanging: ≥3 platforms with ≥2 distinct non-spawn x-positions. (I traced an infinite loop in generate_mobs for degenerate levels — its placement while only terminates when a non-spawn platform's x differs from the longest platform's. The editor refuses to test-play a level that would trip it.)
  • Test-play uses a new sandbox LevelScene mode (custom_data= + sandbox=True) that builds from editor data and pops back to the editor on win/death/Esc instead of routing to the title/game-over flow.

Tests (+20, 96 total)

Widget logic, options navigation + on-disk persistence, editor model add/erase/snap/limits/round-trip/validity, the title→options and title→editor transitions, the developer-overlay render path, and the full editor→play path running headless (which also exercises the generate_mobs hang guard).

Verification

uv run pytest (96 pass) · ruff check · ruff format --check · mypy src · headless smoke run — all green locally.

🤖 Generated with Claude Code

Implements the two features deferred during the modernization.

Options menu (scenes/options.py + ui/widgets.py): a small keyboard-driven
menu toolkit (Toggle/Slider/Choice/Action + a Menu that handles navigation
and rendering) and a scene that edits the live Settings and persists them on
exit. It only surfaces settings that have a real effect — music, volume,
fullscreen, decorations, and a developer overlay — so there are no dead
toggles; audio and fullscreen apply immediately. A small developer HUD
(player pos/vel, lives, counts) is gated on the developer-mode setting, which
makes that toggle meaningful.

Level editor (scenes/editor.py over world/editing.py): a schematic,
mouse-driven editor. The display-free EditorModel holds the level records,
enforces the .dat slot limits, round-trips through world/loader.py, and
exposes playability(), which encodes the structural rules World.from_level_data
needs to build a level without crashing or hanging — most importantly that
generate_mobs' placement loop can terminate (>=3 platforms with >=2 distinct
non-spawn x). Levels save to lvl_custom.dat in the user data dir and can be
test-played in place via a new sandbox LevelScene mode that pops back to the
editor instead of going to the title/game-over flow.

Both are reachable from the title screen (O / E). Adds 20 tests (widgets,
options persistence, editor model + round-trip + the full editor->play path).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@kennethsinder kennethsinder merged commit 814c765 into master Jun 14, 2026
9 checks passed
@kennethsinder kennethsinder deleted the feat/deferred-features branch June 14, 2026 18:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant