import pygame
import sys
import math
import random

# 初始化 Pygame
pygame.init()

# 窗口设置
WIDTH, HEIGHT = 800, 600
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("🧱 打砖块")

# 颜色定义
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
RED = (255, 50, 50)
DARK_RED = (200, 0, 0)
GREEN = (50, 255, 50)
DARK_GREEN = (0, 200, 0)
BLUE = (50, 50, 255)
DARK_BLUE = (0, 0, 200)
YELLOW = (255, 255, 50)
ORANGE = (255, 165, 0)
PURPLE = (200, 50, 255)
GRAY = (150, 150, 150)
LIGHT_GRAY = (200, 200, 200)
DARK_GRAY = (80, 80, 80)

# 帧率控制
clock = pygame.time.Clock()
FPS = 60

# 中文字体
def get_chinese_font(size):
    font_names = ["SimHei", "Microsoft YaHei", "PingFang SC", "Noto Sans CJK SC", "WenQuanYi Micro Hei"]
    for name in font_names:
        try:
            return pygame.font.SysFont(name, size)
        except:
            continue
    return pygame.font.Font(None, size)

font = get_chinese_font(32)
small_font = get_chinese_font(20)

# 砖块类
class Brick:
    def __init__(self, x, y, width, height, color, hp=1, score=10):
        self.x = x
        self.y = y
        self.width = width
        self.height = height
        self.color = color
        self.hp = hp
        self.max_hp = hp
        self.score = score
        self.alive = True
        self.rect = pygame.Rect(x, y, width, height)
        
        # 发光效果
        self.glow = 0
        self.glow_direction = 1
    
    def update(self):
        if not self.alive:
            return
        # 发光闪烁
        self.glow += 0.05 * self.glow_direction
        if self.glow > 1 or self.glow < 0:
            self.glow_direction *= -1
    
    def draw(self, surface):
        if not self.alive:
            return
        
        # 砖块主体
        pygame.draw.rect(surface, self.color, self.rect)
        
        # 边框
        pygame.draw.rect(surface, BLACK, self.rect, 1)
        
        # 高光效果
        highlight_rect = pygame.Rect(self.x + 2, self.y + 2, self.width - 4, 5)
        pygame.draw.rect(surface, WHITE, highlight_rect)
        
        # 根据血量显示不同效果
        if self.hp > 1:
            # 显示剩余血量
            text = small_font.render(str(self.hp), True, WHITE)
            text_rect = text.get_rect(center=self.rect.center)
            surface.blit(text, text_rect)
        
        # 发光效果
        if self.glow > 0.5:
            glow_surf = pygame.Surface((self.width + 10, self.height + 10), pygame.SRCALPHA)
            glow_alpha = int((self.glow - 0.5) * 200)
            # 获取RGB颜色（如果是元组且长度大于3，取前三个值）
            if len(self.color) >= 3:
                r, g, b = self.color[0], self.color[1], self.color[2]
            else:
                r, g, b = 255, 255, 255
            # 使用set_alpha方式
            temp_surf = pygame.Surface((self.width, self.height), pygame.SRCALPHA)
            temp_surf.fill((r, g, b, glow_alpha))
            glow_surf.blit(temp_surf, (5, 5))
            surface.blit(glow_surf, (self.x - 5, self.y - 5))
    
    def hit(self):
        self.hp -= 1
        if self.hp <= 0:
            self.alive = False
            return True
        return False

