Advertisement
Guest User

A tale of two rabbits

a guest
Feb 23rd, 2025
48
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 5.49 KB | None | 0 0
  1. import pygame
  2. import math
  3.  
  4. # Initialize Pygame
  5. pygame.init()
  6.  
  7. # Set up the display
  8. WIDTH = 800
  9. HEIGHT = 600
  10. screen = pygame.display.set_mode((WIDTH, HEIGHT))
  11. pygame.display.set_caption("A tale of two rabbits")
  12.  
  13. # Colors
  14. WHITE = (255, 255, 255)
  15. BLACK = (0, 0, 0)
  16. RED = (255, 0, 0)
  17. BLUE = (0, 0, 255)
  18.  
  19. def interpolate_color(color1, color2, factor):
  20.     r = int(color1[0] + (color2[0] - color1[0]) * factor)
  21.     g = int(color1[1] + (color2[1] - color1[1]) * factor)
  22.     b = int(color1[2] + (color2[2] - color1[2]) * factor)
  23.     return (r, g, b)
  24.  
  25. # Animation parameters
  26. num_sides = 24
  27. radius = 150
  28. growth_rate = 0.5
  29. rotation_angle = 0
  30.  
  31. # Function to calculate polygon points
  32. def get_polygon_points(center_x, center_y, radius, num_sides, rotation):
  33.     points = []
  34.     for i in range(num_sides):
  35.         angle = rotation + (2 * math.pi * i / num_sides)
  36.         x = center_x + radius * math.cos(angle)
  37.         y = center_y + radius * math.sin(angle)
  38.         points.append((int(x), int(y)))
  39.     return points
  40.  
  41. def relax_points(points, step_size):
  42.     new_points = points.copy()
  43.     # center_x = sum([point[0] for point in points]) / len(points)
  44.     # center_y = sum([point[1] for point in points]) / len(points)
  45.     # target_center_x = WIDTH // 2
  46.     # target_center_y = HEIGHT // 2
  47.     for i in range(1, len(points) - 1):
  48.         x, y = points[i]
  49.         x_next, y_next = points[i + 1]
  50.         x_prev, y_prev = points[i - 1]
  51.         # Place the point in the middle of x_prev and x_next, but leave the curvature intact
  52.         dot_product = (x - x_prev) * (x_next - x_prev) + (y - y_prev) * (y_next - y_prev)
  53.         alpha = 0.5 - dot_product / ((x_next - x_prev) ** 2 + (y_next - y_prev) ** 2)
  54.         x_new = x + alpha * (x_next - x_prev) * step_size
  55.         y_new = y + alpha * (y_next - y_prev) * step_size
  56.         # x_new = x_new + (target_center_x - center_x) * step_size
  57.         # y_new = y_new + (target_center_y - center_y) * step_size
  58.         new_points[i] = (x_new, y_new)
  59.  
  60.     return new_points
  61.  
  62. # Maximize polygon area subject to perimeter + len(x0,x1) = 10
  63. def gradient_descent(points, permimeter_penalty, step_size):
  64.     new_points = points.copy()
  65.     perimeter = 0
  66.     for i in range(len(points)):
  67.         x, y = points[i]
  68.         x_next, y_next = points[(i + 1) % len(points)]
  69.         length = math.sqrt((x_next - x) ** 2 + (y_next - y) ** 2)
  70.         if i != len(points) - 1:
  71.             perimeter += length*2
  72.         else:
  73.             perimeter += length
  74.     for i in range(len(points)):
  75.         x, y = points[i]
  76.         x_next, y_next = points[(i + 1) % len(points)]
  77.         x_prev, y_prev = points[(i - 1) % len(points)]
  78.         d_next = math.sqrt((x_next - x) ** 2 + (y_next - y) ** 2)
  79.         d_prev = math.sqrt((x_prev - x) ** 2 + (y_prev - y) ** 2)
  80.         prev_multiplier = 1 if i != 0 else 0.5
  81.         next_multiplier = 1 if i != len(points) - 1 else 0.5
  82.         grad_perimeter_x = (x - x_prev) / d_prev * prev_multiplier + (x - x_next) / d_next * next_multiplier
  83.         grad_perimeter_y = (y - y_prev) / d_prev * prev_multiplier + (y - y_next) / d_next * next_multiplier
  84.         grad_perimeter_sign = 1 if perimeter < 2000 else -1
  85.         area_grad_x = (y_next - y_prev)
  86.         area_grad_y = (x_prev - x_next)
  87.         x_new = x + step_size * (
  88.                 area_grad_x + permimeter_penalty * grad_perimeter_x * grad_perimeter_sign)
  89.         y_new = y + step_size * (
  90.                 area_grad_y + permimeter_penalty * grad_perimeter_y * grad_perimeter_sign)
  91.         new_points[i] = (x_new, y_new)
  92.     return new_points
  93.  
  94. def compute_symmetry_points(points):
  95.     """Symmetry with respect to (points[0], points[len(points)-1])"""
  96.     new_points = points.copy()
  97.     x0, y0 = points[0]
  98.     x1, y1 = points[len(points) - 1]
  99.  
  100.     # Vector of the line
  101.     dx = x1 - x0
  102.     dy = y1 - y0
  103.     # Length squared of the line
  104.     l2 = dx*dx + dy*dy
  105.  
  106.     for i in range(len(points)):
  107.         x, y = points[i]
  108.         # Vector from line start to point
  109.         px = x - x0
  110.         py = y - y0
  111.         # Project point onto line
  112.         dot = (px*dx + py*dy) / l2
  113.         # Projection point
  114.         proj_x = x0 + dot * dx
  115.         proj_y = y0 + dot * dy
  116.         # Reflect point across projection
  117.         new_x = 2 * proj_x - x
  118.         new_y = 2 * proj_y - y
  119.         new_points[i] = (new_x, new_y)
  120.  
  121.     return new_points
  122.  
  123.  
  124. # Main game loop
  125. running = True
  126. clock = pygame.time.Clock()
  127.  
  128. points = get_polygon_points(WIDTH // 4, HEIGHT // 2, radius, num_sides, rotation_angle)
  129. step_size = 0.005
  130.  
  131. while running:
  132.     for event in pygame.event.get():
  133.         if event.type == pygame.QUIT:
  134.             running = False
  135.  
  136.     # Clear screen
  137.     screen.fill(BLACK)
  138.  
  139.     # Calculate polygon points
  140.     center_x = WIDTH // 2
  141.     center_y = HEIGHT // 2
  142.     points = gradient_descent(points, permimeter_penalty=500, step_size=step_size)
  143.     points = relax_points(points, 0.1)
  144.     step_size *= 0.999
  145.     symmetry_points = compute_symmetry_points(points)
  146.  
  147.     # Draw polygon
  148.     pygame.draw.polygon(screen, WHITE, points, 2)
  149.     pygame.draw.polygon(screen, WHITE, symmetry_points, 2)
  150.  
  151.     # Draw corner points with gradient from red to blue
  152.     for i, point in enumerate(points):
  153.         color = interpolate_color(RED, BLUE, i / (len(points) - 1))
  154.         pygame.draw.circle(screen, color, point, 5)
  155.         pygame.draw.circle(screen, color, symmetry_points[i], 5)
  156.  
  157.     # Update display
  158.     pygame.display.flip()
  159.  
  160.     # Control frame rate
  161.     clock.tick(60)
  162.  
  163. pygame.quit()
  164.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement