import pygame
import random
import sys
import math

# 初始化pygame
pygame.init()

# 游戏常量
SCREEN_WIDTH = 800
SCREEN_HEIGHT = 600
FPS = 60
PLAYER_WIDTH = 50
PLAYER_HEIGHT = 80
ENEMY_WIDTH = 50
ENEMY_HEIGHT = 80
LANE_WIDTH = 100
NUM_LANES = 4
ROAD_WIDTH = LANE_WIDTH * NUM_LANES
MIN_SPEED = 2
MAX_SPEED = 8
SPAWN_RATE = 60  # 帧数，敌人生成间隔
COIN_SIZE = 20
NITRO_SIZE = 30

# 颜色定义
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
BLUE = (0, 120, 255)
YELLOW = (255, 255, 0)
ORANGE = (255, 165, 0)
PURPLE = (128, 0, 128)
GRAY = (100, 100, 100)
LIGHT_GRAY = (200, 200, 200)
DARK_GRAY = (50, 50, 50)
DARK_GREEN = (0, 100, 0)
GRASS_COLOR = (0, 150, 0)
ROAD_COLOR = (60, 60, 60)
LINE_COLOR = (255, 255, 255)
SKY_BLUE = (135, 206, 235)
COIN_COLOR = (255, 215, 0)
NITRO_COLOR = (0, 200, 255)
SMOKE_COLOR = (150, 150, 150)


