import tkinter as tk
import random
import math

WIDTH, HEIGHT = 400, 600
FPS = 16  # ≈60FPS

class Player:
    def __init__(self, canvas):
        self.canvas = canvas
        self.x = 100
        self.y = HEIGHT // 2
        self.speed = 5
        self.alive = True

        # 飞机造型（三角形）
        self.id = canvas.create_polygon(
            self.x, self.y - 15,
            self.x - 12, self.y + 10,
            self.x + 12, self.y + 10,
            fill="#4CAF50", outline="#2E7D32", width=2
        )
        # 尾焰
        self.flame = canvas.create_oval(
            self.x - 4, self.y + 10,
            self.x + 4, self.y + 20,
            fill="orange", outline=""
        )

    def move(self, dx, dy):
        self.x += dx * self.speed
        self.y += dy * self.speed

        # 边界
        self.x = max(15, min(WIDTH - 15, self.x))
        self.y = max(15, min(HEIGHT - 15, self.y))

        self.canvas.coords(
            self.id,
            self.x, self.y - 15,
            self.x - 12, self.y + 10,
            self.x + 12, self.y + 10
        )
        self.canvas.coords(
            self.flame,
            self.x - 4, self.y + 10,
            self.x + 4, self.y + 20
        )

    def get_bounds(self):
        return self.canvas.coords(self.id)

    def destroy(self):
        self.canvas.delete(self.id)
        self.canvas.delete(self.flame)


class Obstacle:
    def __init__(self, canvas, game_speed):
        self.canvas = canvas
        self.x = WIDTH + 50
        self.speed = game_speed

        # 上下两根柱子，中间留空隙
        self.gap = random.randint(140, 200)
        self.top_height = random.randint(60, HEIGHT - self.gap - 60)
        self.bottom_y = self.top_height + self.gap

        # 上柱子
        self.top_id = canvas.create_rectangle(
            self.x - 25, 0,
            self.x + 25, self.top_height,
            fill="#f44336", outline="#b71c1c", width=2
        )
        # 下柱子
        self.bottom_id = canvas.create_rectangle(
            self.x - 25, self.bottom_y,
            self.x + 25, HEIGHT,
            fill="#f44336", outline="#b71c1c", width=2
        )

    def update(self):
        self.x -= self.speed
        self.canvas.move(self.top_id, -self.speed, 0)
        self.canvas.move(self.bottom_id, -self.speed, 0)

    def off_screen(self):
        return self.x + 25 < 0

    def get_bounds(self):
        # 返回上下两段的边界
        return [
            self.canvas.coords(self.top_id),
            self.canvas.coords(self.bottom_id)
        ]

    def destroy(self):
        self.canvas.delete(self.top_id)
        self.canvas.delete(self.bottom_id)


