import pygame
import random
import math

# 初始化 Pygame
pygame.init()

# 游戏配置
WIDTH, HEIGHT = 800, 600
FPS = 60
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
RED = (255, 50, 50)
GREEN = (50, 255, 50)
BLUE = (50, 100, 255)
YELLOW = (255, 255, 50)
GRAY = (100, 100, 100)
DARK_GRAY = (50, 50, 50)
BROWN = (139, 69, 19)

# 创建窗口
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("2D 赛车游戏")
clock = pygame.time.Clock()
font = pygame.font.Font(None, 36)
big_font = pygame.font.Font(None, 72)

class Car:
    """赛车类"""
    def __init__(self, x, y, color=RED):
        self.x = x
        self.y = y
        self.width = 40
        self.height = 60
        self.color = color
        self.speed = 0
        self.max_speed = 8
        self.acceleration = 0.2
        self.deceleration = 0.1
        self.angle = 0  # 角度（度）
        self.turn_speed = 4
        self.drift = 0
        self.drift_decay = 0.95
        self.lives = 3
        
    def update(self, keys):
        # 加速
        if keys[pygame.K_UP] or keys[pygame.K_w]:
            self.speed = min(self.speed + self.acceleration, self.max_speed)
        # 减速/倒车
        elif keys[pygame.K_DOWN] or keys[pygame.K_s]:
            self.speed = max(self.speed - self.acceleration, -self.max_speed * 0.5)
        else:
            # 自然减速
            if self.speed > 0:
                self.speed = max(self.speed - self.deceleration, 0)
            elif self.speed < 0:
                self.speed = min(self.speed + self.deceleration, 0)
        
        # 转向（只在移动时转向）
        if abs(self.speed) > 0.5:
            if keys[pygame.K_LEFT] or keys[pygame.K_a]:
                self.angle += self.turn_speed * (self.speed / self.max_speed)
                self.drift += 0.3
            if keys[pygame.K_RIGHT] or keys[pygame.K_d]:
                self.angle -= self.turn_speed * (self.speed / self.max_speed)
                self.drift -= 0.3
        
        # 更新漂移
        self.drift *= self.drift_decay
        
        # 更新位置
        rad = math.radians(self.angle)
        self.x += math.sin(rad) * self.speed
        self.y -= math.cos(rad) * self.speed
        
        # 边界检查
        self.x = max(self.width/2, min(self.x, WIDTH - self.width/2))
        self.y = max(self.height/2, min(self.y, HEIGHT - self.height/2))
    
    def draw(self, surface):
        # 创建赛车表面
        car_surface = pygame.Surface((self.width, self.height), pygame.SRCALPHA)
        
        # 车身
        pygame.draw.rect(car_surface, self.color, (5, 0, 30, 60), border_radius=5)
        
        # 车窗
        pygame.draw.rect(car_surface, (100, 200, 255), (8, 5, 24, 20), border_radius=3)
        
        # 车轮
        pygame.draw.rect(car_surface, BLACK, (0, 8, 6, 15))
        pygame.draw.rect(car_surface, BLACK, (0, 37, 6, 15))
        pygame.draw.rect(car_surface, BLACK, (34, 8, 6, 15))
        pygame.draw.rect(car_surface, BLACK, (34, 37, 6, 15))
        
        # 车灯
        pygame.draw.rect(car_surface, YELLOW, (10, 0, 8, 4))
        pygame.draw.rect(car_surface, YELLOW, (22, 0, 8, 4))
        
        # 尾灯
        pygame.draw.rect(car_surface, (255, 0, 0), (10, 56, 8, 4))
        pygame.draw.rect(car_surface, (255, 0, 0), (22, 56, 8, 4))
        
        # 旋转赛车
        rotated_car = pygame.transform.rotate(car_surface, self.angle)
        rect = rotated_car.get_rect(center=(self.x, self.y))
        surface.blit(rotated_car, rect.topleft)
        
        # 绘制漂移效果
        if abs(self.drift) > 0.5:
            for i in range(2):
                offset_x = random.randint(-10, 10) + math.sin(math.radians(self.angle)) * 20
                offset_y = random.randint(-10, 10) - math.cos(math.radians(self.angle)) * 20
                smoke = pygame.Surface((8, 8), pygame.SRCALPHA)
                pygame.draw.circle(smoke, (200, 200, 200, 100), (4, 4), 4)
                surface.blit(smoke, (self.x + offset_x - 4, self.y + offset_y - 4))

