import tkinter as tk
import math
import random

# ========================
# 全局配置
# ========================
WIDTH, HEIGHT = 900, 600
FPS = 60

# ========================
# 飞行状态（全部提前定义）
# ========================
pitch = 0.0
roll = 0.0
yaw = 0.0
speed = 0.0
altitude = 0.0
throttle = 0.5
fuel = 100.0
gear_down = True
flaps = 0
crashed = False
landed = False
on_ground = True
stall_warning = False
score = 0
mission_step = 0
combo = 0
distance = 0.0

# ========================
# 环境
# ========================
weather = "☀️ 晴天"
time_of_day = "day"

mission_steps = [
    "1️⃣ 起飞：油门推到 80%+，速度>60 时拉杆",
    "2️⃣ 爬升：保持仰角，爬升至 500m",
    "3️⃣ 转向：左转或右转 90°",
    "4️⃣ 巡航：高度 400~600m，速度 80~120",
    "5️⃣ 下降：缓慢降低高度至 100m",
    "6️⃣ 降落：对准跑道，放起落架，速度<40 触地"
]

# ========================
# Tkinter 窗口
# ========================
root = tk.Tk()
root.title("✈️ 飞行模拟器 · 完整封死版")
root.resizable(False, False)

main_canvas = tk.Canvas(root, width=WIDTH, height=HEIGHT, highlightthickness=0)
main_canvas.pack()

panel = tk.Frame(root)
panel.pack(fill="x")

info_label = tk.Label(panel, font=("Consolas", 10))
info_label.pack(side="left", padx=10)

task_label = tk.Label(panel, font=("Consolas", 9))
task_label.pack(side="left", padx=10)

# ========================
# 主题
# ========================
themes = {
    "🛫 经典驾驶舱": {"bg": "#2E3B4E", "fg": "#FFFFFF"},
    "🌙 夜间飞行": {"bg": "#0D1B2A", "fg": "#BBBBBB"},
    "🏜️ 沙漠空域": {"bg": "#D6B26A", "fg": "#3E2723"},
    "🏔️ 极地航线": {"bg": "#E3F2FD", "fg": "#0D47A1"},
    "🌳 丛林巡逻": {"bg": "#1B4332", "fg": "#D8F3DC"},
    "🌌 星空巡航": {"bg": "#02010A", "fg": "#E0E1DD"},
}

def apply_theme(name):
    t = themes[name]
    root.configure(bg=t["bg"])
    panel.configure(bg=t["bg"])
    info_label.configure(bg=t["bg"], fg=t["fg"])
    task_label.configure(bg=t["bg"], fg=t["fg"])
    draw_scene()

# ========================
# 天空（✅ 无半透明）
# ========================
def draw_sky():
    main_canvas.delete("sky")

    for y in range(HEIGHT):
        ratio = y / HEIGHT
        if time_of_day == "day":
            r = int(135 * (1 - ratio) + 30 * ratio)
            g = int(206 * (1 - ratio) + 144 * ratio)
            b = int(250 * (1 - ratio) + 255 * ratio)
        elif time_of_day == "night":
            r = int(10 * (1 - ratio) + 0 * ratio)
            g = int(20 * (1 - ratio) + 0 * ratio)
            b = int(50 * (1 - ratio) + 20 * ratio)
        else:
            r = int(255 * (1 - ratio) + 30 * ratio)
            g = int(150 * (1 - ratio) + 50 * ratio)
            b = int(50 * (1 - ratio) + 80 * ratio)

        main_canvas.create_line(0, y, WIDTH, y, fill=f"#{r:02x}{g:02x}{b:02x}", tags="sky")

    if time_of_day == "day":
        sx, sy = WIDTH * 0.8, HEIGHT * 0.25
        for r in range(50, 71, 5):
            main_canvas.create_oval(sx - r, sy - r, sx + r, sy + r,
                                    fill="#FFD700", outline="", tags="sky")
    elif time_of_day == "night":
        mx, my = WIDTH * 0.8, HEIGHT * 0.25
        main_canvas.create_oval(mx - 35, my - 35, mx + 35, my + 35,
                                fill="#FFF9C4", outline="", tags="sky")
        for _ in range(20):
            sx = random.randint(50, WIDTH - 50)
            sy = random.randint(50, 150)
            main_canvas.create_text(sx, sy, text="✦", fill="#FFFFFF", font=("", 10), tags="sky")

# ========================
# 地形
# ========================
def terrain_height(x):
    h = 100
    h += 30 * math.sin(x * 0.005)
    h += 15 * math.sin(x * 0.011)
    h += 8 * math.sin(x * 0.023)
    if 3500 < x < 3700:
        h -= 80
    return max(h, 20)

