For the following code the panning and zooming dont seem to want to work at all for me. Can you go over this code and try to find what could be wrong with th epanning and zooming in and out functions please?



import pygame
import math
import sys
from pygame.locals import *

class CelestialBody:
    def __init__(self, name, color, distance, radius, period, direction=1):
        self.name = name
        self.color = color
        self.distance = distance
        self.radius = radius
        self.period = period
        self.direction = direction
        self.angle = 0.0
        self.path = []  # Store past positions

    def update_position(self, time_step):
        degrees_per_time = self.direction * (360 / self.period) * time_step
        self.angle = (self.angle + degrees_per_time) % 360

    def get_position(self, reference_position, scale):
        rad_angle = math.radians(self.angle)
        x = reference_position[0] + self.distance * scale * math.cos(rad_angle)
        y = reference_position[1] + self.distance * scale * math.sin(rad_angle)
        return (x, y)

def initialize_pygame(width=800, height=600):
    pygame.init()
    screen = pygame.display.set_mode((width, height))
    pygame.display.set_caption('Solar System Simulation')
    return screen

def create_celestial_bodies():
    sun = CelestialBody(name='Sun', color=(255, 255, 0), distance=0, radius=30, period=0)
    mercury = CelestialBody(name='Mercury', color=(169, 169, 169), distance=60, radius=8, period=0.24)
    venus = CelestialBody(name='Venus', color=(218, 165, 32), distance=90, radius=14, period=0.62)
    earth = CelestialBody(name='Earth', color=(0, 0, 255), distance=120, radius=16, period=1.0)
    mars = CelestialBody(name='Mars', color=(255, 0, 0), distance=150, radius=12, period=1.88)
    return [sun, mercury, venus, earth, mars]

def simulation_loop(screen, celestial_bodies, clock, time_step=0.005, initial_reference='Sun'):
    running = True
    font = pygame.font.SysFont(None, 24)
    reference_body = initial_reference
    last_reference = reference_body

    # Zoom and pan variables
    scale_factor = 1.0
    pan_offset = [0, 0]
    panning = False
    pan_start_pos = (0, 0)

    while running:
        screen.fill((0, 0, 0))  # Black background

        for event in pygame.event.get():
            if event.type == QUIT:
                running = False
            elif event.type == KEYDOWN:
                if event.key == K_ESCAPE:
                    running = False
                elif event.key == K_1:
                    reference_body = 'Sun'
                elif event.key == K_2:
                    reference_body = 'Mercury'
                elif event.key == K_3:
                    reference_body = 'Venus'
                elif event.key == K_4:
                    reference_body = 'Earth'
                elif event.key == K_5:
                    reference_body = 'Mars'
            elif event.type == MOUSEBUTTONDOWN:
                if event.button == 1 and pygame.key.get_mods() & KMOD_CTRL:  # Ctrl + Left Click for panning
                    panning = True
                    pan_start_pos = pygame.mouse.get_pos()
                elif event.button == 4:  # Mouse wheel up
                    scale_factor *= 1.1
                elif event.button == 5:  # Mouse wheel down
                    scale_factor /= 1.1
            elif event.type == MOUSEBUTTONUP:
                if event.button == 1:  # Stop panning on mouse release
                    panning = False
            elif event.type == MOUSEMOTION and panning:
                mouse_x, mouse_y = pygame.mouse.get_pos()
                pan_offset[0] += (mouse_x - pan_start_pos[0])
                pan_offset[1] += (mouse_y - pan_start_pos[1])
                pan_start_pos = (mouse_x, mouse_y)

        # Reset paths if the reference body changes
        if reference_body != last_reference:
            for body in celestial_bodies:
                body.path.clear()  # Clear past positions
            last_reference = reference_body

        # Find the reference body
        reference = next((body for body in celestial_bodies if body.name == reference_body), None)
        if not reference:
            reference = celestial_bodies[0]  # Default to Sun

        # Update positions
        for body in celestial_bodies:
            if body.period != 0:  # Sun doesn't move
                body.update_position(time_step)

        # Get reference position (center of the screen)
        ref_screen_pos = (400 + pan_offset[0], 300 + pan_offset[1])
        ref_x, ref_y = reference.get_position(ref_screen_pos, scale_factor)

        # Draw paths and update positions
        for body in celestial_bodies:
            if body.name != reference_body:
                # Position relative to reference body
                body_x, body_y = body.get_position(ref_screen_pos, scale_factor)
                rel_x = body_x - ref_x
                rel_y = body_y - ref_y

                # Add current position to path
                body.path.append((int(400 + rel_x), int(300 + rel_y)))

                # Draw the path
                if len(body.path) > 1:
                    pygame.draw.lines(screen, body.color, False, body.path, 1)

                # Draw the body with constant size
                pygame.draw.circle(screen, body.color, (int(400 + rel_x), int(300 + rel_y)), body.radius)

            else:
                # Draw the reference body with constant size
                pygame.draw.circle(screen, body.color, (400, 300), body.radius)

        # Display current reference frame
        text = font.render(f'Reference Frame: {reference_body}', True, (255, 255, 255))
        screen.blit(text, (10, 10))
        info_text = font.render('Press 1:Sun, 2:Mercury, 3:Venus, 4:Earth, 5:Mars', True, (255, 255, 255))
        screen.blit(info_text, (10, 30))

        pygame.display.flip()
        clock.tick(60)  # 60 FPS

    pygame.quit()
    sys.exit()

def main():
    screen = initialize_pygame()
    celestial_bodies = create_celestial_bodies()
    clock = pygame.time.Clock()
    simulation_loop(screen, celestial_bodies, clock)

if __name__ == "__main__":
    main()