Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import pygame
- import math
- import sys
- # Constants
- SCREEN_WIDTH, SCREEN_HEIGHT = 800, 800
- CENTER_X, CENTER_Y = SCREEN_WIDTH // 2, SCREEN_HEIGHT // 2
- SCALE = 150 # pixels per AU (adjust as needed)
- TIME_STEP = 0.001 # years per frame (controls animation speed)
- # Planet data (a in AU, e in [0,1), period in years)
- planets = [
- {"name": "Mercury", "color": (180, 180, 180), "a": 0.387, "e": 0.2056, "period": 0.2408},
- {"name": "Venus", "color": (200, 100, 100), "a": 0.723, "e": 0.0068, "period": 0.6152},
- {"name": "Earth", "color": (0, 0, 255), "a": 1.0, "e": 0.0167, "period": 1.0},
- {"name": "Mars", "color": (180, 0, 0), "a": 1.524, "e": 0.0935, "period": 1.882},
- ]
- # Comet data (a in AU, e > 1 for hyperbola)
- comet = {"name": "Comet", "color": (255, 255, 255), "a": -1.0, "e": 2.0}
- # Precompute orbit points for planets and comet
- def precompute_orbit_points(obj, scale=SCALE, center=(400, 400)):
- a, e = obj["a"], obj["e"]
- if e < 1: # Elliptical orbit
- points = []
- for theta in range(0, 360):
- theta_rad = math.radians(theta)
- r = (a * (1 - e**2)) / (1 + e * math.cos(theta_rad))
- x = r * math.cos(theta_rad) * scale + center[0]
- y = r * math.sin(theta_rad) * scale + center[1]
- points.append((x, y))
- else: # Hyperbolic orbit
- a_abs = abs(a)
- points = []
- H_max = 5.0 # Hyperbolic anomaly range
- steps = 1000
- for i in range(-steps, steps + 1):
- H = i * H_max / steps
- x, y = get_position_hyperbola(a_abs, e, H)
- screen_x = x * scale + center[0]
- screen_y = y * scale + center[1]
- points.append((screen_x, screen_y))
- return points
- # Position functions
- def get_position_ellipse(a, e, E):
- b = a * math.sqrt(1 - e**2)
- x = a * (math.cos(E) - e)
- y = b * math.sin(E)
- return x, y
- def get_position_hyperbola(a, e, H):
- b = a * math.sqrt(e**2 - 1)
- x = a * (math.cosh(H) - e)
- y = b * math.sinh(H)
- return x, y
- # Solvers for Kepler's equation
- def solve_kepler(M, e):
- E = M
- for _ in range(100):
- delta = (E - e * math.sin(E) - M) / (1 - e * math.cos(E))
- E -= delta
- if abs(delta) < 1e-8:
- break
- return E
- def solve_hyperbolic_kepler(M, e):
- H = 0.0
- for _ in range(100):
- delta = (e * math.sinh(H) - H - M) / (e * math.cosh(H) - 1)
- H -= delta
- if abs(delta) < 1e-8:
- break
- return H
- # Main loop
- def main():
- pygame.init()
- screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
- clock = pygame.time.Clock()
- running = True
- current_time = 0.0 # in years
- # Precompute orbit lines
- planet_orbits = [precompute_orbit_points(planet) for planet in planets]
- comet_orbit = precompute_orbit_points(comet)
- while running:
- for event in pygame.event.get():
- if event.type == pygame.QUIT:
- running = False
- screen.fill((0, 0, 0))
- # Draw Sun
- pygame.draw.circle(screen, (255, 255, 0), (CENTER_X, CENTER_Y), 10)
- # Update and draw planets
- for i, planet in enumerate(planets):
- a, e, period = planet["a"], planet["e"], planet["period"]
- M = 2 * math.pi * (current_time / period)
- E = solve_kepler(M, e)
- x, y = get_position_ellipse(a, e, E)
- screen_x = x * SCALE + CENTER_X
- screen_y = y * SCALE + CENTER_Y
- pygame.draw.lines(screen, planet["color"], False, planet_orbits[i], 1)
- pygame.draw.circle(screen, planet["color"], (int(screen_x), int(screen_y)), 5)
- # Update and draw comet
- a, e = comet["a"], comet["e"]
- a_abs = abs(a)
- n = math.sqrt(1 / (a_abs ** 3)) # Mean motion for hyperbola
- M = n * current_time
- H = solve_hyperbolic_kepler(M, e)
- x, y = get_position_hyperbola(a_abs, e, H)
- screen_x = x * SCALE + CENTER_X
- screen_y = y * SCALE + CENTER_Y
- pygame.draw.lines(screen, comet["color"], False, comet_orbit, 1)
- pygame.draw.circle(screen, comet["color"], (int(screen_x), int(screen_y)), 3)
- pygame.display.flip()
- clock.tick(60)
- current_time += TIME_STEP
- pygame.quit()
- if __name__ == "__main__":
- main()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement