Refine start menu difficulty and preview workflow

This commit is contained in:
2026-05-08 18:26:55 +02:00
parent f1770b218c
commit d32d2cd79c
12 changed files with 401 additions and 14 deletions
+128
View File
@@ -0,0 +1,128 @@
#!/usr/bin/env python3
import argparse
import os
import random
import sys
import time
from pathlib import Path
PROJECT_ROOT = Path(__file__).resolve().parents[1]
if str(PROJECT_ROOT) not in sys.path:
sys.path.insert(0, str(PROJECT_ROOT))
def parse_args():
parser = argparse.ArgumentParser(description="Render a real Mice menu screen to a PNG preview")
parser.add_argument("--output", default="/tmp/mice_menu_preview.png", help="Output PNG path")
parser.add_argument("--screen", choices=("start", "pause", "level_intro"), default="start")
parser.add_argument("--difficulty", choices=("easy", "normal", "hard", "medium"), default="hard")
parser.add_argument("--level", type=int, default=0, help="0-based level index")
parser.add_argument("--resolution", default="1280x720", help="Preview resolution, for example 1280x720")
parser.add_argument("--seed", type=int, default=1337, help="Random seed for deterministic previews")
parser.add_argument("--animation-ms", type=int, default=1200, help="Start-menu GIF timestamp in milliseconds")
return parser.parse_args()
def configure_environment(args):
os.environ.setdefault("MICE_PROJECT_ROOT", str(PROJECT_ROOT))
os.environ.setdefault("SDL_VIDEODRIVER", "dummy")
os.environ.setdefault("SDL_AUDIODRIVER", "dummy")
os.environ.setdefault("SDL_RENDER_DRIVER", "software")
os.environ.setdefault("MICE_DISABLE_JOYSTICK", "1")
os.environ["RESOLUTION"] = args.resolution
def build_game(args):
from engine import maze, sdl2 as engine
from rats import MiceMaze
original_show_intro = engine.GameWindow.show_intro
original_load_joystick = engine.GameWindow.load_joystick
original_start_game = MiceMaze.start_game
def preview_start_game(self):
self.start_menu_animation_started_at = time.monotonic()
self.current_level_music = self._resolve_level_music(self.current_level)
self._valid_positions = None
self.run_recorded = False
self.ammo = {
"bomb": {"count": 2, "max": 8},
"nuclear": {"count": 1, "max": 1},
"mine": {"count": 2, "max": 4},
"gas": {"count": 2, "max": 4},
}
self.blood_stains = {}
self.background_texture = None
self.blood_layer_sprites.clear()
self.cave_foreground_tiles.clear()
self.game_end = (False, None)
self.game_status = "start_menu"
self.menu_screen = "start"
self.units.clear()
self.unit_positions.clear()
self.unit_positions_before.clear()
self.points = 0
self.pointer = (self.map.width // 2, self.map.height // 2)
self.scroll_cursor()
engine.GameWindow.show_intro = lambda self, *a, **k: None
engine.GameWindow.load_joystick = lambda self: None
MiceMaze.start_game = preview_start_game
try:
game = MiceMaze(maze.get_default_map_source(), level_index=args.level)
finally:
engine.GameWindow.show_intro = original_show_intro
engine.GameWindow.load_joystick = original_load_joystick
MiceMaze.start_game = original_start_game
game.render_engine.audio = False
game._apply_difficulty(args.difficulty, persist=False)
game.start_menu_animation_started_at = time.monotonic() - args.animation_ms / 1000
return game
def render_screen(game, screen_name):
renderer = game.render_engine.renderer
renderer.clear()
game.draw_maze()
if screen_name == "start":
game.game_status = "start_menu"
game.menu_screen = "start"
game.render_start_menu()
elif screen_name == "pause":
game.game_status = "paused"
game.menu_screen = None
game.render_pause_menu()
else:
game.game_status = "start_menu"
game.menu_screen = "level_intro"
game.render_engine.dialog(
f"Level {game.current_level + 1}",
subtitle=f"Points: {game.points}\nPress Return to begin",
image=game.assets["BMP_WEWIN"],
)
renderer.present()
def main():
args = parse_args()
configure_environment(args)
random.seed(args.seed)
game = build_game(args)
output_path = Path(args.output).expanduser()
try:
render_screen(game, args.screen)
saved_path = game.render_engine.save_frame(output_path)
print(saved_path)
finally:
game.render_engine.close()
if __name__ == "__main__":
sys.exit(main())