# 球类
class Ball:
    def __init__(self, x, y):
        self.x = x
        self.y = y
        self.radius = 8
        self.dx = random.choice([-4, 4])
        self.dy = -5
        self.speed = 6
        self.attached = True
        self.trail = []
        self.particles = []
    
    def update(self, paddle):
        if self.attached:
            self.x = paddle.x + paddle.width // 2
            self.y = paddle.y - self.radius - 2
            return
        
        # 记录轨迹
        self.trail.append((self.x, self.y))
        if len(self.trail) > 20:
            self.trail.pop(0)
        
        # 移动
        self.x += self.dx
        self.y += self.dy
        
        # 墙壁碰撞
        if self.x - self.radius <= 0 or self.x + self.radius >= WIDTH:
            self.dx *= -1
            self.x = max(self.radius, min(WIDTH - self.radius, self.x))
        
        if self.y - self.radius <= 0:
            self.dy *= -1
            self.y = self.radius
        
        # 挡板碰撞
        if self.dy > 0 and self.y + self.radius >= paddle.y and self.y + self.radius <= paddle.y + 20:
            if self.x >= paddle.x and self.x <= paddle.x + paddle.width:
                hit_pos = (self.x - paddle.x) / paddle.width
                angle = (hit_pos - 0.5) * 1.2
                speed = math.hypot(self.dx, self.dy)
                self.dx = speed * math.sin(angle)
                self.dy = -speed * math.cos(angle)
                self.y = paddle.y - self.radius
                
                for _ in range(10):
                    self.particles.append({
                        'x': self.x,
                        'y': self.y,
                        'dx': random.uniform(-3, 3),
                        'dy': random.uniform(-5, -1),
                        'life': 30,
                        'color': (255, 200, 100)
                    })
    
    def draw(self, surface):
        # 绘制轨迹
        for i, pos in enumerate(self.trail):
            if i == 0:
                continue
            alpha = int(200 * (i / len(self.trail)))
            trail_surf = pygame.Surface((self.radius * 2, self.radius * 2), pygame.SRCALPHA)
            trail_color = (100, 200, 255, alpha)
            # 使用fill方式绘制透明圆
            temp_surf = pygame.Surface((self.radius * 2, self.radius * 2), pygame.SRCALPHA)
            pygame.draw.circle(temp_surf, (100, 200, 255), (self.radius, self.radius), int(self.radius * (i / len(self.trail))))
            temp_surf.set_alpha(alpha)
            surface.blit(temp_surf, (int(pos[0]) - self.radius, int(pos[1]) - self.radius))
        
        # 绘制球
        pygame.draw.circle(surface, BLUE, (int(self.x), int(self.y)), self.radius)
        pygame.draw.circle(surface, LIGHT_GRAY, (int(self.x - 2), int(self.y - 2)), 3)
        pygame.draw.circle(surface, DARK_BLUE, (int(self.x), int(self.y)), self.radius, 1)
        
        # 发光效果
        glow_surf = pygame.Surface((self.radius * 4, self.radius * 4), pygame.SRCALPHA)
        for i in range(5):
            alpha = 30 - i * 5
            r = self.radius * 2 - i * 3
            temp_surf = pygame.Surface((r * 2, r * 2), pygame.SRCALPHA)
            pygame.draw.circle(temp_surf, (100, 150, 255), (r, r), r)
            temp_surf.set_alpha(alpha)
            glow_surf.blit(temp_surf, (self.radius * 2 - r, self.radius * 2 - r))
        surface.blit(glow_surf, (self.x - self.radius * 2, self.y - self.radius * 2))
        
        # 粒子
        for p in self.particles[:]:
            p['x'] += p['dx']
            p['y'] += p['dy']
            p['dy'] += 0.1
            p['life'] -= 1
            if p['life'] <= 0:
                self.particles.remove(p)
            else:
                alpha = int(255 * p['life'] / 30)
                particle_surf = pygame.Surface((4, 4), pygame.SRCALPHA)
                temp_surf = pygame.Surface((4, 4), pygame.SRCALPHA)
                pygame.draw.circle(temp_surf, p['color'], (2, 2), 2)
                temp_surf.set_alpha(alpha)
                particle_surf.blit(temp_surf, (0, 0))
                surface.blit(particle_surf, (int(p['x']) - 2, int(p['y']) - 2))

