import pygame
import sys
import math
import random

# ========== 初始化 ==========
pygame.init()
WIDTH, HEIGHT = 800, 600
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("🐦 Angry Birds – Beautiful Edition")
clock = pygame.time.Clock()

# ========== 色彩方案 ==========
SKY_TOP = (100, 180, 255)
SKY_BOTTOM = (200, 230, 255)
SUN_COLOR = (255, 255, 150)
CLOUD_COLOR = (255, 255, 255)
MOUNTAIN = (150, 200, 150)
MOUNTAIN_DARK = (100, 150, 100)
GRASS_GREEN = (120, 200, 80)
GRASS_DARK = (70, 150, 50)
DIRT = (160, 120, 80)
WOOD = (200, 160, 100)
WOOD_DARK = (140, 100, 60)
STONE = (180, 180, 190)
STONE_DARK = (120, 120, 130)
PIG_BODY = (130, 210, 80)
PIG_DARK = (80, 160, 50)
PIG_SNOUT = (200, 250, 160)
RED = (230, 60, 50)
RED_DARK = (180, 40, 30)
BLACK = (30, 30, 30)
WHITE = (255, 255, 255)
YELLOW = (255, 240, 50)
BROWN = (150, 100, 50)
DARK_BROWN = (90, 60, 30)
GOLD = (255, 215, 0)

# ========== 字体 ==========
font_score = pygame.font.Font(None, 52)
font_small = pygame.font.Font(None, 28)
font_big = pygame.font.Font(None, 68)
font_title = pygame.font.Font(None, 36)

# ========== 常量 ==========
GRAVITY = 0.6
SLINGSHOT_POS = (180, 470)
MAX_DRAG = 100
BIRDS_COUNT = 3

