Refine start menu difficulty and preview workflow
This commit is contained in:
@@ -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())
|
||||
Reference in New Issue
Block a user