class Obstacle:
    """障碍物类"""
    def __init__(self, x, y, obstacle_type="barrel"):
        self.x = x
        self.y = y
        self.type = obstacle_type
        
        if obstacle_type == "barrel":
            self.radius = 15
            self.color = (255, 140, 0)
        elif obstacle_type == "cone":
            self.radius = 12
            self.color = (255, 200, 0)
        elif obstacle_type == "oil":
            self.radius = 25
            self.color = (20, 20, 20)
    
    def draw(self, surface):
        if self.type == "barrel":
            pygame.draw.circle(surface, self.color, (int(self.x), int(self.y)), self.radius)
            pygame.draw.circle(surface, (200, 100, 0), (int(self.x), int(self.y)), self.radius - 3)
            # 桶的条纹
            pygame.draw.line(surface, BLACK, (self.x - self.radius, self.y), (self.x + self.radius, self.y), 2)
        elif self.type == "cone":
            points = [
                (self.x, self.y - self.radius),
                (self.x - self.radius, self.y + self.radius * 0.7),
                (self.x + self.radius, self.y + self.radius * 0.7)
            ]
            pygame.draw.polygon(surface, self.color, points)
            pygame.draw.polygon(surface, (200, 150, 0), points, 2)
        elif self.type == "oil":
            pygame.draw.circle(surface, self.color, (int(self.x), int(self.y)), self.radius)
            pygame.draw.circle(surface, (40, 40, 40), (int(self.x), int(self.y)), self.radius - 3)
            # 油光效果
            for _ in range(3):
                ox = self.x + random.randint(-10, 10)
                oy = self.y + random.randint(-10, 10)
                pygame.draw.circle(surface, (60, 60, 60, 50), (int(ox), int(oy)), 3)

