import pygame
import sys
import random
import math

# Initialize Pygame
pygame.init()

# Screen dimensions
WIDTH, HEIGHT = 800, 600
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("Endless Mountain with Car Physics")

# Clock for controlling frame rate
clock = pygame.time.Clock()
FPS = 60

# Colors
WHITE = (255, 255, 255)
GREEN = (34, 139, 34)
BLUE = (70, 130, 180)
BLACK = (0, 0, 0)
RED = (220, 20, 60)
GRAY = (169, 169, 169)

# Physics constants
GRAVITY = 0.5
FRICTION = 0.02
CAR_ACC = 0.1
CAR_MAX_SPEED = 10
WHEEL_RADIUS = 15

# Mountain settings
INITIAL_CURVES = 10  # Initial number of curves on the mountain
MIN_CURVES = 2
MAX_CURVES = 20

class Mountain:
    def __init__(self, num_curves):
        self.num_curves = num_curves
        self.step = WIDTH // self.num_curves  # Define step as an instance attribute
        self.points = []
        self.generate_initial_mountain()

    def generate_initial_mountain(self):
        self.points = []
        for i in range(self.num_curves + 2):
            x = i * self.step
            y = HEIGHT // 2 + random.randint(-100, 100)
            self.points.append([x, y])

    def update(self, speed):
        # Move all points to the left based on speed
        for point in self.points:
            point[0] -= speed

        # Remove points that are off-screen
        while self.points and self.points[0][0] < -self.step:
            self.points.pop(0)

        # Add new points to the right if needed
        while self.points[-1][0] < WIDTH + self.step:
            last_x, last_y = self.points[-1]
            new_x = last_x + self.step
            # Ensure the new y is not too steep
            new_y = last_y + random.randint(-50, 50)
            new_y = max(HEIGHT // 2 - 200, min(HEIGHT - 50, new_y))
            self.points.append([new_x, new_y])

    def draw(self, surface):
        pygame.draw.polygon(surface, GREEN, self.points + [[self.points[-1][0], HEIGHT], [self.points[0][0], HEIGHT]])

    def get_height_at(self, x):
        # Find two points between which x lies
        for i in range(len(self.points) - 1):
            if self.points[i][0] <= x <= self.points[i+1][0]:
                # Linear interpolation
                x1, y1 = self.points[i]
                x2, y2 = self.points[i+1]
                if x2 - x1 == 0:
                    return y1
                t = (x - x1) / (x2 - x1)
                return y1 + t * (y2 - y1)
        return HEIGHT  # Fallback

    def increase_curves(self):
        if self.num_curves < MAX_CURVES:
            self.num_curves += 1
            self.step = WIDTH // self.num_curves  # Update step
            self.regenerate()

    def decrease_curves(self):
        if self.num_curves > MIN_CURVES:
            self.num_curves -= 1
            self.step = WIDTH // self.num_curves  # Update step
            self.regenerate()

    def regenerate(self):
        # Regenerate mountain points based on new number of curves
        self.generate_initial_mountain()

class Wheel:
    def __init__(self, x, y):
        self.x = x
        self.y = y
        self.vy = 0
        self.rotation = 0  # For visual rotation
        self.speed = 0  # Rotation speed

    def update(self, terrain_height):
        # Apply gravity
        self.vy += GRAVITY

        # Update vertical position
        self.y += self.vy

        # Collision with terrain
        if self.y + WHEEL_RADIUS >= terrain_height:
            self.y = terrain_height - WHEEL_RADIUS
            self.vy = 0
            # Apply friction
            if self.speed > 0:
                self.speed -= FRICTION
                if self.speed < 0:
                    self.speed = 0
            elif self.speed < 0:
                self.speed += FRICTION
                if self.speed > 0:
                    self.speed = 0

        # Update rotation based on speed
        self.rotation += self.speed
        self.rotation %= 360  # Keep rotation within 0-359 degrees

    def draw(self, surface):
        # Draw wheel
        pygame.draw.circle(surface, GRAY, (int(self.x), int(self.y)), WHEEL_RADIUS)
        # Draw wheel rotation (a line from center to edge)
        end_x = self.x + WHEEL_RADIUS * math.cos(math.radians(self.rotation))
        end_y = self.y + WHEEL_RADIUS * math.sin(math.radians(self.rotation))
        pygame.draw.line(surface, BLACK, (self.x, self.y), (end_x, end_y), 2)

class Car:
    def __init__(self, mountain):
        self.mountain = mountain
        self.body_width = 60
        self.body_height = 30
        self.body_x = WIDTH // 4  # Fixed horizontal position
        self.body_y = 0  # To be calculated based on wheels
        self.vx = 0  # Horizontal velocity (influence scroll_speed)
        self.scroll_speed = 2  # Initial scroll speed

        # Initialize wheels relative to body
        self.wheel_offset_x = self.body_width // 2 - WHEEL_RADIUS
        self.wheel_offset_y = self.body_height // 2 + WHEEL_RADIUS
        # Initial wheel positions
        terrain_height_left = self.mountain.get_height_at(self.body_x - self.wheel_offset_x)
        terrain_height_right = self.mountain.get_height_at(self.body_x + self.wheel_offset_x)
        self.left_wheel = Wheel(self.body_x - self.wheel_offset_x, terrain_height_left - WHEEL_RADIUS)
        self.right_wheel = Wheel(self.body_x + self.wheel_offset_x, terrain_height_right - WHEEL_RADIUS)

    def update(self, keys_pressed):
        # Handle user input for acceleration
        if keys_pressed[pygame.K_RIGHT]:
            self.vx += CAR_ACC
        if keys_pressed[pygame.K_LEFT]:
            self.vx -= CAR_ACC

        # Clamp velocity to max speed
        if self.vx > CAR_MAX_SPEED:
            self.vx = CAR_MAX_SPEED
        elif self.vx < -CAR_MAX_SPEED:
            self.vx = -CAR_MAX_SPEED

        # Update scroll speed based on car's horizontal velocity
        # Positive vx: car moving right (mountain scrolls left faster)
        # Negative vx: car moving left (mountain scrolls left slower or right)
        self.scroll_speed = max(1, 2 + self.vx)  # Ensure scroll_speed is at least 1

        # Update wheels
        terrain_height_left = self.mountain.get_height_at(self.left_wheel.x)
        terrain_height_right = self.mountain.get_height_at(self.right_wheel.x)

        # Apply the updated scroll_speed to mountain (handled externally)

        self.left_wheel.update(terrain_height_left)
        self.right_wheel.update(terrain_height_right)

        # Update body position based on wheels
        self.body_y = min(self.left_wheel.y, self.right_wheel.y) - self.body_height // 2 - WHEEL_RADIUS

    def draw(self, surface):
        # Draw body
        body_rect = pygame.Rect(
            self.body_x - self.body_width // 2,
            self.body_y - self.body_height // 2,
            self.body_width,
            self.body_height
        )
        pygame.draw.rect(surface, RED, body_rect)

        # Draw wheels
        self.left_wheel.draw(surface)
        self.right_wheel.draw(surface)

def main():
    mountain = Mountain(INITIAL_CURVES)
    car = Car(mountain)

    font = pygame.font.SysFont(None, 24)

    running = True
    while running:
        clock.tick(FPS)

        # Event handling
        keys_pressed = pygame.key.get_pressed()
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                running = False
            elif event.type == pygame.KEYDOWN:
                if event.key == pygame.K_UP:
                    mountain.increase_curves()
                elif event.key == pygame.K_DOWN:
                    mountain.decrease_curves()

        # Update car scroll speed based on car's velocity
        scroll_speed = car.scroll_speed

        # Update mountain and car
        mountain.update(scroll_speed)
        car.update(keys_pressed)

        # Clear screen
        screen.fill(BLUE)

        # Draw mountain
        mountain.draw(screen)

        # Draw car
        car.draw(screen)

        # Display number of curves and speed
        text = font.render(f"Number of Curves: {mountain.num_curves} (Up/Down to change)", True, BLACK)
        screen.blit(text, (10, 10))
        speed_text = font.render(f"Car Speed: {car.vx:.2f} (Left/Right to control)", True, BLACK)
        screen.blit(speed_text, (10, 30))

        # Update display
        pygame.display.flip()

    pygame.quit()
    sys.exit()

if __name__ == "__main__":
    main()

Add bend physic for car, provide full updated code