class Cloud:
    def __init__(self, canvas):
        self.canvas = canvas
        self.x = random.randint(WIDTH, WIDTH + 200)
        self.y = random.randint(30, HEIGHT // 2)
        self.speed = random.uniform(0.5, 1.5)
        self.size = random.randint(30, 60)

        self.id = canvas.create_oval(
            self.x, self.y,
            self.x + self.size, self.y + self.size * 0.5,
            fill="white", outline="", stipple="gray25"
        )

    def update(self):
        self.x -= self.speed
        self.canvas.move(self.id, -self.speed, 0)

    def off_screen(self):
        return self.x + self.size < 0

    def destroy(self):
        self.canvas.delete(self.id)


class FlightGame:
    def __init__(self, root):
        self.root = root
        self.root.title("017. 飞行躲避")
        self.root.resizable(False, False)

        self.canvas = tk.Canvas(
            root, width=WIDTH, height=HEIGHT, bg="#87CEEB"
        )
        self.canvas.pack()

        # 地面
        self.ground = self.canvas.create_rectangle(
            0, HEIGHT - 40, WIDTH, HEIGHT,
            fill="#8BC34A", outline=""
        )
        self.ground_x = 0

        self.player = Player(self.canvas)
        self.obstacles = []
        self.clouds = []
        self.score = 0
        self.game_speed = 3
        self.game_over = False
        self.passed_obstacles = set()

        self.score_text = self.canvas.create_text(
            70, 25, text="得分: 0",
            font=("Consolas", 14, "bold"), fill="white"
        )

        self.hint_text = self.canvas.create_text(
            WIDTH // 2, 30, text="方向键控制飞机  |  躲避红色柱子",
            font=("Microsoft YaHei", 10), fill="#555"
        )

        self.keys = set()
        self.bind_keys()
        self.spawn_obstacle()
        self.game_loop()

    def bind_keys(self):
        self.root.bind("<KeyPress>", self.key_down)
        self.root.bind("<KeyRelease>", self.key_up)
        self.root.bind("<space>", lambda e: self.restart())
        self.root.focus_set()

    def key_down(self, e):
        self.keys.add(e.keysym)

    def key_up(self, e):
        self.keys.discard(e.keysym)

    def handle_input(self):
        dx = dy = 0
        if "Left" in self.keys:
            dx -= 1
        if "Right" in self.keys:
            dx += 1
        if "Up" in self.keys:
            dy -= 1
        if "Down" in self.keys:
            dy += 1
        self.player.move(dx, dy)

    def spawn_obstacle(self):
        if self.game_over:
            return
        self.obstacles.append(Obstacle(self.canvas, self.game_speed))
        delay = max(800, 1800 - self.score * 30)
        self.root.after(delay, self.spawn_obstacle)

    def check_collision(self):
        player_box = self.player.get_bounds()

        for obs in self.obstacles:
            bounds = obs.get_bounds()
            for box in bounds:
                if (player_box[2] > box[0] and
                    player_box[0] < box[2] and
                    player_box[3] > box[1] and
                    player_box[1] < box[3]):
                    return True
        return False

    def check_score(self):
        player_x = self.player.x
        for obs in self.obstacles:
            obs_center = obs.x
            obs_id = id(obs)
            if (obs_id not in self.passed_obstacles and
                player_x > obs_center):
                self.passed_obstacles.add(obs_id)
                self.score += 1
                self.canvas.itemconfig(
                    self.score_text, text=f"得分: {self.score}"
                )
                # 每 5 分加速
                if self.score % 5 == 0:
                    self.game_speed += 0.5

    def update_ground(self):
        self.ground_x -= self.game_speed * 0.5
        if self.ground_x <= -40:
            self.ground_x = 0
        self.canvas.coords(
            self.ground,
            self.ground_x, HEIGHT - 40,
            self.ground_x + WIDTH + 40, HEIGHT
        )

    def game_loop(self):
        if self.game_over:
            return

        self.handle_input()

        # 更新障碍物
        for obs in self.obstacles[:]:
            obs.update()
            if obs.off_screen():
                obs.destroy()
                self.obstacles.remove(obs)

        # 更新云朵
        if random.random() < 0.01:
            self.clouds.append(Cloud(self.canvas))
        for cloud in self.clouds[:]:
            cloud.update()
            if cloud.off_screen():
                cloud.destroy()
                self.clouds.remove(cloud)

        # 地面滚动
        self.update_ground()

        # 碰撞检测
        if self.check_collision():
            self.game_over = True
            self.show_game_over()
            return

        # 计分
        self.check_score()

        self.root.after(FPS, self.game_loop)

    def show_game_over(self):
        self.player.destroy()
        self.canvas.create_rectangle(
            0, 0, WIDTH, HEIGHT,
            fill="black", stipple="gray50", tags="overlay"
        )
        self.canvas.create_text(
            WIDTH // 2, HEIGHT // 2 - 40,
            text="💥 游戏结束！",
            fill="#ff4444", font=("Microsoft YaHei", 26, "bold"),
            tags="overlay"
        )
        self.canvas.create_text(
            WIDTH // 2, HEIGHT // 2 + 20,
            text=f"最终得分: {self.score}",
            fill="white", font=("Consolas", 18),
            tags="overlay"
        )
        self.canvas.create_text(
            WIDTH // 2, HEIGHT // 2 + 70,
            text="按 空格键 重新开始",
            fill="#aaaaaa", font=("Microsoft YaHei", 12),
            tags="overlay"
        )

    def restart(self):
        self.canvas.delete("all")
        self.__init__(self.root)


if __name__ == "__main__":
    root = tk.Tk()
    FlightGame(root)
    root.mainloop()