205 lines
10 KiB
Python
205 lines
10 KiB
Python
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))
|