import pygame
import random
import sys

# ===================== 全局常量 =====================
WIDTH, HEIGHT = 800, 600
FPS = 60
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
RED = (220, 30, 30)
GREEN = (40, 180, 40)
BLUE = (30, 120, 220)
GOLD = (255, 200, 0)
GRAY = (80, 80, 80)
BROWN = (110, 70, 40)

# 玩家参数
PLAYER_SIZE = 32
PLAYER_SPEED = 4
PLAYER_MAX_HP = 100

# 怪物参数
MONSTER_SIZE = 28
MONSTER_SPEED = 1.5
MONSTER_DAMAGE = 10
MONSTER_REWARD_GOLD = 5
MONSTER_EXP = 20

# ===================== 游戏类 =====================
class RPGGame:
    def __init__(self):
        pygame.init()
        self.screen = pygame.display.set_mode((WIDTH, HEIGHT))
        pygame.display.set_caption("像素冒险RPG")
        self.clock = pygame.time.Clock()
        
        # 修复字体：优先使用系统默认字体，避免中文黑体缺失报错
        try:
            self.font_small = pygame.font.SysFont(None, 16)
            self.font_mid = pygame.font.SysFont(None, 24)
            self.font_big = pygame.font.SysFont(None, 48)
        except:
            self.font_small = pygame.font.Font(pygame.font.get_default_font(), 16)
            self.font_mid = pygame.font.Font(pygame.font.get_default_font(), 24)
            self.font_big = pygame.font.Font(pygame.font.get_default_font(), 48)

        # 游戏状态
        self.game_state = "menu"  # menu / play / pause / gameover
        self.running = True

        # 玩家数据
        self.player_x = WIDTH // 2
        self.player_y = HEIGHT // 2
        self.player_hp = PLAYER_MAX_HP
        self.player_gold = 0
        self.player_exp = 0
        self.player_level = 1
        self.exp_need = 100

        # 墙体地图（碰撞障碍物）
        self.walls = [
            pygame.Rect(100, 100, 120, 20),
            pygame.Rect(300, 200, 20, 150),
            pygame.Rect(500, 80, 150, 20),
            pygame.Rect(200, 400, 180, 20),
            pygame.Rect(600, 300, 20, 180),
        ]

        # 怪物列表、伤害文字弹窗
        self.monsters = []
        self.damage_texts = []
        self.spawn_timer = 0

    # 生成怪物
    def spawn_monster(self):
        side = random.randint(0, 3)
        if side == 0:
            x = random.randint(0, WIDTH)
            y = -MONSTER_SIZE
        elif side == 1:
            x = WIDTH
            y = random.randint(0, HEIGHT)
        elif side == 2:
            x = random.randint(0, WIDTH)
            y = HEIGHT
        else:
            x = -MONSTER_SIZE
            y = random.randint(0, HEIGHT)
        monster_rect = pygame.Rect(x, y, MONSTER_SIZE, MONSTER_SIZE)
        self.monsters.append({
            "rect": monster_rect,
            "hp": 40 + self.player_level * 10
        })

    # 绘制主菜单
    def draw_menu(self):
        self.screen.fill(BLACK)
        title = self.font_big.render("Pixel RPG Game", True, GOLD)
        start_txt = self.font_mid.render("SPACE - Start Game", True, WHITE)
        quit_txt = self.font_mid.render("ESC - Quit", True, RED)
        tip = self.font_small.render("WASD Move | SPACE Attack | P Pause", True, BLUE)

        self.screen.blit(title, (WIDTH//2 - title.get_width()//2, 180))
        self.screen.blit(start_txt, (WIDTH//2 - start_txt.get_width()//2, 280))
        self.screen.blit(quit_txt, (WIDTH//2 - quit_txt.get_width()//2, 340))
        self.screen.blit(tip, (WIDTH//2 - tip.get_width()//2, 420))

    # 绘制暂停界面
    def draw_pause(self):
        overlay = pygame.Surface((WIDTH, HEIGHT))
        overlay.set_alpha(160)
        overlay.fill(BLACK)
        self.screen.blit(overlay, (0, 0))

        pause_text = self.font_big.render("PAUSED", True, WHITE)
        resume = self.font_mid.render("P - Resume", True, GREEN)
        back_menu = self.font_mid.render("ESC - Back Menu", True, RED)
        self.screen.blit(pause_text, (WIDTH//2 - pause_text.get_width()//2, 220))
        self.screen.blit(resume, (WIDTH//2 - resume.get_width()//2, 320))
        self.screen.blit(back_menu, (WIDTH//2 - back_menu.get_width()//2, 380))

    # 游戏重置
    def reset_game(self):
        self.player_x = WIDTH // 2
        self.player_y = HEIGHT // 2
        self.player_hp = PLAYER_MAX_HP
        self.player_gold = 0
        self.player_exp = 0
        self.player_level = 1
        self.exp_need = 100
        self.monsters.clear()
        self.damage_texts.clear()
        self.spawn_timer = 0

    # 玩家攻击逻辑
    def player_attack(self):
        player_rect = pygame.Rect(self.player_x, self.player_y, PLAYER_SIZE, PLAYER_SIZE)
        hit_range = pygame.Rect(player_rect.x - 15, player_rect.y - 15, PLAYER_SIZE + 30, PLAYER_SIZE + 30)
        damage = 15 + self.player_level * 5
        dead_list = []
        for idx, m in enumerate(self.monsters):
            if hit_range.colliderect(m["rect"]):
                m["hp"] -= damage
                self.damage_texts.append({
                    "x": m["rect"].x,
                    "y": m["rect"].y - 20,
                    "text": f"-{damage}",
                    "time": 40
                })
                if m["hp"] <= 0:
                    self.player_gold += MONSTER_REWARD_GOLD
                    self.player_exp += MONSTER_EXP
                    dead_list.append(idx)
        # 倒序删除死亡怪物
        for i in reversed(dead_list):
            del self.monsters[i]
        # 升级判定
        if self.player_exp >= self.exp_need:
            self.player_level += 1
            self.player_exp -= self.exp_need
            self.exp_need = int(self.exp_need * 1.4)
            self.player_hp = min(self.player_hp + 30, PLAYER_MAX_HP + self.player_level * 20)

    # 游戏主渲染
    def draw_game(self):
        self.screen.fill((30, 40, 30))
        player_rect = pygame.Rect(self.player_x, self.player_y, PLAYER_SIZE, PLAYER_SIZE)

        # 绘制墙体
        for wall in self.walls:
            pygame.draw.rect(self.screen, BROWN, wall)
            pygame.draw.rect(self.screen, GRAY, wall, 2)

        # 绘制玩家
        pygame.draw.rect(self.screen, BLUE, player_rect)
        pygame.draw.rect(self.screen, WHITE, player_rect, 2)

        # 绘制怪物
        for m in self.monsters:
            pygame.draw.rect(self.screen, RED, m["rect"])
            hp_width = m["rect"].width * (m["hp"] / (40 + self.player_level * 10))
            pygame.draw.rect(self.screen, BLACK, (m["rect"].x, m["rect"].y - 6, m["rect"].width, 4))
            pygame.draw.rect(self.screen, GREEN, (m["rect"].x, m["rect"].y - 6, hp_width, 4))

        # 伤害数字
        for dmg in self.damage_texts:
            txt = self.font_small.render(dmg["text"], True, GOLD)
            self.screen.blit(txt, (dmg["x"], dmg["y"]))
            dmg["y"] -= 1
            dmg["time"] -= 1
        self.damage_texts = [d for d in self.damage_texts if d["time"] > 0]

        # ========== UI界面面板 ==========
        # 左上角状态面板
        ui_box = pygame.Rect(10, 10, 220, 120)
        pygame.draw.rect(self.screen, (20, 20, 20), ui_box)
        pygame.draw.rect(self.screen, WHITE, ui_box, 2)

        # 等级
        level_text = self.font_small.render(f"Lv: {self.player_level}", True, WHITE)
        self.screen.blit(level_text, (20, 20))

        # 血条
        hp_text = self.font_small.render("HP", True, RED)
        self.screen.blit(hp_text, (20, 45))
        hp_bar_bg = pygame.Rect(50, 45, 160, 14)
        max_hp = PLAYER_MAX_HP + self.player_level * 20
        hp_bar_fill = pygame.Rect(50, 45, 160 * (self.player_hp / max_hp), 14)
        pygame.draw.rect(self.screen, BLACK, hp_bar_bg)
        pygame.draw.rect(self.screen, RED, hp_bar_fill)

        # 经验条
        exp_text = self.font_small.render("EXP", True, BLUE)
        self.screen.blit(exp_text, (20, 68))
        exp_bar_bg = pygame.Rect(50, 68, 160, 14)
        exp_bar_fill = pygame.Rect(50, 68, 160 * (self.player_exp / self.exp_need), 14)
        pygame.draw.rect(self.screen, BLACK, exp_bar_bg)
        pygame.draw.rect(self.screen, BLUE, exp_bar_fill)

        # 金币
        gold_text = self.font_small.render(f"Gold: {self.player_gold}", True, GOLD)
        self.screen.blit(gold_text, (20, 92))

        # 底部操作提示
        tip_text = self.font_small.render("WASD Move | SPACE Attack | P Pause", True, WHITE)
        self.screen.blit(tip_text, (WIDTH//2 - tip_text.get_width()//2, HEIGHT - 30))

    # 游戏逻辑更新
    def update_game(self, keys):
        player_rect = pygame.Rect(self.player_x, self.player_y, PLAYER_SIZE, PLAYER_SIZE)
        dx, dy = 0, 0
        if keys[pygame.K_w]: dy -= PLAYER_SPEED
        if keys[pygame.K_s]: dy += PLAYER_SPEED
        if keys[pygame.K_a]: dx -= PLAYER_SPEED
        if keys[pygame.K_d]: dx += PLAYER_SPEED

        # X轴移动碰撞检测
        new_x = self.player_x + dx
        temp_rect_x = pygame.Rect(new_x, self.player_y, PLAYER_SIZE, PLAYER_SIZE)
        if not any(temp_rect_x.colliderect(w) for w in self.walls):
            self.player_x = new_x
        # Y轴移动碰撞检测
        new_y = self.player_y + dy
        temp_rect_y = pygame.Rect(self.player_x, new_y, PLAYER_SIZE, PLAYER_SIZE)
        if not any(temp_rect_y.colliderect(w) for w in self.walls):
            self.player_y = new_y

        # 边界限制
        self.player_x = max(0, min(WIDTH - PLAYER_SIZE, self.player_x))
        self.player_y = max(0, min(HEIGHT - PLAYER_SIZE, self.player_y))

        # 怪物AI追踪玩家
        player_center = (self.player_x + PLAYER_SIZE/2, self.player_y + PLAYER_SIZE/2)
        for m in self.monsters:
            m_center = (m["rect"].x + MONSTER_SIZE/2, m["rect"].y + MONSTER_SIZE/2)
            if player_center[0] > m_center[0]:
                m["rect"].x += MONSTER_SPEED
            else:
                m["rect"].x -= MONSTER_SPEED
            if player_center[1] > m_center[1]:
                m["rect"].y += MONSTER_SPEED
            else:
                m["rect"].y -= MONSTER_SPEED
            # 怪物撞到玩家扣血
            if m["rect"].colliderect(player_rect):
                self.player_hp -= MONSTER_DAMAGE / FPS

        # 怪物刷新计时器
        self.spawn_timer += 1
        if self.spawn_timer > 120 and len(self.monsters) < 8:
            self.spawn_monster()
            self.spawn_timer = 0

        # 游戏结束判定
        if self.player_hp <= 0:
            self.game_state = "gameover"

    # 绘制游戏结束界面
    def draw_gameover(self):
        overlay = pygame.Surface((WIDTH, HEIGHT))
        overlay.set_alpha(180)
        overlay.fill(BLACK)
        self.screen.blit(overlay, (0, 0))
        over_text = self.font_big.render("GAME OVER", True, RED)
        data = self.font_mid.render(f"Level:{self.player_level} Gold:{self.player_gold}", True, WHITE)
        restart = self.font_mid.render("SPACE Restart | ESC Menu", True, GOLD)
        self.screen.blit(over_text, (WIDTH//2 - over_text.get_width()//2, 200))
        self.screen.blit(data, (WIDTH//2 - data.get_width()//2, 280))
        self.screen.blit(restart, (WIDTH//2 - restart.get_width()//2, 340))

    # 主事件循环
    def game_loop(self):
        while self.running:
            self.clock.tick(FPS)
            keys = pygame.key.get_pressed()
            # 事件监听
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    self.running = False
                if event.type == pygame.KEYDOWN:
                    # 菜单操作
                    if self.game_state == "menu":
                        if event.key == pygame.K_SPACE:
                            self.reset_game()
                            self.game_state = "play"
                        if event.key == pygame.K_ESCAPE:
                            self.running = False
                    # 游戏中暂停
                    elif self.game_state == "play":
                        if event.key == pygame.K_p:
                            self.game_state = "pause"
                        if event.key == pygame.K_SPACE:
                            self.player_attack()
                    # 暂停界面
                    elif self.game_state == "pause":
                        if event.key == pygame.K_p:
                            self.game_state = "play"
                        if event.key == pygame.K_ESCAPE:
                            self.game_state = "menu"
                    # 游戏结束
                    elif self.game_state == "gameover":
                        if event.key == pygame.K_SPACE:
                            self.reset_game()
                            self.game_state = "play"
                        if event.key == pygame.K_ESCAPE:
                            self.game_state = "menu"

            # 状态分支渲染&更新
            if self.game_state == "menu":
                self.draw_menu()
            elif self.game_state == "play":
                self.update_game(keys)
                self.draw_game()
            elif self.game_state == "pause":
                self.draw_game()
                self.draw_pause()
            elif self.game_state == "gameover":
                self.draw_game()
                self.draw_gameover()

            pygame.display.flip()
        pygame.quit()
        sys.exit()

# 启动游戏
if __name__ == "__main__":
    game = RPGGame()
    game.game_loop()