def draw_terrain():
    main_canvas.delete("terrain")
    cam_x = distance
    horizon = HEIGHT * 0.45

    for screen_x in range(0, WIDTH, 4):
        world_x = cam_x + (screen_x - WIDTH / 2) * 2.0
        h = terrain_height(world_x)
        scale = 300 / max(altitude + 50 - h, 10)
        screen_y = horizon + (h - altitude) * scale

        col = "#4CAF50" if h > 60 else "#8BC34A"
        if altitude - h < 30:
            col = "#795548"
        main_canvas.create_line(screen_x, screen_y, screen_x, HEIGHT,
                                fill=col, width=4, tags="terrain")

    rw = 2000
    if distance < rw:
        rh = terrain_height(distance + rw)
        scale = 300 / max(altitude + 50 - rh, 10)
        rs = horizon + (rh - altitude) * scale
        main_canvas.create_rectangle(0, rs, WIDTH, rs + 20,
                                     fill="#666666", outline="", tags="terrain")
        for i in range(0, WIDTH, 80):
            main_canvas.create_rectangle(i, rs + 5, i + 40, rs + 15,
                                         fill="#FFFFFF", outline="", tags="terrain")

# ========================
# 飞机
# ========================
def draw_plane():
    main_canvas.delete("plane")
    cx, cy = WIDTH // 2, HEIGHT // 2 + 40

    main_canvas.create_polygon(
        cx, cy - 40,
        cx + 10, cy + 20,
        cx - 10, cy + 20,
        fill="#BDBDBD", outline="#424242", width=2, tags="plane"
    )
    main_canvas.create_polygon(
        cx - 50, cy,
        cx + 50, cy,
        cx + 10, cy + 10,
        cx - 10, cy + 10,
        fill="#757575", outline="#424242", width=2, tags="plane"
    )
    main_canvas.create_polygon(
        cx - 15, cy - 35,
        cx + 15, cy - 35,
        cx, cy - 50,
        fill="#757575", outline="#424242", width=2, tags="plane"
    )

# ========================
# 仪表
# ========================
def draw_hud():
    main_canvas.delete("hud")

    ax, ay = 120, HEIGHT - 120
    main_canvas.create_oval(ax - 60, ay - 60, ax + 60, ay + 60,
                            outline="#00E5FF", width=3, tags="hud")
    main_canvas.create_line(ax, ay - 40, ax, ay + 40,
                            fill="#00E5FF", width=2, tags="hud")
    main_canvas.create_line(ax - 40, ay, ax + 40, ay,
                            fill="#00E5FF", width=2, tags="hud")

    main_canvas.create_text(280, HEIGHT - 120, text=f"ALT: {int(altitude)}m",
                            fill="#00FF00", font=("Consolas", 12, "bold"), tags="hud")
    main_canvas.create_text(280, HEIGHT - 90, text=f"SPD: {int(speed)}km/h",
                            fill="#00FF00", font=("Consolas", 12, "bold"), tags="hud")
    main_canvas.create_text(280, HEIGHT - 60, text=f"HDG: {int(math.degrees(yaw)%360)}°",
                            fill="#00FF00", font=("Consolas", 12, "bold"), tags="hud")
    main_canvas.create_text(420, HEIGHT - 120, text=f"THR: {int(throttle*100)}%",
                            fill="#FFD600", font=("Consolas", 12, "bold"), tags="hud")
    main_canvas.create_text(420, HEIGHT - 90, text=f"FUEL: {int(fuel)}%",
                            fill="#FF5252" if fuel < 20 else "#FFD600",
                            font=("Consolas", 12, "bold"), tags="hud")
    main_canvas.create_text(420, HEIGHT - 60, text=f"GEAR: {'DOWN' if gear_down else 'UP'}",
                            fill="#00E5FF", font=("Consolas", 12, "bold"), tags="hud")
    main_canvas.create_text(560, HEIGHT - 60, text=f"FLAPS: {flaps}",
                            fill="#00E5FF", font=("Consolas", 12, "bold"), tags="hud")

    if stall_warning:
        main_canvas.create_text(WIDTH // 2, HEIGHT - 180, text="⚠ STALL ⚠",
                                fill="#FF0000", font=("Consolas", 22, "bold"), tags="hud")