# ========== 背景元素 ==========
class Cloud:
    def __init__(self, x, y, size):
        self.x = x
        self.y = y
        self.size = size
        self.speed = random.uniform(0.2, 0.5)
    def update(self):
        self.x += self.speed
        if self.x > WIDTH + 100:
            self.x = -100
            self.y = random.randint(50, 200)
    def draw(self, surface):
        for ox, oy, r in [(0,0,self.size), (self.size//2, -5, self.size//2), (-self.size//2, -3, self.size//2)]:
            pygame.draw.circle(surface, CLOUD_COLOR, (int(self.x+ox), int(self.y+oy)), r)

# ========== 猪猪（更萌） ==========
class Pig:
    def __init__(self, x, y):
        self.x = x
        self.y = y
        self.radius = 20
        self.alive = True
        self.rect = pygame.Rect(x-20, y-20, 40, 40)
        self.eye_anim = 0

    def draw(self, surface):
        if not self.alive: return
        # 身体
        pygame.draw.circle(surface, PIG_BODY, (self.x, self.y), self.radius)
        pygame.draw.circle(surface, PIG_DARK, (self.x, self.y), self.radius, 3)
        # 高光
        pygame.draw.circle(surface, (180, 255, 120), (self.x-5, self.y-8), 6)
        # 眼睛（带眼皮）
        eye_y = self.y - 6
        pygame.draw.circle(surface, WHITE, (self.x-8, eye_y), 6)
        pygame.draw.circle(surface, WHITE, (self.x+8, eye_y), 6)
        pygame.draw.circle(surface, BLACK, (self.x-9, eye_y), 3)
        pygame.draw.circle(surface, BLACK, (self.x+7, eye_y), 3)
        # 眉毛（生气表情）
        pygame.draw.line(surface, BLACK, (self.x-14, eye_y-4), (self.x-4, eye_y), 3)
        pygame.draw.line(surface, BLACK, (self.x+14, eye_y-4), (self.x+4, eye_y), 3)
        # 鼻子
        snout_rect = pygame.Rect(self.x-9, self.y, 18, 12)
        pygame.draw.ellipse(surface, PIG_SNOUT, snout_rect)
        pygame.draw.ellipse(surface, BLACK, snout_rect, 2)
        pygame.draw.circle(surface, BLACK, (self.x-4, self.y+4), 3)
        pygame.draw.circle(surface, BLACK, (self.x+4, self.y+4), 3)
        # 耳朵
        ear_offset = 2
        pygame.draw.ellipse(surface, PIG_DARK, (self.x-18, self.y-16, 10, 8))
        pygame.draw.ellipse(surface, PIG_DARK, (self.x+8, self.y-16, 10, 8))

    def check_collision(self, bird_rect):
        if self.alive and self.rect.colliderect(bird_rect):
            self.alive = False
            return True
        return False

# ========== 方块（木纹/石纹） ==========
class Block:
    def __init__(self, x, y, w, h, color=WOOD, strength=1):
        self.rect = pygame.Rect(x, y, w, h)
        self.color = color
        self.strength = strength
        self.alive = True

    def draw(self, surface):
        if not self.alive: return
        # 主体
        pygame.draw.rect(surface, self.color, self.rect)
        pygame.draw.rect(surface, BLACK, self.rect, 2)
        # 纹理
        if self.strength >= 1:
            if self.color == WOOD:
                # 木纹
                for i in range(1, 4):
                    y_offset = self.rect.top + i * self.rect.height // 4
                    pygame.draw.line(surface, WOOD_DARK, (self.rect.left+5, y_offset), (self.rect.right-5, y_offset), 1)
            elif self.color == STONE:
                # 石纹斑点
                for _ in range(3):
                    sx = self.rect.left + random.randint(4, self.rect.width-8)
                    sy = self.rect.top + random.randint(4, self.rect.height-8)
                    pygame.draw.circle(surface, STONE_DARK, (sx, sy), 3)

    def hit(self):
        self.strength -= 1
        if self.strength <= 0:
            self.alive = False
            return True
        return False

# ========== 小鸟（带羽毛纹理） ==========
class Bird:
    def __init__(self, x, y):
        self.x = x
        self.y = y
        self.radius = 15
        self.vx = 0
        self.vy = 0
        self.launched = False
        self.active = True
        self.trail = []
        self.angle = 0

    def update(self):
        if not self.launched or not self.active:
            return
        self.vx *= 0.995
        self.vy *= 0.995
        self.vy += GRAVITY
        self.x += self.vx
        self.y += self.vy
        self.angle = math.atan2(self.vy, self.vx)
        self.trail.append((self.x, self.y))
        if len(self.trail) > 15:
            self.trail.pop(0)
        if self.y > HEIGHT + 50 or self.x > WIDTH + 50 or self.x < -50:
            self.active = False

    def draw(self, surface):
        if not self.active: return
        # 轨迹粒子
        for i, (tx, ty) in enumerate(self.trail):
            alpha = int(150 * (i / len(self.trail)))
            radius = 2 + i * 0.3
            pygame.draw.circle(surface, (255, 150, 100, alpha), (int(tx), int(ty)), radius)
        # 身体（带旋转）
        body_surf = pygame.Surface((self.radius*2, self.radius*2), pygame.SRCALPHA)
        body_center = (self.radius, self.radius)
        pygame.draw.circle(body_surf, RED, body_center, self.radius)
        pygame.draw.circle(body_surf, RED_DARK, body_center, self.radius, 2)
        # 高光
        pygame.draw.circle(body_surf, (255, 150, 130), (self.radius-4, self.radius-5), 6)
        # 眼睛
        pygame.draw.circle(body_surf, WHITE, (self.radius-6, self.radius-5), 5)
        pygame.draw.circle(body_surf, BLACK, (self.radius-7, self.radius-6), 2)
        # 眉毛
        pygame.draw.line(body_surf, BLACK, (self.radius-12, self.radius-10), (self.radius-5, self.radius-7), 3)
        pygame.draw.line(body_surf, BLACK, (self.radius+2, self.radius-10), (self.radius+9, self.radius-10), 3)
        # 喙
        beak_points = [(self.radius+9, self.radius-2), (self.radius+18, self.radius), (self.radius+9, self.radius+2)]
        pygame.draw.polygon(body_surf, YELLOW, beak_points)
        # 旋转绘制
        rotated = pygame.transform.rotate(body_surf, -math.degrees(self.angle))
        rot_rect = rotated.get_rect(center=(self.x, self.y))
        surface.blit(rotated, rot_rect)

    def launch(self, vx, vy):
        self.vx = vx
        self.vy = vy
        self.launched = True

    def get_rect(self):
        return pygame.Rect(self.x - self.radius, self.y - self.radius, self.radius*2, self.radius*2)

# ========== 主游戏类 ==========
class Game:
    def __init__(self):
        self.clouds = [Cloud(random.randint(0, WIDTH), random.randint(50, 200), random.randint(30, 60)) for _ in range(5)]
        self.reset()

    def reset(self):
        self.score = 0
        self.birds_left = BIRDS_COUNT
        self.bird = Bird(SLINGSHOT_POS[0], SLINGSHOT_POS[1])
        self.dragging = False
        self.drag_offset = (0, 0)
        self.state = "playing"
        self.pigs = [
            Pig(580, 430),
            Pig(680, 430),
            Pig(630, 360),
        ]
        self.blocks = [
            Block(560, 420, 20, 80, WOOD),
            Block(600, 380, 60, 20, WOOD),
            Block(660, 420, 20, 80, WOOD),
            Block(620, 320, 100, 20, STONE, 2),
            Block(640, 270, 20, 50, STONE, 2),
            Block(680, 380, 80, 20, WOOD),
            Block(740, 420, 20, 80, WOOD),
        ]
        self.particles = []

    def handle_events(self):
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                return False
            if event.type == pygame.MOUSEBUTTONDOWN:
                if not self.bird.launched and self.bird.active:
                    mx, my = pygame.mouse.get_pos()
                    if math.hypot(mx - self.bird.x, my - self.bird.y) < 30:
                        self.dragging = True
                        self.drag_offset = (0, 0)
            elif event.type == pygame.MOUSEBUTTONUP:
                if self.dragging and not self.bird.launched:
                    mx, my = pygame.mouse.get_pos()
                    dx = mx - self.bird.x
                    dy = my - self.bird.y
                    dist = math.hypot(dx, dy)
                    if dist > MAX_DRAG:
                        scale = MAX_DRAG / dist
                        dx *= scale
                        dy *= scale
                    vx = -dx * 0.2
                    vy = -dy * 0.2
                    if math.hypot(vx, vy) >= 3:
                        self.bird.launch(vx, vy)
                self.dragging = False
            elif event.type == pygame.KEYDOWN:
                if event.key == pygame.K_r and self.state in ("win", "lose"):
                    self.reset()
        return True

    def update(self):
        if self.state != "playing":
            return
        for cloud in self.clouds:
            cloud.update()
        self.bird.update()
        bird_rect = self.bird.get_rect()
        if self.bird.active and self.bird.launched:
            for pig in self.pigs:
                if pig.check_collision(bird_rect):
                    self.score += 500
                    self.spawn_particles(pig.x, pig.y, PIG_BODY, 20)
                    self.bird.active = False
            for block in self.blocks:
                if block.alive and bird_rect.colliderect(block.rect):
                    if block.hit():
                        self.score += 100
                        self.spawn_particles(block.rect.centerx, block.rect.centery, block.color, 15)
                    self.bird.vx = 0
                    self.bird.vy = 0
                    self.bird.active = False
                    break
        for p in self.particles[:]:
            p["life"] -= 1
            p["x"] += p["vx"]
            p["y"] += p["vy"]
            p["vy"] += 0.2
            if p["life"] <= 0:
                self.particles.remove(p)
        if not self.bird.active and self.bird.launched:
            self.birds_left -= 1
            if self.birds_left > 0:
                self.bird = Bird(SLINGSHOT_POS[0], SLINGSHOT_POS[1])
            else:
                if all(not pig.alive for pig in self.pigs):
                    self.state = "win"
                else:
                    self.state = "lose"

    def spawn_particles(self, x, y, color, count):
        for _ in range(count):
            p = {
                "x": x, "y": y,
                "vx": random.uniform(-5, 5),
                "vy": random.uniform(-8, -3),
                "color": color,
                "life": random.randint(20, 35)
            }
            self.particles.append(p)

    def draw_scene(self):
        # 天空
        for y in range(HEIGHT):
            ratio = y / HEIGHT
            r = int(SKY_TOP[0] + (SKY_BOTTOM[0]-SKY_TOP[0])*ratio)
            g = int(SKY_TOP[1] + (SKY_BOTTOM[1]-SKY_TOP[1])*ratio)
            b = int(SKY_TOP[2] + (SKY_BOTTOM[2]-SKY_TOP[2])*ratio)
            pygame.draw.line(screen, (r,g,b), (0,y), (WIDTH,y))
        # 太阳
        pygame.draw.circle(screen, SUN_COLOR, (700, 80), 50)
        pygame.draw.circle(screen, (255, 255, 200), (700, 80), 40)
        # 云
        for cloud in self.clouds:
            cloud.draw(screen)
        # 远山
        for i in range(3):
            mx = 200 + i * 250
            my = 500
            points = [(mx-120, my), (mx, my-100), (mx+120, my)]
            pygame.draw.polygon(screen, MOUNTAIN if i%2==0 else MOUNTAIN_DARK, points)
        # 草地
        grass_rect = pygame.Rect(0, 490, WIDTH, 110)
        pygame.draw.rect(screen, GRASS_GREEN, grass_rect)
        # 草地纹理
        for i in range(0, WIDTH, 30):
            grass_blade = [(i, 490), (i+10, 475), (i+20, 490)]
            pygame.draw.polygon(screen, GRASS_DARK, grass_blade)
        # 泥土
        dirt_rect = pygame.Rect(0, 530, WIDTH, 70)
        pygame.draw.rect(screen, DIRT, dirt_rect)

    def draw_slingshot(self):
        base_x = SLINGSHOT_POS[0]
        base_y = SLINGSHOT_POS[1] + 30
        # 木桩（带纹理）
        left_pole = [(base_x-18, base_y), (base_x-22, base_y-70), (base_x-14, base_y-70), (base_x-10, base_y)]
        right_pole = [(base_x+10, base_y), (base_x+14, base_y-70), (base_x+22, base_y-70), (base_x+18, base_y)]
        pygame.draw.polygon(screen, DARK_BROWN, left_pole)
        pygame.draw.polygon(screen, DARK_BROWN, right_pole)
        pygame.draw.polygon(screen, (120, 80, 40), left_pole, 2)
        pygame.draw.polygon(screen, (120, 80, 40), right_pole, 2)
        # 横梁
        beam_rect = pygame.Rect(base_x-24, base_y-75, 48, 14)
        pygame.draw.rect(screen, DARK_BROWN, beam_rect)
        pygame.draw.rect(screen, (140, 100, 50), beam_rect, 2)

        # 橡皮筋
        if self.dragging and not self.bird.launched:
            mx, my = pygame.mouse.get_pos()
            dx = mx - self.bird.x
            dy = my - self.bird.y
            dist = math.hypot(dx, dy)
            if dist > MAX_DRAG:
                scale = MAX_DRAG / dist
                dx *= scale
                dy *= scale
            bird_draw_x = self.bird.x + dx
            bird_draw_y = self.bird.y + dy
        else:
            bird_draw_x = self.bird.x
            bird_draw_y = self.bird.y

        # 左皮筋
        pygame.draw.line(screen, (200, 160, 100), (base_x-18, base_y-70), (bird_draw_x, bird_draw_y), 5)
        # 右皮筋
        pygame.draw.line(screen, (200, 160, 100), (base_x+18, base_y-70), (bird_draw_x, bird_draw_y), 5)

    def draw_ui(self):
        # 半透明面板
        panel = pygame.Surface((WIDTH, 70), pygame.SRCALPHA)
        panel.fill((0,0,0, 100))
        screen.blit(panel, (0, 0))
        score_txt = font_score.render(f"Score: {self.score}", True, WHITE)
        screen.blit(score_txt, (20, 10))
        birds_txt = font_small.render(f"Birds left: {self.birds_left}", True, WHITE)
        screen.blit(birds_txt, (20, 45))
        if not self.bird.launched and self.bird.active:
            hint = font_title.render("Drag the bird!", True, GOLD)
            screen.blit(hint, (WIDTH//2 - hint.get_width()//2, 15))

    def draw_game_over(self):
        overlay = pygame.Surface((WIDTH, HEIGHT), pygame.SRCALPHA)
        overlay.fill((0,0,0, 180))
        screen.blit(overlay, (0,0))
        if self.state == "win":
            msg = "LEVEL CLEAR!"
            color = GOLD
        else:
            msg = "GAME OVER"
            color = RED
        msg_txt = font_big.render(msg, True, color)
        screen.blit(msg_txt, (WIDTH//2 - msg_txt.get_width()//2, HEIGHT//2 - 60))
        score_txt = font_score.render(f"Score: {self.score}", True, WHITE)
        screen.blit(score_txt, (WIDTH//2 - score_txt.get_width()//2, HEIGHT//2))
        restart_txt = font_small.render("Press R to restart", True, WHITE)
        screen.blit(restart_txt, (WIDTH//2 - restart_txt.get_width()//2, HEIGHT//2 + 50))

    def draw(self):
        self.draw_scene()
        for block in self.blocks:
            block.draw(screen)
        for pig in self.pigs:
            pig.draw(screen)
        self.draw_slingshot()
        self.bird.draw(screen)
        for p in self.particles:
            alpha = min(255, p["life"] * 12)
            size = max(1, p["life"] * 0.3)
            pygame.draw.circle(screen, (*p["color"], alpha), (int(p["x"]), int(p["y"])), size)
        self.draw_ui()
        if self.state in ("win", "lose"):
            self.draw_game_over()

    def run(self):
        running = True
        while running:
            running = self.handle_events()
            self.update()
            self.draw()
            pygame.display.flip()
            clock.tick(60)
        pygame.quit()
        sys.exit()

if __name__ == "__main__":
    game = Game()
    game.run()