# 挡板类
class Paddle:
    def __init__(self):
        self.width = 120
        self.height = 16
        self.x = WIDTH // 2 - self.width // 2
        self.y = HEIGHT - 50
        self.speed = 8
        self.color = (50, 150, 255)
        self.rect = pygame.Rect(self.x, self.y, self.width, self.height)
        
        self.glow_alpha = 0
        self.glow_dir = 1
    
    def update(self, keys):
        if keys[pygame.K_LEFT] or keys[pygame.K_a]:
            self.x -= self.speed
        if keys[pygame.K_RIGHT] or keys[pygame.K_d]:
            self.x += self.speed
        
        self.x = max(0, min(WIDTH - self.width, self.x))
        self.rect.x = self.x
        
        self.glow_alpha += 2 * self.glow_dir
        if self.glow_alpha > 60 or self.glow_alpha < 0:
            self.glow_dir *= -1
    
    def draw(self, surface):
        # 发光效果 - 使用set_alpha方式
        glow_surf = pygame.Surface((self.width + 20, self.height + 20), pygame.SRCALPHA)
        # 创建临时表面绘制矩形，然后设置透明度
        temp_surf = pygame.Surface((self.width, self.height), pygame.SRCALPHA)
        pygame.draw.rect(temp_surf, (50, 150, 255), (0, 0, self.width, self.height), 0, 8)
        temp_surf.set_alpha(self.glow_alpha)
        glow_surf.blit(temp_surf, (10, 10))
        surface.blit(glow_surf, (self.x - 10, self.y - 10))
        
        # 主体
        pygame.draw.rect(surface, self.color, (self.x, self.y, self.width, self.height), 0, 8)
        pygame.draw.rect(surface, WHITE, (self.x, self.y, self.width, 4), 0, 8)
        pygame.draw.rect(surface, DARK_BLUE, (self.x, self.y, self.width, self.height), 2, 8)

