maze_python/boss_fight_ui.py
2025-06-30 17:43:54 +08:00

271 lines
11 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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))