# ========================
# 物理更新（✅ global 全部锁死）
# ========================
def update_physics():
    global pitch, roll, yaw, speed, altitude, throttle, fuel
    global crashed, landed, on_ground, stall_warning
    global score, mission_step, combo, distance

    if crashed or landed:
        return

    dt = 1 / FPS

    thrust = throttle * 15
    drag = 0.0008 * speed * speed + 0.5
    acc = thrust - drag
    speed += acc * dt
    speed = max(0, min(speed, 300))

    lift = 0.5 * (pitch + flaps * 0.5) * speed * speed * 0.001
    gravity = 9.81
    vert_acc = lift - gravity
    altitude += vert_acc * dt

    if altitude < 0:
        altitude = 0
        on_ground = True
    else:
        on_ground = False

    yaw += roll * 0.02
    distance += speed * dt * math.cos(yaw) * 0.1

    fuel -= throttle * 0.02
    if fuel <= 0:
        fuel = 0
        throttle = 0

    stall_warning = speed < 30 and altitude > 10 and not on_ground

    if altitude < terrain_height(distance) + 5:
        crashed = True

    if mission_step == 0 and throttle > 0.8 and speed > 60:
        mission_step = 1
        score += 500
    elif mission_step == 1 and altitude > 500:
        mission_step = 2
        score += 500
    elif mission_step == 2 and abs(math.degrees(yaw) % 360 - 90) < 10:
        mission_step = 3
        score += 500
    elif mission_step == 3 and 400 < altitude < 600 and 80 < speed < 120:
        mission_step = 4
        score += 500
    elif mission_step == 4 and altitude < 120:
        mission_step = 5
        score += 500
    elif mission_step == 5 and on_ground and speed < 40 and gear_down:
        landed = True
        score += 2000

# ========================
# 场景绘制
# ========================
def draw_scene():
    draw_sky()
    draw_terrain()
    draw_plane()
    draw_hud()

# ========================
# 游戏循环
# ========================
def game_loop():
    update_physics()
    draw_scene()

    info_label.config(text=f"距离: {int(distance)}m | 得分: {score} | 连击: {combo}")
    task_label.config(text=mission_steps[mission_step] if not (crashed or landed) else "")

    if crashed:
        main_canvas.create_text(WIDTH // 2, HEIGHT // 2, text="💥 CRASHED",
                                fill="#FF0000", font=("Consolas", 36, "bold"))
    if landed:
        main_canvas.create_text(WIDTH // 2, HEIGHT // 2, text="🎉 LANDED!",
                                fill="#00FF00", font=("Consolas", 36, "bold"))

    root.after(int(1000 / FPS), game_loop)

# ========================
# 键盘控制
# ========================
def key_down(e):
    global pitch, roll, yaw, throttle, gear_down, flaps
    global crashed, landed, score, mission_step, combo

    if crashed or landed:
        return

    if e.keysym in ("w", "Up"):
        pitch -= 0.05
    if e.keysym in ("s", "Down"):
        pitch += 0.05
    if e.keysym in ("a", "Left"):
        roll -= 0.08
    if e.keysym in ("d", "Right"):
        roll += 0.08
    if e.keysym == "e":
        throttle = min(1.0, throttle + 0.05)
    if e.keysym == "q":
        throttle = max(0.0, throttle - 0.05)
    if e.keysym == "g":
        gear_down = not gear_down
    if e.keysym == "f":
        flaps = (flaps + 1) % 3
    if e.keysym == "r":
        crashed = landed = False
        pitch = roll = yaw = 0
        speed = altitude = distance = 0
        throttle = 0.5
        fuel = 100
        mission_step = 0
        score = combo = 0
    if e.keysym == "h":
        print("W/S 俯仰 | A/D 转向 | E/Q 油门 | G 起落架 | F 襟翼 | R 重开")

def key_up(e):
    global pitch, roll
    if e.keysym in ("w", "s", "Up", "Down"):
        pitch *= 0.9
    if e.keysym in ("a", "d", "Left", "Right"):
        roll *= 0.9

root.bind("<KeyPress>", key_down)
root.bind("<KeyRelease>", key_up)

# ========================
# 天气 / 时间
# ========================
for w in ["☀️ 晴天", "⛅ 多云", "🌧️ 雨天", "⛈️ 雷暴", "🌫️ 大雾"]:
    tk.Button(panel, text=w, command=lambda w=w: globals().update(weather=w)).pack(side="left", padx=2)

for t in ["day", "dawn", "dusk", "night"]:
    tk.Button(panel, text=t.capitalize(), command=lambda t=t: globals().update(time_of_day=t)).pack(side="left", padx=2)

# ========================
# 换肤
# ========================
for name in themes:
    tk.Button(panel, text=name, command=lambda n=name: apply_theme(n)).pack(side="right", padx=2)

# ========================
# 启动
# ========================
apply_theme("🛫 经典驾驶舱")
game_loop()
root.mainloop()