import pygame
import math
import random

# --- 初始化 ---
pygame.init()
WIDTH, HEIGHT = 800, 600
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("Pygame 3D赛车 - Retro OutRun Style")
clock = pygame.time.Clock()

# 颜色
SKY_COLOR = (100, 150, 255)
GRASS_COLOR = (50, 150, 50)
ROAD_COLOR = (80, 80, 80)
RUMBLE_COLOR = (200, 50, 50)
LANE_COLOR = (255, 255, 255)
CAR_COLOR = (200, 30, 30)

FONT = pygame.font.SysFont("arial", 30)

# --- 3D 投影参数 ---
CAMERA_HEIGHT = 1000
CAMERA_DEPTH = 1 / math.tan((80 / 2) * math.pi / 180)  # 80度FOV
ROAD_WIDTH = 2000
SEG_LENGTH = 200
DRAW_DIST = 150

# --- 赛道生成 ---
def build_road():
    road = []
    # 直道
    for _ in range(50): road.append(0)
    # 左弯
    for i in range(50): road.append(-math.sin(i / 50 * math.pi) * 4)
    # 直道
    for _ in range(50): road.append(0)
    # 右弯
    for i in range(50): road.append(math.sin(i / 50 * math.pi) * 6)
    # 连续S弯
    for i in range(100): road.append(math.sin(i / 20 * math.pi) * 3)
    return road

class Car:
    def __init__(self):
        self.x = 0  # -1 到 1，0是中心
        self.z = 0  # 前进距离
        self.speed = 0
        self.max_speed = SEG_LENGTH * 60
        self.accel = self.max_speed / 120
        self.brake = -self.max_speed / 60
        self.decel = -self.max_speed / 300
        self.off_road_decel = -self.max_speed / 60
        self.steer_speed = 3.0

    def update(self, keys, dt, road):
        # 输入
        if keys[pygame.K_UP]: self.speed += self.accel * dt
        elif keys[pygame.K_DOWN]: self.speed += self.brake * dt
        else: self.speed += self.decel * dt

        # 边界限制
        self.speed = max(0, min(self.speed, self.max_speed))

        # 转向
        steer = 0
        if keys[pygame.K_LEFT]: steer = -self.steer_speed
        if keys[pygame.K_RIGHT]: steer = self.steer_speed
        
        # 速度越快转向越明显，但也要考虑离心力
        self.x += steer * (self.speed / self.max_speed) * dt

        # 弯道离心力
        seg_idx = int(self.z / SEG_LENGTH) % len(road)
        curve = road[seg_idx]
        self.x -= curve * (self.speed / self.max_speed) * 0.01 * dt

        # 路边惩罚
        if abs(self.x) > 1.0:
            self.speed += self.off_road_decel * dt
            self.x = max(-2, min(2, self.x))  # 防止飞出太远

        # 前进
        self.z += self.speed * dt

# --- 3D 投影辅助 ---
def project(p, camera_x, camera_y, camera_z, camera_depth, width, height, road_width):
    # 简单透视投影
    trans_x = p[0] - camera_x
    trans_y = p[1] - camera_y
    trans_z = p[2] - camera_z
    
    if trans_z <= 0: return None
    
    scale = camera_depth / trans_z
    screen_x = width / 2 + scale * trans_x * width / 2
    screen_y = height / 2 - scale * trans_y * height / 2
    screen_w = scale * road_width * width / 2
    
    return (screen_x, screen_y, screen_w, scale)