class PlayerCar:
    """玩家赛车"""

    def __init__(self):
        self.lane = NUM_LANES // 2  # 从中间车道开始
        self.x = (SCREEN_WIDTH - ROAD_WIDTH) // 2 + \
            self.lane * LANE_WIDTH + LANE_WIDTH // 2
        self.y = SCREEN_HEIGHT - 150
        self.width = PLAYER_WIDTH
        self.height = PLAYER_HEIGHT
        self.speed = 5
        self.max_speed = 10
        self.min_speed = 2
        self.acceleration = 0.2
        self.deceleration = 0.3
        self.color = BLUE
        self.score = 0
        self.coins = 0
        self.nitro = 100
        self.nitro_active = False
        self.nitro_timer = 0
        self.crash_timer = 0
        self.smoke_particles = []

    def update(self, keys):
        """更新玩家状态"""
        if self.crash_timer > 0:
            self.crash_timer -= 1
            return

        # 加速/减速
        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.deceleration, self.min_speed)

        # 左右移动
        if keys[pygame.K_LEFT] or keys[pygame.K_a]:
            self.move_left()
        if keys[pygame.K_RIGHT] or keys[pygame.K_d]:
            self.move_right()

        # 氮气加速
        if keys[pygame.K_SPACE] and self.nitro > 0 and not self.nitro_active:
            self.nitro_active = True
            self.nitro_timer = 120  # 2秒氮气时间

        # 更新氮气状态
        if self.nitro_active:
            self.nitro_timer -= 1
            self.speed = min(self.speed + 2, self.max_speed * 1.5)
            self.nitro -= 1
            if self.nitro_timer <= 0 or self.nitro <= 0:
                self.nitro_active = False

        # 氮气恢复
        if not self.nitro_active and self.nitro < 100:
            self.nitro += 0.2

        # 生成烟雾粒子
        if self.speed > 5 and random.random() < 0.3:
            self.smoke_particles.append({
                'x': self.x + random.randint(-20, 20),
                'y': self.y + self.height//2,
                'size': random.randint(3, 8),
                'life': random.randint(20, 40),
                'speed': random.uniform(0.5, 2)
            })

        # 更新烟雾粒子
        for particle in self.smoke_particles[:]:
            particle['life'] -= 1
            particle['y'] -= particle['speed']
            if particle['life'] <= 0:
                self.smoke_particles.remove(particle)

    def move_left(self):
        """向左换道"""
        if self.lane > 0:
            self.lane -= 1
            self.update_position()

    def move_right(self):
        """向右换道"""
        if self.lane < NUM_LANES - 1:
            self.lane += 1
            self.update_position()

    def update_position(self):
        """更新赛车位置"""
        road_left = (SCREEN_WIDTH - ROAD_WIDTH) // 2
        self.x = road_left + self.lane * LANE_WIDTH + LANE_WIDTH // 2

    def get_rect(self):
        """获取赛车矩形"""
        return pygame.Rect(
            self.x - self.width//2,
            self.y - self.height//2,
            self.width,
            self.height
        )

    def crash(self):
        """赛车碰撞"""
        self.crash_timer = 30
        self.speed *= 0.5
        self.nitro_active = False

    def draw(self, screen):
        """绘制赛车"""
        if self.crash_timer > 0 and self.crash_timer % 10 < 5:
            return  # 碰撞闪烁效果

        # 绘制赛车主体
        car_rect = pygame.Rect(
            self.x - self.width//2,
            self.y - self.height//2,
            self.width,
            self.height
        )

        # 车身
        body_color = self.color
        if self.nitro_active:
            # 氮气激活时的发光效果
            glow = (pygame.time.get_ticks() // 100) % 2
            if glow:
                body_color = (min(255, self.color[0] + 50),
                              min(255, self.color[1] + 50),
                              min(255, self.color[2] + 50))

        pygame.draw.rect(screen, body_color, car_rect)

        # 车窗
        window_rect = pygame.Rect(
            self.x - self.width//2 + 5,
            self.y - self.height//2 + 5,
            self.width - 10,
            25
        )
        pygame.draw.rect(screen, (200, 230, 255), window_rect)

        # 车灯
        pygame.draw.rect(screen, YELLOW, (self.x - self.width //
                         2, self.y - self.height//2, 8, 5))
        pygame.draw.rect(screen, YELLOW, (self.x + self.width //
                         2 - 8, self.y - self.height//2, 8, 5))

        # 尾灯
        pygame.draw.rect(screen, RED, (self.x - self.width//2,
                         self.y + self.height//2 - 5, 8, 5))
        pygame.draw.rect(screen, RED, (self.x + self.width //
                         2 - 8, self.y + self.height//2 - 5, 8, 5))

        # 车轮
        wheel_color = (30, 30, 30)
        # 前轮
        pygame.draw.rect(screen, wheel_color, (self.x -
                         self.width//2 - 3, self.y - 10, 6, 12))
        pygame.draw.rect(screen, wheel_color, (self.x +
                         self.width//2 - 3, self.y - 10, 6, 12))
        # 后轮
        pygame.draw.rect(screen, wheel_color, (self.x -
                         self.width//2 - 3, self.y + 10, 6, 12))
        pygame.draw.rect(screen, wheel_color, (self.x +
                         self.width//2 - 3, self.y + 10, 6, 12))

        # 车号
        font = pygame.font.Font(None, 24)
        number_text = font.render("P1", True, WHITE)
        screen.blit(number_text, (self.x - 10, self.y - 10))

        # 绘制烟雾
        for particle in self.smoke_particles:
            alpha = particle['life'] * 6
            pygame.draw.circle(screen, SMOKE_COLOR + (alpha,),
                               (int(particle['x']), int(particle['y'])), particle['size'])


class EnemyCar:
    """敌车"""

    def __init__(self, lane, speed=None):
        self.lane = lane
        road_left = (SCREEN_WIDTH - ROAD_WIDTH) // 2
        self.x = road_left + lane * LANE_WIDTH + LANE_WIDTH // 2
        self.y = -ENEMY_HEIGHT
        self.width = ENEMY_WIDTH
        self.height = ENEMY_HEIGHT
        self.speed = speed if speed else random.uniform(2, 6)
        self.colors = [RED, GREEN, PURPLE, ORANGE, (255, 105, 180)]
        self.color = random.choice(self.colors)
        self.passed = False

    def update(self, player_speed=0):
        """更新敌车位置"""
        self.y += self.speed + player_speed * 0.3

    def is_off_screen(self):
        """检查是否离开屏幕"""
        return self.y > SCREEN_HEIGHT + self.height

    def get_rect(self):
        """获取敌车矩形"""
        return pygame.Rect(
            self.x - self.width//2,
            self.y - self.height//2,
            self.width,
            self.height
        )

    def draw(self, screen):
        """绘制敌车"""
        car_rect = pygame.Rect(
            self.x - self.width//2,
            self.y - self.height//2,
            self.width,
            self.height
        )

        # 车身
        pygame.draw.rect(screen, self.color, car_rect)

        # 车窗
        window_rect = pygame.Rect(
            self.x - self.width//2 + 5,
            self.y - self.height//2 + 5,
            self.width - 10,
            20
        )
        pygame.draw.rect(screen, (230, 240, 255), window_rect)

        # 车灯
        pygame.draw.rect(screen, YELLOW, (self.x - self.width //
                         2, self.y - self.height//2, 6, 4))
        pygame.draw.rect(screen, YELLOW, (self.x + self.width //
                         2 - 6, self.y - self.height//2, 6, 4))


class Coin:
    """金币"""

    def __init__(self, lane):
        self.lane = lane
        road_left = (SCREEN_WIDTH - ROAD_WIDTH) // 2
        self.x = road_left + lane * LANE_WIDTH + LANE_WIDTH // 2
        self.y = -COIN_SIZE
        self.size = COIN_SIZE
        self.speed = 3
        self.rotation = 0

    def update(self, player_speed=0):
        """更新金币位置"""
        self.y += self.speed + player_speed * 0.3
        self.rotation += 5

    def is_off_screen(self):
        """检查是否离开屏幕"""
        return self.y > SCREEN_HEIGHT + self.size

    def get_rect(self):
        """获取金币矩形"""
        return pygame.Rect(
            self.x - self.size//2,
            self.y - self.size//2,
            self.size,
            self.size
        )

    def draw(self, screen):
        """绘制金币"""
        # 旋转的金币
        angle = math.radians(self.rotation)
        points = []
        for i in range(5):
            point_angle = angle + i * 2 * math.pi / 5
            x = self.x + math.cos(point_angle) * self.size//2
            y = self.y + math.sin(point_angle) * self.size//2
            points.append((x, y))

        pygame.draw.polygon(screen, COIN_COLOR, points)
        pygame.draw.circle(screen, (255, 200, 0),
                           (int(self.x), int(self.y)), self.size//4)


class NitroPower:
    """氮气道具"""

    def __init__(self, lane):
        self.lane = lane
        road_left = (SCREEN_WIDTH - ROAD_WIDTH) // 2
        self.x = road_left + lane * LANE_WIDTH + LANE_WIDTH // 2
        self.y = -NITRO_SIZE
        self.size = NITRO_SIZE
        self.speed = 3
        self.pulse = 0

    def update(self, player_speed=0):
        """更新位置"""
        self.y += self.speed + player_speed * 0.3
        self.pulse = (self.pulse + 5) % 360

    def is_off_screen(self):
        """检查是否离开屏幕"""
        return self.y > SCREEN_HEIGHT + self.size

    def get_rect(self):
        """获取矩形"""
        return pygame.Rect(
            self.x - self.size//2,
            self.y - self.size//2,
            self.size,
            self.size
        )

    def draw(self, screen):
        """绘制氮气道具"""
        pulse_size = self.size + math.sin(math.radians(self.pulse)) * 5
        pygame.draw.circle(screen, NITRO_COLOR, (int(
            self.x), int(self.y)), int(pulse_size//2))
        # 氮气标志
        font = pygame.font.Font(None, 20)
        nitro_text = font.render("N2O", True, WHITE)
        screen.blit(nitro_text, (self.x - 15, self.y - 10))


class Game:
    """游戏主类"""

    def __init__(self):
        self.screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
        pygame.display.set_caption("直线狂飙")
        self.clock = pygame.time.Clock()
        self.font = pygame.font.Font(None, 36)
        self.small_font = pygame.font.Font(None, 24)

        # 游戏对象
        self.player = PlayerCar()
        self.enemies = []
        self.coins = []
        self.nitro_powerups = []

        # 游戏状态
        self.running = True
        self.game_over = False
        self.score = 0
        self.high_score = 0
        self.distance = 0
        self.spawn_timer = 0
        self.road_scroll = 0

        # 加载音效（如果可用）
        self.sound_enabled = True

    def spawn_enemy(self):
        """生成敌车"""
        available_lanes = list(range(NUM_LANES))
        if self.enemies:
            # 避免在同一车道连续生成
            for enemy in self.enemies[-3:]:
                if enemy.lane in available_lanes:
                    available_lanes.remove(enemy.lane)

        if available_lanes:
            lane = random.choice(available_lanes)
            new_enemy = EnemyCar(lane)
            self.enemies.append(new_enemy)

    def spawn_coin(self):
        """生成金币"""
        lane = random.randint(0, NUM_LANES - 1)
        new_coin = Coin(lane)
        self.coins.append(new_coin)

    def spawn_nitro(self):
        """生成氮气道具"""
        if random.random() < 0.1:  # 10%概率生成氮气
            lane = random.randint(0, NUM_LANES - 1)
            new_nitro = NitroPower(lane)
            self.nitro_powerups.append(new_nitro)

    def check_collisions(self):
        """检测碰撞"""
        player_rect = self.player.get_rect()

        # 检查敌车碰撞
        for enemy in self.enemies:
            if player_rect.colliderect(enemy.get_rect()):
                self.player.crash()
                self.score = max(0, self.score - 50)

        # 检查金币收集
        for coin in self.coins[:]:
            if player_rect.colliderect(coin.get_rect()):
                self.coins.remove(coin)
                self.player.coins += 1
                self.score += 10

        # 检查氮气道具
        for nitro in self.nitro_powerups[:]:
            if player_rect.colliderect(nitro.get_rect()):
                self.nitro_powerups.remove(nitro)
                self.player.nitro = min(100, self.player.nitro + 30)
                self.score += 20

    def check_overtake(self):
        """检查超车"""
        for enemy in self.enemies:
            if not enemy.passed and enemy.y > self.player.y:
                enemy.passed = True
                self.score += 5

    def update(self):
        """更新游戏状态"""
        if self.game_over:
            return

        # 更新玩家
        keys = pygame.key.get_pressed()
        self.player.update(keys)

        # 更新距离
        self.distance += self.player.speed * 0.1

        # 道路滚动
        self.road_scroll = (self.road_scroll + self.player.speed) % 40

        # 生成新对象
        self.spawn_timer += 1
        if self.spawn_timer >= SPAWN_RATE:
            self.spawn_enemy()
            if random.random() < 0.3:  # 30%概率生成金币
                self.spawn_coin()
            self.spawn_nitro()
            self.spawn_timer = 0

        # 更新敌车
        for enemy in self.enemies[:]:
            enemy.update(self.player.speed)
            if enemy.is_off_screen():
                self.enemies.remove(enemy)

        # 更新金币
        for coin in self.coins[:]:
            coin.update(self.player.speed)
            if coin.is_off_screen():
                self.coins.remove(coin)

        # 更新氮气道具
        for nitro in self.nitro_powerups[:]:
            nitro.update(self.player.speed)
            if nitro.is_off_screen():
                self.nitro_powerups.remove(nitro)

        # 碰撞检测
        self.check_collisions()
        self.check_overtake()

        # 更新最高分
        if self.score > self.high_score:
            self.high_score = self.score

    def draw_road(self):
        """绘制道路"""
        road_left = (SCREEN_WIDTH - ROAD_WIDTH) // 2

        # 绘制草地
        pygame.draw.rect(self.screen, GRASS_COLOR,
                         (0, 0, road_left, SCREEN_HEIGHT))
        pygame.draw.rect(self.screen, GRASS_COLOR,
                         (road_left + ROAD_WIDTH, 0, road_left, SCREEN_HEIGHT))

        # 绘制道路
        pygame.draw.rect(self.screen, ROAD_COLOR,
                         (road_left, 0, ROAD_WIDTH, SCREEN_HEIGHT))

        # 绘制车道线
        for i in range(1, NUM_LANES):
            x = road_left + i * LANE_WIDTH
            for y in range(-40, SCREEN_HEIGHT, 80):
                if (y + int(self.road_scroll)) % 80 < 40:  # 虚线
                    pygame.draw.line(self.screen, LINE_COLOR,
                                     (x, y), (x, y + 40), 3)

        # 绘制道路边缘
        pygame.draw.line(self.screen, WHITE, (road_left, 0),
                         (road_left, SCREEN_HEIGHT), 5)
        pygame.draw.line(self.screen, WHITE, (road_left + ROAD_WIDTH, 0),
                         (road_left + ROAD_WIDTH, SCREEN_HEIGHT), 5)

    def draw_hud(self):
        """绘制HUD"""
        # 分数
        score_text = self.font.render(f"分数: {self.score}", True, YELLOW)
        self.screen.blit(score_text, (20, 20))

        # 最高分
        high_score_text = self.small_font.render(
            f"最高分: {self.high_score}", True, YELLOW)
        self.screen.blit(high_score_text, (20, 60))

        # 金币
        coin_text = self.font.render(
            f"金币: {self.player.coins}", True, COIN_COLOR)
        self.screen.blit(coin_text, (20, 100))

        # 速度
        speed_text = self.font.render(
            f"速度: {int(self.player.speed * 20)}", True, YELLOW)
        self.screen.blit(speed_text, (SCREEN_WIDTH - 200, 20))

        # 距离
        distance_text = self.small_font.render(
            f"距离: {int(self.distance)}m", True, WHITE)
        self.screen.blit(distance_text, (SCREEN_WIDTH - 200, 60))

        # 氮气条
        nitro_text = self.small_font.render("氮气:", True, WHITE)
        self.screen.blit(nitro_text, (SCREEN_WIDTH - 200, 100))
        nitro_width = 120
        nitro_fill = (self.player.nitro / 100) * nitro_width
        pygame.draw.rect(self.screen, DARK_GRAY,
                         (SCREEN_WIDTH - 80, 100, nitro_width, 20))
        nitro_color = NITRO_COLOR if self.player.nitro > 30 else RED
        pygame.draw.rect(self.screen, nitro_color,
                         (SCREEN_WIDTH - 80, 100, nitro_fill, 20))
        pygame.draw.rect(self.screen, WHITE,
                         (SCREEN_WIDTH - 80, 100, nitro_width, 20), 2)

        # 控制说明
        controls = [
            "方向键/WASD: 控制赛车",
            "空格: 氮气加速",
            "R: 重新开始",
            "ESC: 退出游戏"
        ]

        for i, text in enumerate(controls):
            control_text = self.small_font.render(text, True, WHITE)
            self.screen.blit(control_text, (SCREEN_WIDTH - 200, 150 + i * 25))

    def draw_game_over(self):
        """绘制游戏结束画面"""
        overlay = pygame.Surface((SCREEN_WIDTH, SCREEN_HEIGHT))
        overlay.set_alpha(180)
        overlay.fill(BLACK)
        self.screen.blit(overlay, (0, 0))

        game_over_text = self.font.render("游戏结束!", True, RED)
        score_text = self.font.render(f"最终分数: {self.score}", True, YELLOW)
        coins_text = self.font.render(
            f"收集金币: {self.player.coins}", True, COIN_COLOR)
        distance_text = self.font.render(
            f"行驶距离: {int(self.distance)}m", True, WHITE)
        restart_text = self.small_font.render("按 R 键重新开始", True, WHITE)

        self.screen.blit(game_over_text, (SCREEN_WIDTH//2 -
                         game_over_text.get_width()//2, SCREEN_HEIGHT//2 - 100))
        self.screen.blit(score_text, (SCREEN_WIDTH//2 -
                         score_text.get_width()//2, SCREEN_HEIGHT//2 - 50))
        self.screen.blit(coins_text, (SCREEN_WIDTH//2 -
                         coins_text.get_width()//2, SCREEN_HEIGHT//2))
        self.screen.blit(distance_text, (SCREEN_WIDTH//2 -
                         distance_text.get_width()//2, SCREEN_HEIGHT//2 + 50))
        self.screen.blit(restart_text, (SCREEN_WIDTH//2 -
                         restart_text.get_width()//2, SCREEN_HEIGHT//2 + 100))

    def handle_events(self):
        """处理事件"""
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                self.running = False
            elif event.type == pygame.KEYDOWN:
                if event.key == pygame.K_ESCAPE:
                    self.running = False
                elif event.key == pygame.K_r:
                    if self.game_over:
                        # 重新开始游戏
                        self.__init__()
                    else:
                        self.game_over = True

        return self.running

    def draw(self):
        """绘制游戏"""
        # 绘制背景
        self.screen.fill(SKY_BLUE)

        # 绘制道路
        self.draw_road()

        # 绘制金币
        for coin in self.coins:
            coin.draw(self.screen)

        # 绘制氮气道具
        for nitro in self.nitro_powerups:
            nitro.draw(self.screen)

        # 绘制敌车
        for enemy in self.enemies:
            enemy.draw(self.screen)

        # 绘制玩家
        self.player.draw(self.screen)

        # 绘制HUD
        self.draw_hud()

        # 游戏结束画面
        if self.game_over:
            self.draw_game_over()

    def run(self):
        """运行游戏主循环"""
        while self.running:
            self.running = self.handle_events()
            self.update()
            self.draw()
            pygame.display.flip()
            self.clock.tick(FPS)

        pygame.quit()
        sys.exit()


# 启动游戏
if __name__ == "__main__":
    try:
        game = Game()
        game.run()
    except Exception as e:
        print(f"游戏运行出错: {e}")
        import traceback
        traceback.print_exc()
        input("按Enter键退出...")
