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

# 初始化pygame
pygame.init()

# 游戏设置
SCREEN_WIDTH = 1024
SCREEN_HEIGHT = 768
FPS = 60

# 颜色定义
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
RED = (255, 50, 50)
GREEN = (50, 255, 50)
BLUE = (50, 100, 255)
GRAY = (100, 100, 100)
DARK_GRAY = (50, 50, 50)
YELLOW = (255, 255, 0)
ROAD_COLOR = (40, 40, 40)
GRASS_COLOR = (30, 120, 30)
SKY_COLOR = (135, 206, 235)

# 创建游戏窗口
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
pygame.display.set_caption("第一人称驾驶模拟器")
clock = pygame.time.Clock()

# 字体
try:
    font_small = pygame.font.Font(None, 24)
    font_medium = pygame.font.Font(None, 36)
    font_large = pygame.font.Font(None, 48)
except:
    font_small = pygame.font.SysFont("arial", 24)
    font_medium = pygame.font.SysFont("arial", 36)
    font_large = pygame.font.SysFont("arial", 48)

class Car:
    def __init__(self):
        self.x = 0
        self.y = 0
        self.z = 0
        self.speed = 0
        self.max_speed = 8  # 降低最大速度
        self.acceleration = 0.1  # 降低加速度
        self.deceleration = 0.2
        self.brake_power = 0.3
        self.steering = 0
        self.max_steering = 0.04  # 降低转向灵敏度
        self.steering_speed = 0.0015
        self.direction = 0
        self.width = 2
        self.lane = 0
        self.max_lane = 1
        self.lane_width = 4
        self.changing_lane = 0
        
    def update(self, keys):
        # 加速和减速
        if keys[K_UP] or keys[K_w]:
            self.speed += self.acceleration
        elif keys[K_DOWN] or keys[K_s]:
            self.speed -= self.brake_power
        # 限制速度
        self.speed = max(-self.max_speed * 0.5, min(self.speed, self.max_speed))
        
        # 转向控制
        target_steering = 0
        if keys[K_LEFT] or keys[K_a]:
            target_steering = -self.max_steering
        if keys[K_RIGHT] or keys[K_d]:
            target_steering = self.max_steering
            
        # 平滑转向
        if target_steering > self.steering:
            self.steering = min(target_steering, self.steering + self.steering_speed)
        elif target_steering < self.steering:
            self.steering = max(target_steering, self.steering - self.steering_speed)
        else:
            # 自动回正
            if self.steering > 0:
                self.steering = max(0, self.steering - self.steering_speed * 0.5)
            elif self.steering < 0:
                self.steering = min(0, self.steering + self.steering_speed * 0.5)
        
        # 换道控制
        if keys[K_q] and self.changing_lane == 0 and self.lane > -self.max_lane:
            self.changing_lane = -1
        if keys[K_e] and self.changing_lane == 0 and self.lane < self.max_lane:
            self.changing_lane = 1
            
        # 执行换道
        if self.changing_lane != 0:
            self.lane += self.changing_lane * 0.08  # 降低换道速度
            if abs(self.lane - round(self.lane)) < 0.05:
                self.lane = round(self.lane)
                self.changing_lane = 0
        
        # 更新位置和方向
        self.direction += self.steering * self.speed
        self.x += math.sin(self.direction) * self.speed
        self.z += math.cos(self.direction) * self.speed
        
        # 确保方向在0-2π范围内
        self.direction %= 2 * math.pi

class RoadSegment:
    def __init__(self, z, curve=0):
        self.z = z
        self.curve = curve
        
    def get_color(self, index):
        colors = [GRASS_COLOR, ROAD_COLOR, DARK_GRAY, ROAD_COLOR, GRASS_COLOR]
        return colors[index]

