import pygame
import sys
import math
import random

# --- 配置常量 ---
SCREEN_WIDTH, SCREEN_HEIGHT = 800, 600
FPS = 60

# 颜色定义
COLOR_BG = (20, 25, 30)
COLOR_PLAYER = (50, 150, 255)
COLOR_ENEMY = (255, 60, 60)
COLOR_BULLET = (255, 255, 100)
COLOR_GUN = (150, 150, 150)

pygame.init()
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
pygame.display.set_caption("Pygame 2D Top-Down Shooter")
clock = pygame.time.Clock()
font = pygame.font.Font(None, 36)

# --- 基础类 ---
class Bullet(pygame.sprite.Sprite):
    def __init__(self, x, y, angle):
        super().__init__()
        self.speed = 12
        self.x, self.y = x, y
        self.angle = angle
        
        self.image = pygame.Surface((10, 10), pygame.SRCALPHA)
        pygame.draw.circle(self.image, COLOR_BULLET, (5, 5), 5)
        self.rect = self.image.get_rect(center=(x, y))

    def update(self):
        self.x += self.speed * math.cos(self.angle)
        self.y -= self.speed * math.sin(self.angle)  # Pygame Y轴向下，所以是减
        self.rect.center = (int(self.x), int(self.y))
        
        # 超出屏幕销毁
        if not screen.get_rect().colliderect(self.rect):
            self.kill()

class Enemy(pygame.sprite.Sprite):
    def __init__(self, x, y):
        super().__init__()
        self.speed = 2.5
        self.health = 3
        self.x, self.y = float(x), float(y)
        
        self.image = pygame.Surface((30, 30), pygame.SRCALPHA)
        pygame.draw.circle(self.image, COLOR_ENEMY, (15, 15), 15)
        self.rect = self.image.get_rect(center=(self.x, self.y))

    def update(self, player):
        # 简单的直线追踪玩家
        dx = player.rect.centerx - self.x
        dy = player.rect.centery - self.y
        dist = math.hypot(dx, dy)
        
        if dist > 1:
            self.x += self.speed * dx / dist
            self.y += self.speed * dy / dist
        self.rect.center = (int(self.x), int(self.y))

class Player(pygame.sprite.Sprite):
    def __init__(self):
        super().__init__()
        self.speed = 5
        self.fire_rate = 10  # 帧数
        self.cooldown = 0
        self.score = 0
        
        # 玩家本体（不旋转，只画个圆）
        self.image = pygame.Surface((40, 40), pygame.SRCALPHA)
        pygame.draw.circle(self.image, COLOR_PLAYER, (20, 20), 20)
        self.rect = self.image.get_rect(center=(SCREEN_WIDTH//2, SCREEN_HEIGHT//2))
        
        # 枪管（单独处理旋转）
        self.gun_image = pygame.Surface((30, 10), pygame.SRCALPHA)
        pygame.draw.rect(self.gun_image, COLOR_GUN, (0, 0, 30, 10))

    def handle_input(self, bullets):
        keys = pygame.key.get_pressed()
        dx, dy = 0, 0
        if keys[pygame.K_w] or keys[pygame.K_UP]: dy -= 1
        if keys[pygame.K_s] or keys[pygame.K_DOWN]: dy += 1
        if keys[pygame.K_a] or keys[pygame.K_LEFT]: dx -= 1
        if keys[pygame.K_d] or keys[pygame.K_RIGHT]: dx += 1
        
        # 对角线移动归一化
        if dx != 0 or dy != 0:
            length = math.hypot(dx, dy)
            self.rect.x += self.speed * dx / length
            self.rect.y += self.speed * dy / length
            
        # 限制在屏幕内
        self.rect.clamp_ip(screen.get_rect())

        # 鼠标瞄准与射击
        mx, my = pygame.mouse.get_pos()
        dx = mx - self.rect.centerx
        dy = my - self.rect.centery
        self.angle = math.atan2(-dy, dx)  # 计算弧度
        
        # 冷却控制
        if self.cooldown > 0:
            self.cooldown -= 1
        elif pygame.mouse.get_pressed()[0]:  # 按住左键连发
            bullet_x = self.rect.centerx + 25 * math.cos(self.angle)
            bullet_y = self.rect.centery - 25 * math.sin(self.angle)
            bullets.add(Bullet(bullet_x, bullet_y, self.angle))
            self.cooldown = self.fire_rate

    def draw_gun(self, surface):
        # 旋转枪管并绘制
        rotated_gun = pygame.transform.rotate(self.gun_image, math.degrees(self.angle))
        gun_rect = rotated_gun.get_rect(center=self.rect.center)
        # 稍微偏移让枪看起来是从身体伸出来的
        offset_x = 15 * math.cos(self.angle)
        offset_y = -15 * math.sin(self.angle)
        gun_rect.center = (self.rect.centerx + offset_x, self.rect.centery + offset_y)
        surface.blit(rotated_gun, gun_rect)

# --- 主循环 ---
def main():
    player = Player()
    enemies = pygame.sprite.Group()
    bullets = pygame.sprite.Group()
    all_sprites = pygame.sprite.Group(player, enemies, bullets)
    
    spawn_timer = 0
    running = True

    while running:
        clock.tick(FPS)
        
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                running = False
            if event.type == pygame.KEYDOWN and event.key == pygame.K_r:
                # R键重置
                player.__init__()
                enemies.empty(); bullets.empty()
                all_sprites.empty()
                all_sprites.add(player, enemies, bullets)

        # 生成敌人
        spawn_timer += 1
        if spawn_timer >= 40:
            side = random.choice(['top', 'bottom', 'left', 'right'])
            if side == 'top': ex, ey = random.randint(0, SCREEN_WIDTH), -30
            elif side == 'bottom': ex, ey = random.randint(0, SCREEN_WIDTH), SCREEN_HEIGHT + 30
            elif side == 'left': ex, ey = -30, random.randint(0, SCREEN_HEIGHT)
            else: ex, ey = SCREEN_WIDTH + 30, random.randint(0, SCREEN_HEIGHT)
            
            enemy = Enemy(ex, ey)
            enemies.add(enemy)
            all_sprites.add(enemy)
            spawn_timer = 0

        # 更新逻辑
        player.handle_input(bullets)
        enemies.update(player)
        bullets.update()
        
        # 子弹击中敌人
        hits = pygame.sprite.groupcollide(enemies, bullets, False, True)
        for enemy, hit_bullets in hits.items():
            enemy.health -= len(hit_bullets)
            if enemy.health <= 0:
                player.score += 100
                enemy.kill()
                
        # 敌人碰到玩家 -> 扣血/重置
        if pygame.sprite.spritecollideany(player, enemies):
            player.score = max(0, player.score - 200)
            player.rect.center = (SCREEN_WIDTH//2, SCREEN_HEIGHT//2)
            enemies.empty()  # 清屏惩罚

        # 绘制
        screen.fill(COLOR_BG)
        all_sprites.draw(screen)
        player.draw_gun(screen)  # 枪需要单独绘制以支持旋转
        
        # UI
        score_text = font.render(f"Kills: {player.score // 100} | Score: {player.score}", True, (255, 255, 255))
        hint_text = font.render("WASD Move | Mouse Aim & Shoot | R Reset", True, (150, 150, 150))
        screen.blit(score_text, (10, 10))
        screen.blit(hint_text, (10, SCREEN_HEIGHT - 30))

        pygame.display.flip()

    pygame.quit()
    sys.exit()

if __name__ == "__main__":
    main()