import math import random from solar_objects import Star, Planet TICKET_CONFIG = { "window": {"width": 1200, "height": 720, "min_width": 850, "min_height": 560}, "stars": [ { "name": "Star 1", "planet_count": 11, "planets_per_orbit": 1, "orbit_radii": [70, 85, 100, 115, 130, 145, 160, 175, 190, 205, 220], "color": (255, 190, 40), "mass": 1.989e30, }, { "name": "Star 2", "planet_count": 12, "planets_per_orbit": 2, "orbit_radii": [80, 110, 140, 170, 200, 230], "color": (255, 150, 55), "mass": 1.650e30, }, ], "rules": {"even_orbit_direction": -1, "odd_orbit_direction": 1, "orbits_must_intersect": True}, } SAFE_START_ANGLES = [ 3.009640, 2.737011, 5.484431, 2.979849, 1.049068, 1.478066, 1.191136, 1.579170, 4.454420, 4.226254, 2.025695, 0.705927, 3.488630, 2.293706, 6.173658, 0.440441, 5.055767, ] class SolarSystem: def __init__(self, width=1200, height=720): self.width = width self.height = height self.stars = [] self.show_orbits = True self.paused = False self.create_system() self.resize(width, height) def create_system(self): self.stars = [] for star_index, star_data in enumerate(TICKET_CONFIG["stars"]): star = Star( 0, 0, radius=34, color=star_data["color"], name=star_data["name"], mass=star_data["mass"], ) planet_count = star_data["planet_count"] planets_per_orbit = star_data["planets_per_orbit"] created = 0 for orbit_number, orbit_radius in enumerate(star_data["orbit_radii"], start=1): direction = self.get_direction(orbit_number) # Ближние к звезде планеты двигаются быстрее, дальние — медленнее. # Скорости и начальные углы подобраны так, чтобы планеты не пересекались. angular_speed = (0.055 / (orbit_number ** 0.45)) * (1.0 if star_index == 0 else 0.945) # Начальные углы подобраны заранее: планеты не стартуют кучей и не встречаются на пересечениях орбит. angle_index = created if star_index == 0 else 11 + (orbit_number - 1) base_angle = SAFE_START_ANGLES[angle_index] for place in range(planets_per_orbit): if created >= planet_count: break # Если на одной орбите две планеты, они стоят напротив друг друга. angle = base_angle + place * (2 * math.pi / planets_per_orbit) planet = Planet( star, orbit_number, orbit_radius, angle, angular_speed, direction, random.uniform(3.0e24, 8.0e24), ) star.add_planet(planet) created += 1 self.stars.append(star) def get_direction(self, orbit_number): if orbit_number % 2 == 0: return TICKET_CONFIG["rules"]["even_orbit_direction"] return TICKET_CONFIG["rules"]["odd_orbit_direction"] def resize(self, width, height): self.width = width self.height = height center_x = width // 2 center_y = height // 2 distance = 285 self.stars[0].set_position(center_x - distance // 2, center_y) self.stars[1].set_position(center_x + distance // 2, center_y) for star in self.stars: for planet in star.planets: planet.x, planet.y = planet.calculate_position() def update(self): if self.paused: return for star in self.stars: star.update() def draw(self, screen, pygame): for star in self.stars: star.draw(screen, pygame, self.show_orbits) def toggle_pause(self): self.paused = not self.paused def toggle_orbits(self): self.show_orbits = not self.show_orbits def get_all_planets(self): planets = [] for star in self.stars: planets.extend(star.planets) return planets def get_all_objects(self): objects = [] for star in self.stars: objects.append(star) objects.extend(star.planets) return objects def get_total_mass(self): return sum(space_object.mass for space_object in self.get_all_objects()) def get_planet_count(self): return sum(len(star.planets) for star in self.stars)