# 游戏主类
class BreakoutGame:
    def __init__(self):
        self.paddle = Paddle()
        self.ball = Ball(self.paddle.x + self.paddle.width // 2, 
                        self.paddle.y - 10)
        self.bricks = []
        self.score = 0
        self.lives = 3
        self.level = 1
        self.game_over = False
        self.win = False
        self.paused = False
        self.combo = 0
        self.combo_timer = 0
        self.particles = []
        self.floating_texts = []
        
        self.create_level()
    
    def create_level(self):
        self.bricks = []
        rows = 6 + self.level
        cols = 10
        brick_width = 70
        brick_height = 25
        spacing = 5
        start_x = (WIDTH - (cols * (brick_width + spacing) - spacing)) // 2
        start_y = 60
        
        colors = [
            RED, ORANGE, YELLOW, GREEN, BLUE, PURPLE,
            (255, 100, 100), (255, 200, 50)
        ]
        
        for row in range(rows):
            for col in range(cols):
                if self.level > 2 and random.random() < 0.1:
                    continue
                
                x = start_x + col * (brick_width + spacing)
                y = start_y + row * (brick_height + spacing)
                
                hp = 1
                if row < 2:
                    hp = 2 + (self.level // 2)
                elif row < 4:
                    hp = 1 + (self.level // 3)
                
                if self.level > 3 and random.random() < 0.05:
                    hp = 3
                
                color = colors[row % len(colors)]
                score = 10 * hp
                brick = Brick(x, y, brick_width, brick_height, color, hp, score)
                self.bricks.append(brick)
        
        if len(self.bricks) < 10:
            for row in range(3):
                for col in range(5):
                    x = start_x + col * (brick_width + spacing) + 150
                    y = start_y + row * (brick_height + spacing) + 50
                    brick = Brick(x, y, brick_width, brick_height, colors[row % len(colors)], 1, 10)
                    self.bricks.append(brick)
    
    def reset_ball(self):
        self.ball = Ball(self.paddle.x + self.paddle.width // 2, 
                        self.paddle.y - 10)
        self.ball.attached = True
        self.combo = 0
    
    def launch_ball(self):
        if self.ball.attached:
            self.ball.attached = False
    
    def update(self, keys):
        if self.game_over or self.win or self.paused:
            return
        
        self.paddle.update(keys)
        
        if keys[pygame.K_SPACE] and self.ball.attached:
            self.launch_ball()
        
        self.ball.update(self.paddle)
        
        for brick in self.bricks:
            brick.update()
        
        if not self.ball.attached:
            ball_rect = pygame.Rect(self.ball.x - self.ball.radius,
                                   self.ball.y - self.ball.radius,
                                   self.ball.radius * 2,
                                   self.ball.radius * 2)
            
            for brick in self.bricks:
                if not brick.alive:
                    continue
                
                if ball_rect.colliderect(brick.rect):
                    overlap_x = min(ball_rect.right, brick.rect.right) - max(ball_rect.left, brick.rect.left)
                    overlap_y = min(ball_rect.bottom, brick.rect.bottom) - max(ball_rect.top, brick.rect.top)
                    
                    if overlap_x < overlap_y:
                        self.ball.dx *= -1
                    else:
                        self.ball.dy *= -1
                    
                    destroyed = brick.hit()
                    if destroyed:
                        self.combo += 1
                        self.combo_timer = 60
                        
                        bonus = self.combo // 5
                        points = brick.score + bonus
                        self.score += points
                        
                        self.floating_texts.append({
                            'x': brick.rect.centerx,
                            'y': brick.rect.centery,
                            'text': f"+{points}",
                            'life': 40,
                            'color': (255, 200, 50)
                        })
                        
                        for _ in range(15):
                            self.particles.append({
                                'x': brick.rect.centerx,
                                'y': brick.rect.centery,
                                'dx': random.uniform(-5, 5),
                                'dy': random.uniform(-5, 5),
                                'life': random.randint(20, 40),
                                'color': brick.color,
                                'size': random.randint(2, 5)
                            })
                        
                        if random.random() < 0.1:
                            self.floating_texts.append({
                                'x': brick.rect.centerx,
                                'y': brick.rect.centery + 30,
                                'text': "⭐ +20",
                                'life': 60,
                                'color': GREEN
                            })
                            self.score += 20
                    
                    break
        
        if self.ball.y > HEIGHT + 50:
            self.lives -= 1
            if self.lives <= 0:
                self.game_over = True
            else:
                self.reset_ball()
        
        for p in self.particles[:]:
            p['x'] += p['dx']
            p['y'] += p['dy']
            p['dy'] += 0.2
            p['life'] -= 1
            if p['life'] <= 0:
                self.particles.remove(p)
        
        for ft in self.floating_texts[:]:
            ft['y'] -= 0.5
            ft['life'] -= 1
            if ft['life'] <= 0:
                self.floating_texts.remove(ft)
        
        if self.combo_timer > 0:
            self.combo_timer -= 1
            if self.combo_timer == 0:
                self.combo = 0
        
        if all(not brick.alive for brick in self.bricks):
            self.win = True
    
    def draw(self, surface):
        surface.fill(BLACK)
        
        # 背景星空
        for i in range(100):
            x = random.randint(0, WIDTH)
            y = random.randint(0, HEIGHT)
            alpha = random.randint(10, 60)
            star_surf = pygame.Surface((2, 2), pygame.SRCALPHA)
            temp_surf = pygame.Surface((2, 2), pygame.SRCALPHA)
            pygame.draw.circle(temp_surf, (255, 255, 255), (1, 1), 1)
            temp_surf.set_alpha(alpha)
            star_surf.blit(temp_surf, (0, 0))
            surface.blit(star_surf, (x, y))
        
        for brick in self.bricks:
            brick.draw(surface)
        
        self.paddle.draw(surface)
        self.ball.draw(surface)
        
        for p in self.particles:
            alpha = int(255 * p['life'] / 40)
            particle_surf = pygame.Surface((p['size'] * 2, p['size'] * 2), pygame.SRCALPHA)
            temp_surf = pygame.Surface((p['size'] * 2, p['size'] * 2), pygame.SRCALPHA)
            color = p['color']
            if len(color) >= 3:
                pygame.draw.circle(temp_surf, (color[0], color[1], color[2]), 
                                 (p['size'], p['size']), p['size'])
            else:
                pygame.draw.circle(temp_surf, color, (p['size'], p['size']), p['size'])
            temp_surf.set_alpha(alpha)
            particle_surf.blit(temp_surf, (0, 0))
            surface.blit(particle_surf, (int(p['x']) - p['size'], int(p['y']) - p['size']))
        
        for ft in self.floating_texts:
            text = small_font.render(ft['text'], True, ft['color'])
            text_rect = text.get_rect(center=(ft['x'], ft['y']))
            surface.blit(text, text_rect)
        
        ui_y = 10
        score_text = font.render(f"得分: {self.score}", True, WHITE)
        surface.blit(score_text, (20, ui_y))
        
        lives_text = font.render(f"❤️ x{self.lives}", True, RED)
        surface.blit(lives_text, (200, ui_y))
        
        level_text = font.render(f"第 {self.level} 关", True, YELLOW)
        surface.blit(level_text, (WIDTH - 150, ui_y))
        
        if self.combo >= 3:
            combo_text = small_font.render(f"🔥 {self.combo}连击!", True, ORANGE)
            surface.blit(combo_text, (WIDTH // 2 - 50, ui_y + 10))
        
        remaining = sum(1 for b in self.bricks if b.alive)
        remaining_text = small_font.render(f"剩余砖块: {remaining}", True, LIGHT_GRAY)
        surface.blit(remaining_text, (20, ui_y + 45))
        
        if self.ball.attached:
            hint = small_font.render("按 空格键 发射球", True, LIGHT_GRAY)
            hint_rect = hint.get_rect(center=(WIDTH // 2, HEIGHT - 20))
            surface.blit(hint, hint_rect)
        
        if self.paused:
            pause_text = font.render("⏸ 暂停中", True, WHITE)
            pause_rect = pause_text.get_rect(center=(WIDTH // 2, HEIGHT // 2))
            surface.blit(pause_text, pause_rect)
        
        if self.game_over:
            overlay = pygame.Surface((WIDTH, HEIGHT))
            overlay.set_alpha(180)
            overlay.fill(BLACK)
            surface.blit(overlay, (0, 0))
            
            game_over_text = font.render("💀 游戏结束", True, RED)
            game_over_rect = game_over_text.get_rect(center=(WIDTH // 2, HEIGHT // 2 - 40))
            surface.blit(game_over_text, game_over_rect)
            
            final_score = font.render(f"最终得分: {self.score}", True, WHITE)
            final_score_rect = final_score.get_rect(center=(WIDTH // 2, HEIGHT // 2 + 20))
            surface.blit(final_score, final_score_rect)
            
            restart = small_font.render("按 R 重新开始", True, LIGHT_GRAY)
            restart_rect = restart.get_rect(center=(WIDTH // 2, HEIGHT // 2 + 60))
            surface.blit(restart, restart_rect)
        
        if self.win:
            overlay = pygame.Surface((WIDTH, HEIGHT))
            overlay.set_alpha(180)
            overlay.fill(BLACK)
            surface.blit(overlay, (0, 0))
            
            win_text = font.render("🎉 恭喜过关！", True, GREEN)
            win_rect = win_text.get_rect(center=(WIDTH // 2, HEIGHT // 2 - 40))
            surface.blit(win_text, win_rect)
            
            next_text = font.render(f"得分: {self.score}  |  按 R 进入下一关", True, WHITE)
            next_rect = next_text.get_rect(center=(WIDTH // 2, HEIGHT // 2 + 20))
            surface.blit(next_text, next_rect)

# 创建游戏实例
game = BreakoutGame()

# 主循环
running = True
while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_r:
                if game.game_over or game.win:
                    if game.win:
                        game.level += 1
                        game.create_level()
                        game.reset_ball()
                        game.win = False
                    else:
                        game = BreakoutGame()
                else:
                    game = BreakoutGame()
                    game.level = 1
            if event.key == pygame.K_p:
                game.paused = not game.paused
            if event.key == pygame.K_SPACE and game.ball.attached:
                game.launch_ball()
    
    keys = pygame.key.get_pressed()
    game.update(keys)
    game.draw(screen)
    pygame.display.flip()
    clock.tick(FPS)

pygame.quit()
sys.exit()