# --- 主程序 ---
def main():
    car = Car()
    road = build_road()
    running = True
    
    while running:
        dt = clock.tick(60) / 1000.0  # 秒
        for event in pygame.event.get():
            if event.type == pygame.QUIT: running = False

        car.update(pygame.key.get_pressed(), dt, road)

        # --- 绘图 ---
        screen.fill(SKY_COLOR)
        
        # 画草地（下半屏）
        pygame.draw.rect(screen, GRASS_COLOR, (0, HEIGHT//2, WIDTH, HEIGHT//2))

        base_seg = int(car.z / SEG_LENGTH)
        base_percent = (car.z % SEG_LENGTH) / SEG_LENGTH
        
        # 累积曲线偏移
        x = 0
        dx = 0
        
        # 从远到近画
        segments = []
        for n in range(DRAW_DIST):
            idx = (base_seg + n) % len(road)
            curve = road[idx]
            
            # 世界坐标
            world_z = (n - base_percent) * SEG_LENGTH
            if world_z <= 0: continue
            
            # 透视投影
            scale = CAMERA_DEPTH / (world_z / CAMERA_HEIGHT)
            screen_y = HEIGHT / 2 + scale * CAMERA_HEIGHT * HEIGHT / 2
            screen_w = scale * ROAD_WIDTH * WIDTH / 2
            
            # 累积弯道偏移
            x += dx
            dx += curve
            
            screen_x = WIDTH / 2 + (x - car.x * ROAD_WIDTH / 2) * scale * WIDTH / 2
            
            segments.append({
                'y': screen_y,
                'w': screen_w,
                'x': screen_x,
                'idx': idx,
                'n': n
            })

        # 从后往前画（画家算法）
        for i in range(len(segments) - 1, 0, -1):
            s1 = segments[i]
            s2 = segments[i-1]
            
            if s1['y'] <= s2['y']: continue  # 被遮挡
            
            # 交替颜色
            alt = (s1['idx'] // 3) % 2
            road_col = ROAD_COLOR if alt else (70, 70, 70)
            rumble_col = RUMBLE_COLOR if alt else (255, 255, 255)
            grass_col = GRASS_COLOR if alt else (40, 130, 40)
            
            # 画草地
            pygame.draw.rect(screen, grass_col, (0, int(s2['y']), WIDTH, int(s1['y'] - s2['y'])))
            
            # 画路肩
            pygame.draw.polygon(screen, rumble_col, [
                (s2['x'] - s2['w'] * 1.1, s2['y']),
                (s2['x'] + s2['w'] * 1.1, s2['y']),
                (s1['x'] + s1['w'] * 1.1, s1['y']),
                (s1['x'] - s1['w'] * 1.1, s1['y'])
            ])
            
            # 画路面
            pygame.draw.polygon(screen, road_col, [
                (s2['x'] - s2['w'], s2['y']),
                (s2['x'] + s2['w'], s2['y']),
                (s1['x'] + s1['w'], s1['y']),
                (s1['x'] - s1['w'], s1['y'])
            ])
            
            # 画中线
            if alt:
                lw1 = max(2, s1['w'] * 0.02)
                lw2 = max(2, s2['w'] * 0.02)
                pygame.draw.polygon(screen, LANE_COLOR, [
                    (s2['x'] - lw2, s2['y']),
                    (s2['x'] + lw2, s2['y']),
                    (s1['x'] + lw1, s1['y']),
                    (s1['x'] - lw1, s1['y'])
                ])

        # 画玩家车
        steer_angle = 0
        if pygame.key.get_pressed()[pygame.K_LEFT]: steer_angle = -15
        if pygame.key.get_pressed()[pygame.K_RIGHT]: steer_angle = 15
        
        car_rect = pygame.Rect(WIDTH//2 - 30, HEIGHT - 120, 60, 80)
        pygame.draw.rect(screen, CAR_COLOR, car_rect)
        # 车窗
        pygame.draw.rect(screen, (100, 150, 255), (WIDTH//2 - 20, HEIGHT - 110, 40, 30))
        # 轮胎
        pygame.draw.rect(screen, (30, 30, 30), (WIDTH//2 - 35, HEIGHT - 100, 10, 40))
        pygame.draw.rect(screen, (30, 30, 30), (WIDTH//2 + 25, HEIGHT - 100, 10, 40))

        # UI
        speed_kmh = int(car.speed / car.max_speed * 300)
        spd_txt = FONT.render(f"Speed: {speed_kmh} km/h", True, (255, 255, 255))
        screen.blit(spd_txt, (20, 20))

        pygame.display.flip()

    pygame.quit()

if __name__ == "__main__":
    main()