import pygame import json import os from boss_fight import boss_fight class BossFightUI: def __init__(self, font=None): # 初始化字体 font_path = os.path.join(os.path.dirname(__file__), "syht.otf") if os.path.exists(font_path): self.font = pygame.font.Font(font_path, 32) self.small_font = pygame.font.Font(font_path, 24) else: # 备用字体 self.font = font if font else pygame.font.Font(None, 32) self.small_font = pygame.font.Font(None, 24) self.is_showing = False self.boss_data = None self.player_skills = None self.fight_sequences = None self.current_boss_index = 0 self.current_action_index = 0 self.animation_timer = 0 self.animation_speed = 60 # 每秒1步 self.auto_play = False self.cooldowns = [] # 当前技能冷却状态 self.boss_hp = 0 # 当前boss剩余血量 self.round_count = 0 # 当前回合数 # UI位置和尺寸 self.window_rect = pygame.Rect(50, 50, 700, 500) self.close_button_rect = pygame.Rect(self.window_rect.right - 30, self.window_rect.top + 5, 25, 25) self.auto_button_rect = pygame.Rect(self.window_rect.left + 10, self.window_rect.bottom - 40, 80, 30) self.next_button_rect = pygame.Rect(self.window_rect.left + 100, self.window_rect.bottom - 40, 80, 30) self.reset_button_rect = pygame.Rect(self.window_rect.left + 190, self.window_rect.bottom - 40, 80, 30) # 颜色定义 self.bg_color = (240, 240, 240) self.border_color = (100, 100, 100) self.button_color = (200, 200, 200) self.button_hover_color = (180, 180, 180) self.skill_colors = [(255, 100, 100), (100, 255, 100), (100, 100, 255), (255, 255, 100)] self.cooldown_color = (150, 150, 150) def show_boss_fight(self, boss_data, player_skills): """显示boss战斗界面""" self.boss_data = boss_data self.player_skills = player_skills self.is_showing = True # 计算战斗策略 self.fight_sequences = boss_fight(boss_data, player_skills) if self.fight_sequences: self.reset_fight_state() else: print("无法计算boss战斗策略") def reset_fight_state(self): """重置战斗状态""" self.current_boss_index = 0 self.current_action_index = 0 self.cooldowns = [0] * len(self.player_skills) self.boss_hp = self.boss_data[0] if self.boss_data else 0 self.round_count = 0 self.animation_timer = 0 def handle_event(self, event): """处理事件""" if not self.is_showing: return False if event.type == pygame.MOUSEBUTTONDOWN: if self.close_button_rect.collidepoint(event.pos): self.is_showing = False return True elif self.auto_button_rect.collidepoint(event.pos): self.auto_play = not self.auto_play return True elif self.next_button_rect.collidepoint(event.pos): self.next_action() return True elif self.reset_button_rect.collidepoint(event.pos): self.reset_fight_state() return True elif event.type == pygame.KEYDOWN: if event.key == pygame.K_ESCAPE: self.is_showing = False return True elif event.key == pygame.K_SPACE: self.next_action() return True elif event.key == pygame.K_r: self.reset_fight_state() return True elif event.key == pygame.K_a: self.auto_play = not self.auto_play return True return False def update(self): """更新动画状态""" if not self.is_showing or not self.auto_play: return self.animation_timer += 1 if self.animation_timer >= self.animation_speed: self.next_action() self.animation_timer = 0 def next_action(self): """执行下一个动作""" if not self.fight_sequences or self.current_boss_index >= len(self.fight_sequences): return current_sequence = self.fight_sequences[self.current_boss_index] if self.current_action_index >= len(current_sequence): # 当前boss已击败,切换到下一个boss self.current_boss_index += 1 if self.current_boss_index < len(self.boss_data): self.current_action_index = 0 self.boss_hp = self.boss_data[self.current_boss_index] # 冷却时间递减但不重置 self.cooldowns = [max(0, cd - 1) for cd in self.cooldowns] self.round_count += 1 else: # 所有boss都被击败 self.auto_play = False return # 执行当前动作 action = current_sequence[self.current_action_index] # 先减少所有技能的冷却时间 self.cooldowns = [max(0, cd - 1) for cd in self.cooldowns] if action == -1: # 等待动作 pass else: # 使用技能 if action < len(self.player_skills): damage, cooldown = self.player_skills[action] self.boss_hp -= damage self.cooldowns[action] = cooldown # 检查boss是否被击败 if self.boss_hp <= 0: self.boss_hp = 0 self.current_action_index += 1 self.round_count += 1 def draw(self, screen): """绘制boss战斗界面""" if not self.is_showing: return # 绘制背景窗口 pygame.draw.rect(screen, self.bg_color, self.window_rect) pygame.draw.rect(screen, self.border_color, self.window_rect, 3) # 绘制标题 title_text = self.font.render("Boss战斗策略", True, (0, 0, 0)) screen.blit(title_text, (self.window_rect.left + 10, self.window_rect.top + 10)) # 绘制关闭按钮 pygame.draw.rect(screen, (255, 100, 100), self.close_button_rect) close_text = self.small_font.render("X", True, (255, 255, 255)) close_rect = close_text.get_rect(center=self.close_button_rect.center) screen.blit(close_text, close_rect) if not self.fight_sequences: # 无解情况 no_solution_text = self.font.render("无法击败所有Boss!", True, (255, 0, 0)) screen.blit(no_solution_text, (self.window_rect.left + 50, self.window_rect.top + 100)) return # 绘制boss信息 y_offset = 50 for i, boss_hp in enumerate(self.boss_data): color = (0, 255, 0) if i < self.current_boss_index else (255, 0, 0) if i == self.current_boss_index else (100, 100, 100) if i == self.current_boss_index: boss_text = f"Boss {i+1}: {self.boss_hp}/{boss_hp} HP" else: boss_text = f"Boss {i+1}: {boss_hp} HP" text = self.small_font.render(boss_text, True, color) screen.blit(text, (self.window_rect.left + 10, self.window_rect.top + y_offset)) y_offset += 25 # 绘制技能信息 y_offset += 20 skills_title = self.font.render("技能信息:", True, (0, 0, 0)) screen.blit(skills_title, (self.window_rect.left + 10, self.window_rect.top + y_offset)) y_offset += 30 for i, (damage, cooldown_time) in enumerate(self.player_skills): current_cooldown = self.cooldowns[i] if i < len(self.cooldowns) else 0 color = self.skill_colors[i % len(self.skill_colors)] if current_cooldown == 0 else self.cooldown_color skill_text = f"技能{i}: 伤害{damage}, 冷却{cooldown_time}" if current_cooldown > 0: skill_text += f" (冷却中: {current_cooldown})" text = self.small_font.render(skill_text, True, color) screen.blit(text, (self.window_rect.left + 10, self.window_rect.top + y_offset)) y_offset += 25 # 绘制当前战斗状态 y_offset += 20 if self.current_boss_index < len(self.fight_sequences): current_sequence = self.fight_sequences[self.current_boss_index] status_text = f"当前Boss {self.current_boss_index + 1}, 回合 {self.round_count}" text = self.small_font.render(status_text, True, (0, 0, 0)) screen.blit(text, (self.window_rect.left + 10, self.window_rect.top + y_offset)) y_offset += 25 # 绘制当前boss的战斗序列 sequence_text = "战斗序列: " for j, action in enumerate(current_sequence): if j == self.current_action_index: sequence_text += f"[{action}] " elif j < self.current_action_index: sequence_text += f"{action} " else: sequence_text += f"({action}) " text = self.small_font.render(sequence_text, True, (0, 0, 0)) screen.blit(text, (self.window_rect.left + 10, self.window_rect.top + y_offset)) y_offset += 25 # 说明当前动作 if self.current_action_index < len(current_sequence): action = current_sequence[self.current_action_index] if action == -1: action_text = "下一个动作: 等待" else: damage, cooldown = self.player_skills[action] action_text = f"下一个动作: 使用技能{action} (伤害{damage})" text = self.small_font.render(action_text, True, (0, 100, 0)) screen.blit(text, (self.window_rect.left + 10, self.window_rect.top + y_offset)) # 绘制控制按钮 # 自动播放按钮 auto_color = (100, 255, 100) if self.auto_play else self.button_color pygame.draw.rect(screen, auto_color, self.auto_button_rect) auto_text = self.small_font.render("自动" if not self.auto_play else "停止", True, (0, 0, 0)) auto_rect = auto_text.get_rect(center=self.auto_button_rect.center) screen.blit(auto_text, auto_rect) # 下一步按钮 pygame.draw.rect(screen, self.button_color, self.next_button_rect) next_text = self.small_font.render("下一步", True, (0, 0, 0)) next_rect = next_text.get_rect(center=self.next_button_rect.center) screen.blit(next_text, next_rect) # 重置按钮 pygame.draw.rect(screen, self.button_color, self.reset_button_rect) reset_text = self.small_font.render("重置", True, (0, 0, 0)) reset_rect = reset_text.get_rect(center=self.reset_button_rect.center) screen.blit(reset_text, reset_rect) # 绘制操作提示 hint_text = "ESC: 关闭 | 空格: 下一步 | A: 自动播放 | R: 重置" hint = self.small_font.render(hint_text, True, (100, 100, 100)) screen.blit(hint, (self.window_rect.left + 10, self.window_rect.bottom - 60))