fix: Refine geometry demos for 1024x768 and fix animations
- Fix timer restart when switching between animated demo scenes - Update all demos from 800x600 to 1024x768 resolution - Add screen_angle_between() for correct arc angles in screen coords - Fix arc directions by accounting for screen Y inversion - Reposition labels to avoid text overlaps - Shift solar system center down to prevent moon orbit overflow - Reposition ship/target in pathfinding demo to avoid sun clipping - Scale menu screen to fill 1024x768 with wider buttons - Regenerate all demo screenshots 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
576481957a
commit
51e96c0c6b
12 changed files with 497 additions and 337 deletions
|
|
@ -1,6 +1,7 @@
|
|||
"""Bresenham circle algorithm demonstration on a grid."""
|
||||
import mcrfpy
|
||||
from .base import GeometryDemoScreen, bresenham_circle, bresenham_line, filled_circle
|
||||
import math
|
||||
from .base import GeometryDemoScreen, bresenham_circle, bresenham_line, filled_circle, SCREEN_WIDTH, SCREEN_HEIGHT
|
||||
|
||||
|
||||
class BresenhamDemo(GeometryDemoScreen):
|
||||
|
|
@ -13,48 +14,71 @@ class BresenhamDemo(GeometryDemoScreen):
|
|||
self.add_title("Bresenham Circle & Line Algorithms")
|
||||
self.add_description("Grid-aligned geometric primitives for orbit rings and LOS calculations")
|
||||
|
||||
# Create a grid for circle demo
|
||||
grid_w, grid_h = 25, 18
|
||||
cell_size = 16
|
||||
margin = 30
|
||||
frame_gap = 20
|
||||
|
||||
# We need a texture for the grid - create a simple one
|
||||
# Actually, let's use Grid's built-in cell coloring via GridPoint
|
||||
# Calculate frame dimensions for 2x2 layout
|
||||
# Available width: 1024 - 2*margin = 964, split into 2 with gap
|
||||
frame_width = (SCREEN_WIDTH - 2 * margin - frame_gap) // 2 # ~472 each
|
||||
# Available height for frames: 768 - 80 (top) - 30 (bottom margin)
|
||||
top_area = 80
|
||||
bottom_margin = 30
|
||||
available_height = SCREEN_HEIGHT - top_area - bottom_margin - frame_gap
|
||||
frame_height = available_height // 2 # ~314 each
|
||||
|
||||
# Create display area with Frame background
|
||||
bg1 = mcrfpy.Frame(pos=(30, 80), size=(420, 310))
|
||||
bg1.fill_color = mcrfpy.Color(15, 15, 25)
|
||||
bg1.outline = 1
|
||||
bg1.outline_color = mcrfpy.Color(60, 60, 100)
|
||||
self.ui.append(bg1)
|
||||
# Top-left: Bresenham Circle
|
||||
self._draw_circle_demo(margin, top_area, frame_width, frame_height, cell_size)
|
||||
|
||||
self.add_label("Bresenham Circle (radius=8)", 50, 85, (255, 200, 100))
|
||||
self.add_label("Center: (12, 9)", 50, 105, (150, 150, 150))
|
||||
# Top-right: Bresenham Lines
|
||||
self._draw_lines_demo(margin + frame_width + frame_gap, top_area, frame_width, frame_height, cell_size)
|
||||
|
||||
# Bottom-left: Filled Circle
|
||||
self._draw_filled_demo(margin, top_area + frame_height + frame_gap, frame_width, frame_height, cell_size)
|
||||
|
||||
# Bottom-right: Planet + Orbit Ring
|
||||
self._draw_combined_demo(margin + frame_width + frame_gap, top_area + frame_height + frame_gap,
|
||||
frame_width, frame_height, cell_size)
|
||||
|
||||
def _draw_circle_demo(self, x, y, w, h, cell_size):
|
||||
"""Draw Bresenham circle demonstration."""
|
||||
bg = mcrfpy.Frame(pos=(x, y), size=(w, h))
|
||||
bg.fill_color = mcrfpy.Color(15, 15, 25)
|
||||
bg.outline = 1
|
||||
bg.outline_color = mcrfpy.Color(60, 60, 100)
|
||||
self.ui.append(bg)
|
||||
|
||||
self.add_label("Bresenham Circle (radius=8)", x + 10, y + 5, (255, 200, 100))
|
||||
self.add_label("Center: (12, 9)", x + 10, y + 25, (150, 150, 150))
|
||||
|
||||
# Grid origin for this demo
|
||||
grid_x = x + 20
|
||||
grid_y = y + 50
|
||||
|
||||
# Draw circle using UICircle primitives to show the cells
|
||||
center = (12, 9)
|
||||
radius = 8
|
||||
circle_cells = bresenham_circle(center, radius)
|
||||
|
||||
# Draw each cell as a small rectangle
|
||||
for x, y in circle_cells:
|
||||
px = 40 + x * cell_size
|
||||
py = 120 + y * cell_size
|
||||
# Draw each cell
|
||||
for cx, cy in circle_cells:
|
||||
px = grid_x + cx * cell_size
|
||||
py = grid_y + cy * cell_size
|
||||
cell_rect = mcrfpy.Frame(pos=(px, py), size=(cell_size - 1, cell_size - 1))
|
||||
cell_rect.fill_color = mcrfpy.Color(100, 200, 255)
|
||||
cell_rect.outline = 0
|
||||
self.ui.append(cell_rect)
|
||||
|
||||
# Draw center point
|
||||
cx_px = 40 + center[0] * cell_size
|
||||
cy_px = 120 + center[1] * cell_size
|
||||
cx_px = grid_x + center[0] * cell_size
|
||||
cy_px = grid_y + center[1] * cell_size
|
||||
center_rect = mcrfpy.Frame(pos=(cx_px, cy_px), size=(cell_size - 1, cell_size - 1))
|
||||
center_rect.fill_color = mcrfpy.Color(255, 100, 100)
|
||||
self.ui.append(center_rect)
|
||||
|
||||
# Draw the actual circle outline for comparison
|
||||
# Draw actual circle outline for comparison (centered on cells)
|
||||
actual_circle = mcrfpy.Circle(
|
||||
center=(40 + center[0] * cell_size + cell_size // 2,
|
||||
120 + center[1] * cell_size + cell_size // 2),
|
||||
center=(grid_x + center[0] * cell_size + cell_size // 2,
|
||||
grid_y + center[1] * cell_size + cell_size // 2),
|
||||
radius=radius * cell_size,
|
||||
fill_color=mcrfpy.Color(0, 0, 0, 0),
|
||||
outline_color=mcrfpy.Color(255, 255, 100, 128),
|
||||
|
|
@ -62,14 +86,18 @@ class BresenhamDemo(GeometryDemoScreen):
|
|||
)
|
||||
self.ui.append(actual_circle)
|
||||
|
||||
# Second demo: Bresenham line
|
||||
bg2 = mcrfpy.Frame(pos=(470, 80), size=(310, 310))
|
||||
bg2.fill_color = mcrfpy.Color(15, 15, 25)
|
||||
bg2.outline = 1
|
||||
bg2.outline_color = mcrfpy.Color(60, 60, 100)
|
||||
self.ui.append(bg2)
|
||||
def _draw_lines_demo(self, x, y, w, h, cell_size):
|
||||
"""Draw Bresenham lines demonstration."""
|
||||
bg = mcrfpy.Frame(pos=(x, y), size=(w, h))
|
||||
bg.fill_color = mcrfpy.Color(15, 15, 25)
|
||||
bg.outline = 1
|
||||
bg.outline_color = mcrfpy.Color(60, 60, 100)
|
||||
self.ui.append(bg)
|
||||
|
||||
self.add_label("Bresenham Lines", 490, 85, (255, 200, 100))
|
||||
self.add_label("Bresenham Lines", x + 10, y + 5, (255, 200, 100))
|
||||
|
||||
grid_x = x + 20
|
||||
grid_y = y + 40
|
||||
|
||||
# Draw multiple lines at different angles
|
||||
lines_data = [
|
||||
|
|
@ -80,91 +108,100 @@ class BresenhamDemo(GeometryDemoScreen):
|
|||
|
||||
for start, end, color in lines_data:
|
||||
line_cells = bresenham_line(start, end)
|
||||
for x, y in line_cells:
|
||||
px = 480 + x * cell_size
|
||||
py = 110 + y * cell_size
|
||||
for cx, cy in line_cells:
|
||||
px = grid_x + cx * cell_size
|
||||
py = grid_y + cy * cell_size
|
||||
cell_rect = mcrfpy.Frame(pos=(px, py), size=(cell_size - 1, cell_size - 1))
|
||||
cell_rect.fill_color = mcrfpy.Color(*color)
|
||||
self.ui.append(cell_rect)
|
||||
|
||||
# Draw the actual line for comparison
|
||||
# Draw the actual line for comparison (through cell centers)
|
||||
line = mcrfpy.Line(
|
||||
start=(480 + start[0] * cell_size + cell_size // 2,
|
||||
110 + start[1] * cell_size + cell_size // 2),
|
||||
end=(480 + end[0] * cell_size + cell_size // 2,
|
||||
110 + end[1] * cell_size + cell_size // 2),
|
||||
start=(grid_x + start[0] * cell_size + cell_size // 2,
|
||||
grid_y + start[1] * cell_size + cell_size // 2),
|
||||
end=(grid_x + end[0] * cell_size + cell_size // 2,
|
||||
grid_y + end[1] * cell_size + cell_size // 2),
|
||||
color=mcrfpy.Color(255, 255, 255, 128),
|
||||
thickness=1
|
||||
)
|
||||
self.ui.append(line)
|
||||
|
||||
# Third demo: Filled circle (planet surface)
|
||||
bg3 = mcrfpy.Frame(pos=(30, 410), size=(200, 170))
|
||||
bg3.fill_color = mcrfpy.Color(15, 15, 25)
|
||||
bg3.outline = 1
|
||||
bg3.outline_color = mcrfpy.Color(60, 60, 100)
|
||||
self.ui.append(bg3)
|
||||
def _draw_filled_demo(self, x, y, w, h, cell_size):
|
||||
"""Draw filled circle demonstration."""
|
||||
bg = mcrfpy.Frame(pos=(x, y), size=(w, h))
|
||||
bg.fill_color = mcrfpy.Color(15, 15, 25)
|
||||
bg.outline = 1
|
||||
bg.outline_color = mcrfpy.Color(60, 60, 100)
|
||||
self.ui.append(bg)
|
||||
|
||||
self.add_label("Filled Circle (radius=4)", 50, 415, (255, 200, 100))
|
||||
self.add_label("Planet surface representation", 50, 435, (150, 150, 150))
|
||||
self.add_label("Filled Circle (radius=5)", x + 10, y + 5, (255, 200, 100))
|
||||
self.add_label("Planet surface representation", x + 10, y + 25, (150, 150, 150))
|
||||
|
||||
fill_center = (6, 5)
|
||||
fill_radius = 4
|
||||
grid_x = x + 50
|
||||
grid_y = y + 60
|
||||
|
||||
fill_center = (8, 8)
|
||||
fill_radius = 5
|
||||
filled_cells = filled_circle(fill_center, fill_radius)
|
||||
|
||||
for x, y in filled_cells:
|
||||
px = 40 + x * cell_size
|
||||
py = 460 + y * cell_size
|
||||
cell_rect = mcrfpy.Frame(pos=(px, py), size=(cell_size - 1, cell_size - 1))
|
||||
for cx, cy in filled_cells:
|
||||
px = grid_x + cx * cell_size
|
||||
py = grid_y + cy * cell_size
|
||||
# Gradient based on distance from center
|
||||
dist = ((x - fill_center[0])**2 + (y - fill_center[1])**2) ** 0.5
|
||||
dist = math.sqrt((cx - fill_center[0])**2 + (cy - fill_center[1])**2)
|
||||
intensity = int(255 * (1 - dist / (fill_radius + 1)))
|
||||
cell_rect = mcrfpy.Frame(pos=(px, py), size=(cell_size - 1, cell_size - 1))
|
||||
cell_rect.fill_color = mcrfpy.Color(intensity, intensity // 2, 50)
|
||||
self.ui.append(cell_rect)
|
||||
|
||||
# Fourth demo: Combined - planet with orbit ring
|
||||
bg4 = mcrfpy.Frame(pos=(250, 410), size=(530, 170))
|
||||
bg4.fill_color = mcrfpy.Color(15, 15, 25)
|
||||
bg4.outline = 1
|
||||
bg4.outline_color = mcrfpy.Color(60, 60, 100)
|
||||
self.ui.append(bg4)
|
||||
def _draw_combined_demo(self, x, y, w, h, cell_size):
|
||||
"""Draw planet + orbit ring demonstration."""
|
||||
bg = mcrfpy.Frame(pos=(x, y), size=(w, h))
|
||||
bg.fill_color = mcrfpy.Color(15, 15, 25)
|
||||
bg.outline = 1
|
||||
bg.outline_color = mcrfpy.Color(60, 60, 100)
|
||||
self.ui.append(bg)
|
||||
|
||||
self.add_label("Planet + Orbit Ring", 270, 415, (255, 200, 100))
|
||||
self.add_label("Surface (r=3) + Orbit (r=7)", 270, 435, (150, 150, 150))
|
||||
self.add_label("Planet + Orbit Ring", x + 10, y + 5, (255, 200, 100))
|
||||
self.add_label("Surface (r=3) + Orbit (r=8)", x + 10, y + 25, (150, 150, 150))
|
||||
|
||||
planet_center = (16, 5)
|
||||
grid_x = x + 60
|
||||
grid_y = y + 50
|
||||
|
||||
planet_center = (12, 10)
|
||||
surface_radius = 3
|
||||
orbit_radius = 7
|
||||
orbit_radius = 8
|
||||
|
||||
# Draw orbit ring (behind planet)
|
||||
orbit_cells = bresenham_circle(planet_center, orbit_radius)
|
||||
for x, y in orbit_cells:
|
||||
px = 260 + x * cell_size
|
||||
py = 460 + y * cell_size
|
||||
for cx, cy in orbit_cells:
|
||||
px = grid_x + cx * cell_size
|
||||
py = grid_y + cy * cell_size
|
||||
cell_rect = mcrfpy.Frame(pos=(px, py), size=(cell_size - 1, cell_size - 1))
|
||||
cell_rect.fill_color = mcrfpy.Color(50, 150, 50, 180)
|
||||
self.ui.append(cell_rect)
|
||||
|
||||
# Draw planet surface (on top)
|
||||
surface_cells = filled_circle(planet_center, surface_radius)
|
||||
for x, y in surface_cells:
|
||||
px = 260 + x * cell_size
|
||||
py = 460 + y * cell_size
|
||||
cell_rect = mcrfpy.Frame(pos=(px, py), size=(cell_size - 1, cell_size - 1))
|
||||
dist = ((x - planet_center[0])**2 + (y - planet_center[1])**2) ** 0.5
|
||||
for cx, cy in surface_cells:
|
||||
px = grid_x + cx * cell_size
|
||||
py = grid_y + cy * cell_size
|
||||
dist = math.sqrt((cx - planet_center[0])**2 + (cy - planet_center[1])**2)
|
||||
intensity = int(200 * (1 - dist / (surface_radius + 1)))
|
||||
cell_rect = mcrfpy.Frame(pos=(px, py), size=(cell_size - 1, cell_size - 1))
|
||||
cell_rect.fill_color = mcrfpy.Color(50 + intensity, 100 + intensity // 2, 200)
|
||||
self.ui.append(cell_rect)
|
||||
|
||||
# Legend
|
||||
self.add_label("Legend:", 600, 455, (200, 200, 200))
|
||||
# Legend in bottom-left of frame
|
||||
leg_x = x + 10
|
||||
leg_y = y + h - 50
|
||||
|
||||
leg1 = mcrfpy.Frame(pos=(600, 475), size=(12, 12))
|
||||
leg1 = mcrfpy.Frame(pos=(leg_x, leg_y), size=(12, 12))
|
||||
leg1.fill_color = mcrfpy.Color(100, 150, 200)
|
||||
self.ui.append(leg1)
|
||||
self.add_label("Planet surface", 620, 473, (150, 150, 150))
|
||||
self.add_label("Planet", leg_x + 18, leg_y - 2, (150, 150, 150))
|
||||
|
||||
leg2 = mcrfpy.Frame(pos=(600, 495), size=(12, 12))
|
||||
leg2 = mcrfpy.Frame(pos=(leg_x, leg_y + 20), size=(12, 12))
|
||||
leg2.fill_color = mcrfpy.Color(50, 150, 50)
|
||||
self.ui.append(leg2)
|
||||
self.add_label("Orbit ring (ship positions)", 620, 493, (150, 150, 150))
|
||||
self.add_label("Orbit ring", leg_x + 18, leg_y + 18, (150, 150, 150))
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue