214 lines
7.0 KiB
Python
214 lines
7.0 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
Geometry Module Demo System
|
|
|
|
Demonstrates the geometry module for Pinships orbital mechanics:
|
|
- Bresenham algorithms for grid-aligned circles and lines
|
|
- Angle calculations for pathfinding
|
|
- Static pathfinding through planetary orbits
|
|
- Animated solar system with discrete time steps
|
|
- Ship navigation anticipating planetary motion
|
|
|
|
Usage:
|
|
Headless (screenshots): ./mcrogueface --headless --exec tests/geometry_demo/geometry_main.py
|
|
Interactive: ./mcrogueface tests/geometry_demo/geometry_main.py
|
|
"""
|
|
import mcrfpy
|
|
from mcrfpy import automation
|
|
import sys
|
|
import os
|
|
|
|
# Add paths for imports
|
|
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
|
sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..', '..', 'src', 'scripts'))
|
|
|
|
# Import screen modules
|
|
from geometry_demo.screens.bresenham_demo import BresenhamDemo
|
|
from geometry_demo.screens.angle_lines_demo import AngleLinesDemo
|
|
from geometry_demo.screens.pathfinding_static_demo import PathfindingStaticDemo
|
|
from geometry_demo.screens.solar_system_demo import SolarSystemDemo
|
|
from geometry_demo.screens.pathfinding_animated_demo import PathfindingAnimatedDemo
|
|
|
|
# All demo screens in order
|
|
DEMO_SCREENS = [
|
|
BresenhamDemo,
|
|
AngleLinesDemo,
|
|
PathfindingStaticDemo,
|
|
SolarSystemDemo,
|
|
PathfindingAnimatedDemo,
|
|
]
|
|
|
|
|
|
class GeometryDemoRunner:
|
|
"""Manages the geometry demo system."""
|
|
|
|
def __init__(self):
|
|
self.screens = []
|
|
self.current_index = 0
|
|
self.headless = self._detect_headless()
|
|
self.screenshot_dir = os.path.join(os.path.dirname(__file__), "screenshots")
|
|
|
|
def _detect_headless(self):
|
|
"""Detect if running in headless mode."""
|
|
try:
|
|
win = mcrfpy.Window.get()
|
|
return str(win).find("headless") >= 0
|
|
except:
|
|
return True
|
|
|
|
def setup_all_screens(self):
|
|
"""Initialize all demo screens."""
|
|
for i, ScreenClass in enumerate(DEMO_SCREENS):
|
|
scene_name = f"geo_{i:02d}_{ScreenClass.name.lower().replace(' ', '_')}"
|
|
screen = ScreenClass(scene_name)
|
|
screen.setup()
|
|
self.screens.append(screen)
|
|
|
|
def create_menu(self):
|
|
"""Create the main menu screen."""
|
|
mcrfpy.createScene("geo_menu")
|
|
ui = mcrfpy.sceneUI("geo_menu")
|
|
|
|
# Background
|
|
bg = mcrfpy.Frame(pos=(0, 0), size=(800, 600))
|
|
bg.fill_color = mcrfpy.Color(15, 15, 25)
|
|
ui.append(bg)
|
|
|
|
# Title
|
|
title = mcrfpy.Caption(text="Geometry Module Demo", pos=(400, 30))
|
|
title.fill_color = mcrfpy.Color(255, 255, 255)
|
|
title.outline = 2
|
|
title.outline_color = mcrfpy.Color(0, 0, 0)
|
|
ui.append(title)
|
|
|
|
subtitle = mcrfpy.Caption(text="Pinships Orbital Mechanics", pos=(400, 70))
|
|
subtitle.fill_color = mcrfpy.Color(180, 180, 180)
|
|
ui.append(subtitle)
|
|
|
|
# Menu items
|
|
for i, screen in enumerate(self.screens):
|
|
y = 130 + i * 60
|
|
|
|
# Button frame
|
|
btn = mcrfpy.Frame(pos=(200, y), size=(400, 50))
|
|
btn.fill_color = mcrfpy.Color(30, 40, 60)
|
|
btn.outline = 2
|
|
btn.outline_color = mcrfpy.Color(80, 100, 150)
|
|
ui.append(btn)
|
|
|
|
# Button text
|
|
label = mcrfpy.Caption(text=f"{i+1}. {screen.name}", pos=(20, 12))
|
|
label.fill_color = mcrfpy.Color(200, 200, 255)
|
|
btn.children.append(label)
|
|
|
|
# Description
|
|
desc = mcrfpy.Caption(text=screen.description, pos=(20, 32))
|
|
desc.fill_color = mcrfpy.Color(120, 120, 150)
|
|
btn.children.append(desc)
|
|
|
|
# Instructions
|
|
instr1 = mcrfpy.Caption(text="Press 1-5 to view demos", pos=(300, 480))
|
|
instr1.fill_color = mcrfpy.Color(150, 150, 150)
|
|
ui.append(instr1)
|
|
|
|
instr2 = mcrfpy.Caption(text="ESC = return to menu | Q = quit", pos=(270, 510))
|
|
instr2.fill_color = mcrfpy.Color(100, 100, 100)
|
|
ui.append(instr2)
|
|
|
|
# Credits
|
|
credits = mcrfpy.Caption(text="Geometry module: src/scripts/geometry.py", pos=(250, 560))
|
|
credits.fill_color = mcrfpy.Color(80, 80, 100)
|
|
ui.append(credits)
|
|
|
|
def run_headless(self):
|
|
"""Run in headless mode - generate all screenshots."""
|
|
print(f"Generating {len(self.screens)} geometry demo screenshots...")
|
|
|
|
os.makedirs(self.screenshot_dir, exist_ok=True)
|
|
|
|
self.current_index = 0
|
|
self.render_wait = 0
|
|
|
|
def screenshot_cycle(runtime):
|
|
if self.render_wait == 0:
|
|
if self.current_index >= len(self.screens):
|
|
print("Done!")
|
|
sys.exit(0)
|
|
return
|
|
screen = self.screens[self.current_index]
|
|
mcrfpy.setScene(screen.scene_name)
|
|
self.render_wait = 1
|
|
elif self.render_wait < 3:
|
|
# Wait for animated demos to show initial state
|
|
self.render_wait += 1
|
|
else:
|
|
screen = self.screens[self.current_index]
|
|
filename = os.path.join(self.screenshot_dir, screen.get_screenshot_name())
|
|
automation.screenshot(filename)
|
|
print(f" [{self.current_index+1}/{len(self.screens)}] {filename}")
|
|
|
|
# Clean up timers for animated demos
|
|
screen.cleanup()
|
|
|
|
self.current_index += 1
|
|
self.render_wait = 0
|
|
if self.current_index >= len(self.screens):
|
|
print("Done!")
|
|
sys.exit(0)
|
|
|
|
mcrfpy.setTimer("screenshot", screenshot_cycle, 100)
|
|
|
|
def run_interactive(self):
|
|
"""Run in interactive mode with menu."""
|
|
self.create_menu()
|
|
|
|
def handle_key(key, state):
|
|
if state != "start":
|
|
return
|
|
|
|
# Number keys 1-9 for direct screen access
|
|
if key in [f"Num{n}" for n in "123456789"]:
|
|
idx = int(key[-1]) - 1
|
|
if idx < len(self.screens):
|
|
# Clean up previous screen's timers
|
|
for screen in self.screens:
|
|
screen.cleanup()
|
|
mcrfpy.setScene(self.screens[idx].scene_name)
|
|
# Re-setup the screen to restart animations
|
|
# (timers were cleaned up, need to restart)
|
|
|
|
# ESC returns to menu
|
|
elif key == "Escape":
|
|
for screen in self.screens:
|
|
screen.cleanup()
|
|
mcrfpy.setScene("geo_menu")
|
|
|
|
# Q quits
|
|
elif key == "Q":
|
|
sys.exit(0)
|
|
|
|
# Register keyboard handler on all scenes
|
|
mcrfpy.setScene("geo_menu")
|
|
mcrfpy.keypressScene(handle_key)
|
|
|
|
for screen in self.screens:
|
|
mcrfpy.setScene(screen.scene_name)
|
|
mcrfpy.keypressScene(handle_key)
|
|
|
|
mcrfpy.setScene("geo_menu")
|
|
|
|
|
|
def main():
|
|
"""Main entry point."""
|
|
runner = GeometryDemoRunner()
|
|
runner.setup_all_screens()
|
|
|
|
if runner.headless:
|
|
runner.run_headless()
|
|
else:
|
|
runner.run_interactive()
|
|
|
|
|
|
# Run when executed
|
|
main()
|