import pygame from config import * class SaveLoadUI: """存档和读档界面""" def __init__(self, font): self.font = font self.small_font = pygame.font.Font(FONT_FILE, FONT_SIZE - 4) self.show_save_list = False self.save_list = [] self.selected_save = -1 self.scroll_offset = 0 self.max_visible_saves = 8 # 双击检测 self.last_click_time = 0 self.last_clicked_index = -1 self.double_click_threshold = 500 # 毫秒 # 界面元素 button_positions = get_button_positions() self.list_area = pygame.Rect(*button_positions['save_list_area']) self.save_input = "" self.input_active = False def update_save_list(self, maze): """更新存档列表""" self.save_list = maze.get_save_list() def toggle_save_list(self): """切换存档列表显示状态""" self.show_save_list = not self.show_save_list if not self.show_save_list: self.selected_save = -1 self.input_active = False def handle_event(self, event, maze): """处理界面事件""" if not self.show_save_list: return None if event.type == pygame.KEYDOWN: if self.input_active: if event.key == pygame.K_RETURN: # 保存游戏 if self.save_input.strip(): result = maze.save_game(self.save_input.strip()) if result: self.update_save_list(maze) self.save_input = "" self.input_active = False return "save_success" return "save_failed" elif event.key == pygame.K_ESCAPE: self.input_active = False self.save_input = "" elif event.key == pygame.K_BACKSPACE: self.save_input = self.save_input[:-1] else: if len(self.save_input) < 20: # 限制输入长度 self.save_input += event.unicode else: if event.key == pygame.K_UP: if self.selected_save > 0: self.selected_save -= 1 elif event.key == pygame.K_DOWN: if self.selected_save < len(self.save_list) - 1: self.selected_save += 1 elif event.key == pygame.K_RETURN: # 加载选中的存档 if 0 <= self.selected_save < len(self.save_list): save_file = self.save_list[self.selected_save]['path'] if maze.load_game(save_file): # 加载成功后检查是否需要重新生成路径 if len(maze.full_path) == 0 and maze.generater.maze: # 只有当没有路径信息时才重新生成 from SourceCollector import SourceCollector maze.source_collector = SourceCollector(maze=maze.generater.maze) maze.source_collector.run() maze.full_path = maze.source_collector.get_path() maze.path_step = 0 maze.is_path_complete = False # 不要重置grid,保持加载的包含路径的网格 print(f"已为加载的存档重新生成路径,路径长度: {len(maze.full_path)}") self.show_save_list = False return "load_success" return "load_failed" elif event.key == pygame.K_DELETE: # 删除选中的存档 if 0 <= self.selected_save < len(self.save_list): save_file = self.save_list[self.selected_save]['path'] from simple_save_manager import simple_save_manager if simple_save_manager.delete_save(save_file): self.update_save_list(maze) if self.selected_save >= len(self.save_list): self.selected_save = len(self.save_list) - 1 return "delete_success" elif event.key == pygame.K_n: # 新建存档 self.input_active = True self.save_input = "" elif event.key == pygame.K_ESCAPE: self.toggle_save_list() elif event.type == pygame.MOUSEBUTTONDOWN: if event.button == 1: # 左键点击 mouse_pos = pygame.mouse.get_pos() # 检查是否点击在存档列表区域 if self.list_area.collidepoint(mouse_pos): # 计算点击的存档索引 relative_y = mouse_pos[1] - self.list_area.y - 30 # 减去标题高度 if relative_y >= 0: clicked_index = relative_y // 25 # 每个存档项25像素高 if 0 <= clicked_index < len(self.save_list): current_time = pygame.time.get_ticks() # 检查是否为双击 if (clicked_index == self.last_clicked_index and current_time - self.last_click_time < self.double_click_threshold): # 双击加载存档 save_file = self.save_list[clicked_index]['path'] if maze.load_game(save_file): # 加载成功后检查是否需要重新生成路径 if len(maze.full_path) == 0 and maze.generater.maze: # 只有当没有路径信息时才重新生成 from SourceCollector import SourceCollector maze.source_collector = SourceCollector(maze=maze.generater.maze) maze.source_collector.run() maze.full_path = maze.source_collector.get_path() maze.path_step = 0 maze.is_path_complete = False # 不要重置grid,保持加载的包含路径的网格 print(f"已为加载的存档重新生成路径,路径长度: {len(maze.full_path)}") self.show_save_list = False return "load_success" return "load_failed" else: # 单击选择 self.selected_save = clicked_index self.last_clicked_index = clicked_index self.last_click_time = current_time else: # 点击外部关闭界面 self.toggle_save_list() return None def draw(self, screen): """绘制存档界面""" if not self.show_save_list: return # 绘制半透明背景 overlay = pygame.Surface((UI_WIDTH, UI_HEIGHT)) overlay.set_alpha(128) overlay.fill((0, 0, 0)) screen.blit(overlay, (0, 0)) # 绘制存档列表背景 pygame.draw.rect(screen, COLOR_WHITE, self.list_area) pygame.draw.rect(screen, COLOR_BLACK, self.list_area, 2) # 绘制标题 title_text = self.font.render("存档管理", True, COLOR_BLACK) screen.blit(title_text, (self.list_area.x + 10, self.list_area.y + 5)) # 绘制操作说明 if self.input_active: hint_text = self.small_font.render("输入存档名称(.csv),按回车保存:", True, COLOR_BLACK) screen.blit(hint_text, (self.list_area.x + 10, self.list_area.y + 30)) # 绘制输入框 input_rect = pygame.Rect(self.list_area.x + 10, self.list_area.y + 50, 300, 25) pygame.draw.rect(screen, COLOR_WHITE, input_rect) pygame.draw.rect(screen, COLOR_BLACK, input_rect, 2) input_text = self.small_font.render(self.save_input + "|", True, COLOR_BLACK) screen.blit(input_text, (input_rect.x + 5, input_rect.y + 5)) else: hint_text = self.small_font.render("↑↓选择 回车/双击加载 Delete删除 N新建 ESC关闭", True, COLOR_BLACK) screen.blit(hint_text, (self.list_area.x + 10, self.list_area.y + 30)) # 绘制存档列表 start_y = self.list_area.y + 55 for i, save_info in enumerate(self.save_list): y_pos = start_y + i * 25 if y_pos > self.list_area.bottom - 25: break # 高亮选中项 if i == self.selected_save: highlight_rect = pygame.Rect(self.list_area.x + 5, y_pos - 2, self.list_area.width - 10, 22) pygame.draw.rect(screen, COLOR_GRAY, highlight_rect) # 显示存档信息 save_text = f"{save_info['name']} - {save_info['save_time'][:16]}" text_surface = self.small_font.render(save_text, True, COLOR_BLACK) screen.blit(text_surface, (self.list_area.x + 10, y_pos)) # 如果没有存档,显示提示 if not self.save_list and not self.input_active: no_save_text = self.small_font.render("没有找到存档文件", True, COLOR_LIGHT_GRAY) screen.blit(no_save_text, (self.list_area.x + 10, self.list_area.y + 60))