class Track:
    """赛道类"""
    def __init__(self):
        self.checkpoints = []
        self.current_checkpoint = 0
        self.lap = 0
        self.total_checkpoints = 8
        self.create_checkpoints()
        
    def create_checkpoints(self):
        # 创建环形赛道的检查点
        cx, cy = WIDTH // 2, HEIGHT // 2
        radius = 200
        for i in range(self.total_checkpoints):
            angle = (2 * math.pi * i) / self.total_checkpoints - math.pi / 2
            x = cx + radius * math.cos(angle)
            y = cy + radius * math.sin(angle)
            self.checkpoints.append((x, y))
    
    def draw(self, surface):
        # 绘制赛道背景
        pygame.draw.circle(surface, DARK_GRAY, (WIDTH//2, HEIGHT//2), 300)
        pygame.draw.circle(surface, (80, 80, 80), (WIDTH//2, HEIGHT//2), 280)
        pygame.draw.circle(surface, GRAY, (WIDTH//2, HEIGHT//2), 260)
        
        # 绘制赛道标记
        for i in range(len(self.checkpoints)):
            x, y = self.checkpoints[i]
            # 检查点标记
            if i == self.current_checkpoint:
                color = GREEN
                radius = 12
            else:
                color = WHITE
                radius = 8
            pygame.draw.circle(surface, color, (int(x), int(y)), radius, 2)
            
            # 连接线
            next_i = (i + 1) % len(self.checkpoints)
            next_x, next_y = self.checkpoints[next_i]
            pygame.draw.line(surface, (60, 60, 60), (x, y), (next_x, next_y), 2)

class Particle:
    """粒子效果类"""
    def __init__(self, x, y, color):
        self.x = x
        self.y = y
        self.color = color
        self.vx = random.uniform(-3, 3)
        self.vy = random.uniform(-3, 3)
        self.life = 30
        self.size = random.randint(2, 6)
    
    def update(self):
        self.x += self.vx
        self.y += self.vy
        self.life -= 1
        self.size = max(0, self.size - 0.1)
    
    def draw(self, surface):
        if self.life > 0:
            alpha = int(255 * (self.life / 30))
            color = (*self.color[:3], alpha)
            particle_surface = pygame.Surface((int(self.size*2), int(self.size*2)), pygame.SRCALPHA)
            pygame.draw.circle(particle_surface, color, (int(self.size), int(self.size)), int(self.size))
            surface.blit(particle_surface, (int(self.x - self.size), int(self.y - self.size)))

class Game:
    """游戏主类"""
    def __init__(self):
        self.car = Car(WIDTH // 2, HEIGHT // 2 + 100, RED)
        self.track = Track()
        self.obstacles = []
        self.particles = []
        self.score = 0
        self.best_score = 0
        self.game_over = False
        self.game_started = False
        self.crash_timer = 0
        self.create_obstacles()
    
    def create_obstacles(self):
        """创建障碍物"""
        self.obstacles = []
        # 在赛道上随机放置障碍物
        for _ in range(6):
            angle = random.uniform(0, 2 * math.pi)
            dist = random.uniform(150, 250)
            x = WIDTH//2 + dist * math.cos(angle)
            y = HEIGHT//2 + dist * math.sin(angle)
            obstacle_type = random.choice(["barrel", "cone", "oil"])
            self.obstacles.append(Obstacle(x, y, obstacle_type))
    
    def check_collision(self, car, obstacle):
        """检测碰撞"""
        dx = car.x - obstacle.x
        dy = car.y - obstacle.y
        distance = math.sqrt(dx*dx + dy*dy)
        return distance < (car.width/2 + obstacle.radius)
    
    def check_checkpoint(self, car):
        """检查是否通过检查点"""
        if len(self.track.checkpoints) == 0:
            return
        
        cx, cy = self.track.checkpoints[self.track.current_checkpoint]
        dx = car.x - cx
        dy = car.y - cy
        distance = math.sqrt(dx*dx + dy*dy)
        
        if distance < 40:
            self.track.current_checkpoint += 1
            if self.track.current_checkpoint >= self.track.total_checkpoints:
                self.track.current_checkpoint = 0
                self.track.lap += 1
                self.score += 1000 * (self.track.lap)
                # 圈数奖励粒子效果
                for _ in range(30):
                    self.particles.append(Particle(car.x, car.y, (255, 215, 0)))
            else:
                self.score += 100
    
    def handle_crash(self, car, obstacle):
        """处理碰撞"""
        if obstacle.type == "oil":
            # 油渍让车打滑
            car.drift += random.uniform(-2, 2)
            car.speed *= 0.7
            self.score = max(0, self.score - 50)
        else:
            # 碰撞障碍物
            car.lives -= 1
            car.speed *= 0.3
            self.score = max(0, self.score - 200)
            self.crash_timer = 30
            
            # 碰撞粒子效果
            for _ in range(20):
                self.particles.append(Particle(car.x, car.y, (255, 100, 100)))
            
            if car.lives <= 0:
                self.game_over = True
                self.best_score = max(self.best_score, self.score)
    
    def update(self):
        if self.game_over or not self.game_started:
            return
        
        keys = pygame.key.get_pressed()
        self.car.update(keys)
        
        # 检查检查点
        self.check_checkpoint(self.car)
        
        # 检查碰撞
        for obstacle in self.obstacles:
            if self.check_collision(self.car, obstacle):
                self.handle_crash(self.car, obstacle)
                # 把障碍物移到新位置
                angle = random.uniform(0, 2 * math.pi)
                dist = random.uniform(150, 250)
                obstacle.x = WIDTH//2 + dist * math.cos(angle)
                obstacle.y = HEIGHT//2 + dist * math.sin(angle)
                obstacle.type = random.choice(["barrel", "cone", "oil"])
        
        # 更新粒子
        for particle in self.particles[:]:
            particle.update()
            if particle.life <= 0:
                self.particles.remove(particle)
        
        # 更新碰撞闪烁效果
        if self.crash_timer > 0:
            self.crash_timer -= 1
        
        # 计分（基于速度和时间）
        self.score += abs(self.car.speed) * 0.1
    
    def draw(self, surface):
        # 绘制背景
        surface.fill((40, 40, 40))
        
        # 绘制草地纹理
        for _ in range(50):
            gx = random.randint(0, WIDTH)
            gy = random.randint(0, HEIGHT)
            pygame.draw.circle(surface, (60, 100, 60), (gx, gy), 20)
        
        # 绘制赛道
        self.track.draw(surface)
        
        # 绘制障碍物
        for obstacle in self.obstacles:
            obstacle.draw(surface)
        
        # 绘制粒子
        for particle in self.particles:
            particle.draw(surface)
        
        # 绘制赛车（碰撞时闪烁）
        if self.crash_timer <= 0 or self.crash_timer % 4 < 2:
            self.car.draw(surface)
        
        # 绘制UI
        self.draw_ui(surface)
        
        # 绘制开始/结束画面
        if not self.game_started:
            self.draw_start_screen(surface)
        elif self.game_over:
            self.draw_game_over_screen(surface)
    
    def draw_ui(self, surface):
        # 分数
        score_text = font.render(f"Score: {int(self.score)}", True, WHITE)
        surface.blit(score_text, (10, 10))
        
        # 最高分
        best_text = font.render(f"Best: {int(self.best_score)}", True, YELLOW)
        surface.blit(best_text, (10, 50))
        
        # 生命值
        lives_text = font.render(f"Lives: {'❤' * self.car.lives}", True, RED)
        surface.blit(lives_text, (WIDTH - 150, 10))
        
        # 圈数
        lap_text = font.render(f"Lap: {self.track.lap}", True, GREEN)
        surface.blit(lap_text, (WIDTH - 150, 50))
        
        # 速度表
        speed = abs(self.car.speed)
        speed_text = font.render(f"Speed: {int(speed * 15)} km/h", True, WHITE)
        surface.blit(speed_text, (WIDTH // 2 - 80, 10))
        
        # 检查点进度
        progress = self.track.current_checkpoint / self.track.total_checkpoints
        bar_width = 200
        bar_height = 10
        bar_x = WIDTH // 2 - bar_width // 2
        bar_y = 50
        pygame.draw.rect(surface, DARK_GRAY, (bar_x, bar_y, bar_width, bar_height))
        pygame.draw.rect(surface, GREEN, (bar_x, bar_y, bar_width * progress, bar_height))
    
    def draw_start_screen(self, surface):
        overlay = pygame.Surface((WIDTH, HEIGHT), pygame.SRCALPHA)
        overlay.fill((0, 0, 0, 180))
        surface.blit(overlay, (0, 0))
        
        title = big_font.render("2D RACING", True, YELLOW)
        surface.blit(title, (WIDTH//2 - title.get_width()//2, HEIGHT//2 - 100))
        
        instructions = [
            "Press SPACE to Start",
            "",
            "Controls:",
            "W/↑ - Accelerate",
            "S/↓ - Brake/Reverse",
            "A/← - Turn Left",
            "D/→ - Turn Right",
        ]
        
        for i, text in enumerate(instructions):
            color = WHITE if i > 0 else GREEN
            text_surface = font.render(text, True, color)
            surface.blit(text_surface, (WIDTH//2 - text_surface.get_width()//2, 
                                      HEIGHT//2 - 20 + i * 35))
    
    def draw_game_over_screen(self, surface):
        overlay = pygame.Surface((WIDTH, HEIGHT), pygame.SRCALPHA)
        overlay.fill((0, 0, 0, 200))
        surface.blit(overlay, (0, 0))
        
        game_over_text = big_font.render("GAME OVER", True, RED)
        surface.blit(game_over_text, (WIDTH//2 - game_over_text.get_width()//2, HEIGHT//2 - 100))
        
        final_score = font.render(f"Final Score: {int(self.score)}", True, WHITE)
        surface.blit(final_score, (WIDTH//2 - final_score.get_width()//2, HEIGHT//2))
        
        best = font.render(f"Best Score: {int(self.best_score)}", True, YELLOW)
        surface.blit(best, (WIDTH//2 - best.get_width()//2, HEIGHT//2 + 50))
        
        restart = font.render("Press SPACE to Restart", True, GREEN)
        surface.blit(restart, (WIDTH//2 - restart.get_width()//2, HEIGHT//2 + 120))
    
    def reset(self):
        """重置游戏"""
        self.car = Car(WIDTH // 2, HEIGHT // 2 + 100, RED)
        self.track = Track()
        self.obstacles = []
        self.particles = []
        self.score = 0
        self.game_over = False
        self.crash_timer = 0
        self.create_obstacles()

# 主游戏循环
def main():
    game = Game()
    running = True
    
    while running:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                running = False
            
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_SPACE:
                    if not game.game_started:
                        game.game_started = True
                    elif game.game_over:
                        game.reset()
                
                if event.key == pygame.K_ESCAPE:
                    if game.game_started and not game.game_over:
                        game.game_started = False
        
        game.update()
        game.draw(screen)
        
        pygame.display.flip()
        clock.tick(FPS)
    
    pygame.quit()

if __name__ == "__main__":
    main()