class Game:
    def __init__(self):
        self.car = Car()
        self.road_length = 200
        self.segment_length = 5
        self.road = []
        self.camera_height = 2
        self.draw_distance = 100
        self.fov = 100
        self.speedometer = 0
        self.score = 0
        self.time = 0
        self.game_over = False
        self.paused = False
        
        # 生成道路
        self.generate_road()
        
        # 创建一些道路上的物体 - 减少数量
        self.objects = []
        self.object_count = 10  # 减少物体数量
        for i in range(self.object_count):
            lane = random.choice([-1, 0, 1])
            z = random.randint(50, 800)  # 增加物体间距
            self.objects.append({
                'x': lane * self.car.lane_width,
                'z': z,
                'type': random.choice(['tree', 'cone', 'sign']),
                'color': random.choice([GREEN, YELLOW, RED, BLUE])
            })
    
    def generate_road(self):
        self.road = []
        curve = 0
        for i in range(self.road_length):
            z = i * self.segment_length
            # 降低道路弯曲程度
            if i % 30 == 0:  # 减少弯曲频率
                curve = random.uniform(-0.01, 0.01)  # 减少弯曲幅度
            self.road.append(RoadSegment(z, curve))
    
    def project(self, x, y, z, camera_x, camera_z, camera_depth):
        if z <= 0:
            z = 0.1
            
        scale = camera_depth / z
        screen_x = SCREEN_WIDTH / 2 + (x - camera_x) * scale
        screen_y = SCREEN_HEIGHT / 2 - y * scale
        
        return screen_x, screen_y, scale
    
    def draw_road(self):
        # 背景
        screen.fill(SKY_COLOR)
        pygame.draw.rect(screen, GRASS_COLOR, (0, SCREEN_HEIGHT//2, SCREEN_WIDTH, SCREEN_HEIGHT//2))
        
        # 找到最近的段
        start_pos = int(self.car.z / self.segment_length) % len(self.road)
        
        # 绘制道路
        road_width = 20
        for i in range(self.draw_distance, 0, -1):
            segment_index = (start_pos + i) % len(self.road)
            segment = self.road[segment_index]
            
            # 计算段的世界坐标
            segment_z = segment.z
            if segment_z < self.car.z:
                segment_z += len(self.road) * self.segment_length
            
            # 计算下一段
            next_segment_index = (segment_index + 1) % len(self.road)
            next_segment = self.road[next_segment_index]
            next_z = next_segment.z
            if next_z < self.car.z:
                next_z += len(self.road) * self.segment_length
            
            # 应用道路弯曲
            curve_offset1 = segment.curve * (segment_z - self.car.z) ** 2 / 100
            curve_offset2 = next_segment.curve * (next_z - self.car.z) ** 2 / 100
            
            # 计算道路边界
            x1 = -road_width + curve_offset1
            x2 = road_width + curve_offset1
            x3 = -road_width + curve_offset2
            x4 = road_width + curve_offset2
            
            # 投影到屏幕
            screen_x1, screen_y1, scale1 = self.project(
                x1, 0, segment_z - self.car.z, 
                self.car.x, self.car.z, 
                self.fov
            )
            screen_x2, screen_y2, scale2 = self.project(
                x2, 0, segment_z - self.car.z, 
                self.car.x, self.car.z, 
                self.fov
            )
            screen_x3, screen_y3, scale3 = self.project(
                x3, 0, next_z - self.car.z, 
                self.car.x, self.car.z, 
                self.fov
            )
            screen_x4, screen_y4, scale4 = self.project(
                x4, 0, next_z - self.car.z, 
                self.car.x, self.car.z, 
                self.fov
            )
            
            # 只绘制在屏幕内的道路段
            if (screen_y1 < SCREEN_HEIGHT and screen_y2 < SCREEN_HEIGHT and 
                screen_y3 < SCREEN_HEIGHT and screen_y4 < SCREEN_HEIGHT):
                
                # 道路主体
                pygame.draw.polygon(screen, ROAD_COLOR, [
                    (screen_x1, screen_y1),
                    (screen_x2, screen_y2),
                    (screen_x4, screen_y4),
                    (screen_x3, screen_y3)
                ])
                
                # 道路中线
                mid_x1 = (screen_x1 + screen_x2) / 2
                mid_x2 = (screen_x3 + screen_x4) / 2
                
                if i % 2 == 0:  # 虚线
                    pygame.draw.line(screen, YELLOW, 
                                    (mid_x1, screen_y1), 
                                    (mid_x2, screen_y3), 3)
                
                # 道路边线
                if i == 1:  # 只绘制最近的边线
                    pygame.draw.line(screen, WHITE, 
                                    (screen_x1, screen_y1), 
                                    (screen_x3, screen_y3), 3)
                    pygame.draw.line(screen, WHITE, 
                                    (screen_x2, screen_y2), 
                                    (screen_x4, screen_y4), 3)
        
        # 绘制物体
        for obj in self.objects:
            obj_z = obj['z']
            if obj_z < self.car.z:
                obj_z += 1000  # 简单循环
            
            distance = obj_z - self.car.z
            if 0 < distance < 100:  # 只绘制前方的物体
                x = obj['x']
                car_lane_offset = self.car.lane * self.car.lane_width
                
                obj_x, obj_y, scale = self.project(
                    x - car_lane_offset, 1, distance,
                    self.car.x, self.car.z,
                    self.fov
                )
                
                if 0 < obj_y < SCREEN_HEIGHT and 0 < obj_x < SCREEN_WIDTH:
                    size = 20 * scale
                    if size < 0.5:  # 太小的物体不绘制
                        continue
                        
                    if obj['type'] == 'tree':
                        pygame.draw.circle(screen, obj['color'], (int(obj_x), int(obj_y)), int(size))
                    elif obj['type'] == 'cone':
                        pygame.draw.polygon(screen, obj['color'], [
                            (obj_x, obj_y),
                            (obj_x - size/2, obj_y + size),
                            (obj_x + size/2, obj_y + size)
                        ])
                    else:  # sign
                        pygame.draw.rect(screen, obj['color'], 
                                        (obj_x - size/2, obj_y - size/2, size, size))
    
    def draw_ui(self):
        # 速度表
        speed = abs(self.car.speed * 20)  # 转换为km/h
        speed_text = font_large.render(f"{int(speed)} km/h", True, WHITE)
        screen.blit(speed_text, (30, 30))
        
        # 档位指示器
        gear = "D" if self.car.speed >= 0 else "R"
        gear_text = font_medium.render(f"档位: {gear}", True, WHITE)
        screen.blit(gear_text, (30, 90))
        
        # 方向指示器
        dir_angle = self.car.direction * 180 / math.pi
        dir_text = font_medium.render(f"方向: {int(dir_angle)}°", True, WHITE)
        screen.blit(dir_text, (30, 130))
        
        # 车道指示
        lane_text = font_medium.render(f"车道: {int(self.car.lane + 2)}", True, WHITE)
        screen.blit(lane_text, (30, 170))
        
        # 分数
        score_text = font_medium.render(f"分数: {int(self.score)}", True, WHITE)
        screen.blit(score_text, (SCREEN_WIDTH - 150, 30))
        
        # 时间
        time_text = font_medium.render(f"时间: {int(self.time)}s", True, WHITE)
        screen.blit(time_text, (SCREEN_WIDTH - 150, 70))
        
        # 控制说明
        controls = [
            "控制说明:",
            "W/↑: 加速",
            "S/↓: 减速/倒车",
            "A/←: 左转",
            "D/→: 右转",
            "Q/E: 换道",
            "P: 暂停/继续",
            "R: 重新开始",
            "ESC: 退出游戏"
        ]
        
        for i, text in enumerate(controls):
            control_text = font_small.render(text, True, WHITE)
            screen.blit(control_text, (SCREEN_WIDTH - 200, 120 + i * 25))
        
        # 游戏状态
        if self.game_over:
            overlay = pygame.Surface((SCREEN_WIDTH, SCREEN_HEIGHT), pygame.SRCALPHA)
            overlay.fill((0, 0, 0, 150))
            screen.blit(overlay, (0, 0))
            
            game_over_text = font_large.render("游戏结束!", True, RED)
            screen.blit(game_over_text, (SCREEN_WIDTH//2 - 100, SCREEN_HEIGHT//2 - 50))
            restart_text = font_medium.render("按R重新开始", True, WHITE)
            screen.blit(restart_text, (SCREEN_WIDTH//2 - 80, SCREEN_HEIGHT//2 + 20))
        
        if self.paused:
            overlay = pygame.Surface((SCREEN_WIDTH, SCREEN_HEIGHT), pygame.SRCALPHA)
            overlay.fill((0, 0, 0, 150))
            screen.blit(overlay, (0, 0))
            
            pause_text = font_large.render("游戏暂停", True, YELLOW)
            screen.blit(pause_text, (SCREEN_WIDTH//2 - 100, SCREEN_HEIGHT//2 - 50))
            continue_text = font_medium.render("按P继续游戏", True, WHITE)
            screen.blit(continue_text, (SCREEN_WIDTH//2 - 80, SCREEN_HEIGHT//2 + 20))
    
    def update(self, dt):
        if self.game_over or self.paused:
            return
            
        # 更新车辆
        keys = pygame.key.get_pressed()
        self.car.update(keys)
        
        # 更新时间和分数
        self.time += dt / 1000.0
        self.score += abs(self.car.speed) * dt / 1000.0
        
        # 检查碰撞
        for obj in self.objects:
            obj_z = obj['z']
            if obj_z < self.car.z:
                obj_z += 1000
                
            distance_z = abs(obj_z - self.car.z)
            distance_x = abs(obj['x'] - self.car.lane * self.car.lane_width)
            
            if distance_z < 5 and distance_x < 1.5:  # 略微增加碰撞距离
                self.game_over = True
                return
        
        # 更新物体位置
        for obj in self.objects:
            obj['z'] -= self.car.speed
            if obj['z'] < self.car.z - 50:
                obj['z'] += 1000  # 增加物体重新出现距离
                obj['x'] = random.choice([-1, 0, 1]) * self.car.lane_width
                obj['type'] = random.choice(['tree', 'cone', 'sign'])
                obj['color'] = random.choice([GREEN, YELLOW, RED, BLUE])
    
    def reset(self):
        self.__init__()
    
    def toggle_pause(self):
        self.paused = not self.paused
    
    def run(self):
        last_time = pygame.time.get_ticks()
        
        # 主游戏循环
        running = True
        while running:
            current_time = pygame.time.get_ticks()
            dt = current_time - last_time
            last_time = current_time
            
            # 事件处理
            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_r:
                        self.reset()
                    elif event.key == K_p:
                        self.toggle_pause()
            
            # 更新游戏状态
            self.update(dt)
            
            # 绘制游戏
            self.draw_road()
            self.draw_ui()
            
            # 更新屏幕
            pygame.display.flip()
            clock.tick(FPS)
        
        pygame.quit()
        sys.exit()

# 启动游戏
if __name__ == "__main__":
    try:
        game = Game()
        game.run()
    except Exception as e:
        print(f"游戏运行时出错: {e}")
        pygame.quit()