Advertisement
Guest User

Untitled

a guest
Apr 1st, 2025
16
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 30.95 KB | None | 0 0
  1. # -*- coding: utf-8 -*-
  2. # 海岛求生终极版(完整功能优化版)
  3. import tkinter as tk
  4. from tkinter import ttk, messagebox, filedialog
  5. import random
  6. from datetime import datetime, timedelta
  7. import os
  8. import json # 新增导入
  9.  
  10. try:
  11. import pygame
  12. pygame.mixer.init()
  13. SOUND_ENABLED = True
  14. except (ImportError, ModuleNotFoundError):
  15. SOUND_ENABLED = False
  16.  
  17. class IslandSurvivalGame:
  18. def __init__(self, root):
  19. self.root = root
  20. self.root.title("海岛求生-终极版")
  21. self.root.geometry("1100x800")
  22. self.root.configure(bg='#1a1a1a')
  23.  
  24. self.init_styles()
  25. self.init_game_data()
  26. self.create_widgets()
  27. self.update_display()
  28. self.check_status()
  29. self.show_logs()
  30.  
  31. # region 初始化部分
  32. def init_styles(self):
  33. self.style = ttk.Style()
  34. self.style.theme_use('clam')
  35. self.color = {
  36. 'bg': '#1a1a1a', 'fg': '#e0e0e0', 'secondary': '#2c3e50',
  37. 'progress': '#2ecc71', 'danger': '#e74c3c', 'warning': '#f39c12',
  38. 'log_bg': '#2c3e50', 'log_fg': '#bdc3c7'
  39. }
  40. self.style.configure('.', background=self.color['bg'], foreground=self.color['fg'], font=('微软雅黑', 10))
  41. self.style.configure("TProgressbar", thickness=20, troughcolor='#34495e', background=self.color['progress'])
  42. self.style.configure('Dark.TFrame', background=self.color['secondary'])
  43. self.style.configure('Dark.TLabel', background=self.color['secondary'], foreground='white')
  44. self.style.configure('Action.TButton', font=('微软雅黑', 11, 'bold'), padding=10, background='#34495e', foreground='white')
  45. self.style.configure('Dark.Treeview', background='#2c3e50', foreground='#bdc3c7', fieldbackground='#2c3e50')
  46. self.style.map('Dark.Treeview', background=[('selected', '#3498db')])
  47.  
  48. def init_game_data(self):
  49. self.resources = {'木材':5, '淡水':3, '食物':2, '石头':0, '种子':0, '鱼':0}
  50. self.base_levels = {'住所':1, '工具':1, '防御':1, '农田':0}
  51. self.areas = ["沙滩", "棕榈树林", "岩石海岸", "淡水溪流", "山洞", "丛林深处", "废弃营地"]
  52. self.current_area_idx = 0
  53. self.farm = {'planted':False, 'growth_stage':0.0, 'crop_type':None}
  54. self.health = 100.0
  55. self.stamina = 80.0
  56. self.game_start_time = datetime(2023, 1, 1, 6, 0)
  57. self.current_time = self.game_start_time
  58. self.seasons = {
  59. 1:"❄️冬季",2:"❄️冬季",3:"🌸春季",4:"🌸春季",5:"🌸春季",
  60. 6:"☀️夏季",7:"☀️夏季",8:"☀️夏季",9:"🍂秋季",10:"🍂秋季",11:"🍂秋季",12:"❄️冬季"
  61. }
  62. self.log_types = ['全部', '收集', '建造', '种植', '危险', '系统']
  63. self.current_filter = '全部'
  64. self.log_buffer = []
  65. self.max_log_lines = 100
  66.  
  67. @property
  68. def current_area(self):
  69. return self.areas[self.current_area_idx]
  70. # endregion
  71.  
  72. # region 界面创建
  73. def create_widgets(self):
  74. # 时间面板
  75. time_frame = ttk.Frame(self.root, style='Dark.TFrame')
  76. time_frame.pack(fill=tk.X, pady=(0, 10))
  77. self.time_label = ttk.Label(time_frame, font=('微软雅黑', 10, 'bold'), style='Dark.TLabel')
  78. self.time_label.pack(side=tk.LEFT, padx=15)
  79. self.season_label = ttk.Label(time_frame, font=('微软雅黑', 10, 'bold'), style='Dark.TLabel')
  80. self.season_label.pack(side=tk.RIGHT, padx=15)
  81.  
  82. # 主界面
  83. main_frame = ttk.Frame(self.root)
  84. main_frame.pack(pady=10, fill=tk.BOTH, expand=True)
  85.  
  86. # 场景区域
  87. scene_frame = ttk.LabelFrame(main_frame, text="当前区域", style='Dark.TLabelframe')
  88. scene_frame.pack(side=tk.LEFT, padx=15, fill=tk.BOTH, expand=True)
  89.  
  90. self.area_name_label = ttk.Label(scene_frame, font=('微软雅黑', 12, 'bold'),
  91. style='Dark.TLabel', foreground='#e67e22')
  92. self.area_name_label.pack(pady=5)
  93.  
  94. scene_control = ttk.Frame(scene_frame)
  95. scene_control.pack(fill=tk.BOTH, expand=True)
  96. self.btn_prev = ttk.Button(scene_control, text="《", command=self.prev_area, style='Action.TButton', width=3)
  97. self.btn_prev.pack(side=tk.LEFT, fill=tk.Y)
  98. self.scene_ascii = ttk.Label(scene_control, font=('Courier New', 14, 'bold'), foreground='#7f8c8d', anchor=tk.CENTER)
  99. self.scene_ascii.pack(side=tk.LEFT, expand=True, fill=tk.BOTH)
  100. self.btn_next = ttk.Button(scene_control, text="》", command=self.next_area, style='Action.TButton', width=3)
  101. self.btn_next.pack(side=tk.RIGHT, fill=tk.Y)
  102.  
  103. self.resource_info_label = ttk.Label(scene_frame, font=('微软雅黑', 10),
  104. style='Dark.TLabel', foreground='#2ecc71')
  105. self.resource_info_label.pack(pady=5)
  106.  
  107. status_frame = ttk.LabelFrame(main_frame, text="生存状态", style='Dark.TLabelframe')
  108. status_frame.pack(side=tk.RIGHT, padx=15, fill=tk.Y)
  109. ttk.Label(status_frame, text="健康值:").grid(row=0, column=0, sticky=tk.W)
  110. self.health_bar = ttk.Progressbar(status_frame, length=200)
  111. self.health_bar.grid(row=0, column=1, pady=5)
  112. ttk.Label(status_frame, text="体力值:").grid(row=1, column=0, sticky=tk.W)
  113. self.stamina_bar = ttk.Progressbar(status_frame, length=200)
  114. self.stamina_bar.grid(row=1, column=1, pady=5)
  115. self.resource_labels = {}
  116. for idx, (text, key) in enumerate([('🪵 木材','木材'),('💧 淡水','淡水'),('🍎 食物','食物'),
  117. ('🐟 鱼','鱼'),('🪨 石头','石头'),('🌾 种子','种子')]):
  118. ttk.Label(status_frame, text=text).grid(row=idx+2, column=0, sticky=tk.W)
  119. self.resource_labels[key] = ttk.Label(status_frame)
  120. self.resource_labels[key].grid(row=idx+2, column=1, sticky=tk.E)
  121.  
  122. action_frame = ttk.Frame(self.root)
  123. action_frame.pack(pady=15, fill=tk.X)
  124. button_config = [
  125. ("🪓 收集", self.gather_resources), ("🏗️ 建造", self.show_build),
  126. ("🌱 种植", self.show_farm), ("💤 休息", self.rest),
  127. ("📜 日志", self.show_logs), ("📦 库存", self.show_inventory)
  128. ]
  129. for text, cmd in button_config:
  130. ttk.Button(action_frame, text=text, command=cmd, style='Action.TButton').pack(side=tk.LEFT, padx=8)
  131.  
  132. self.info_frame = ttk.LabelFrame(self.root, style='Dark.TLabelframe')
  133. self.info_frame.pack(pady=10, fill=tk.BOTH, expand=True)
  134.  
  135. self.create_log_panel()
  136. self.create_inventory_panel()
  137. self.create_build_panel()
  138. self.create_farm_panel()
  139.  
  140. def create_log_panel(self):
  141. self.log_panel = ttk.Frame(self.info_frame)
  142. log_control = ttk.Frame(self.log_panel)
  143. log_control.pack(fill=tk.X)
  144. ttk.Label(log_control, text="日志类型:").pack(side=tk.LEFT)
  145. self.filter_combo = ttk.Combobox(log_control, values=self.log_types, state='readonly')
  146. self.filter_combo.current(0)
  147. self.filter_combo.pack(side=tk.LEFT, padx=5)
  148. self.filter_combo.bind('<<ComboboxSelected>>', self.apply_log_filter)
  149. ttk.Button(log_control, text="保存存档", command=self.save_game).pack(side=tk.RIGHT)
  150. ttk.Button(log_control, text="加载存档", command=self.load_game).pack(side=tk.RIGHT, padx=5)
  151. self.log_text = tk.Text(self.log_panel, wrap=tk.WORD, state='disabled', bg=self.color['log_bg'],
  152. fg=self.color['log_fg'], font=('Consolas', 9))
  153. scrollbar = ttk.Scrollbar(self.log_panel, command=self.log_text.yview)
  154. self.log_text.configure(yscrollcommand=scrollbar.set)
  155. scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
  156. self.log_text.pack(fill=tk.BOTH, expand=True)
  157.  
  158. def create_inventory_panel(self):
  159. self.inventory_panel = ttk.Frame(self.info_frame)
  160. columns = ('资源', '数量')
  161. self.inventory_tree = ttk.Treeview(
  162. self.inventory_panel,
  163. columns=columns,
  164. show='headings',
  165. selectmode='none',
  166. style='Dark.Treeview'
  167. )
  168. for col in columns:
  169. self.inventory_tree.heading(col, text=col, anchor=tk.CENTER)
  170. self.inventory_tree.column(col, width=120, anchor=tk.CENTER)
  171. scrollbar = ttk.Scrollbar(self.inventory_panel, command=self.inventory_tree.yview)
  172. self.inventory_tree.configure(yscrollcommand=scrollbar.set)
  173. scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
  174. self.inventory_tree.pack(fill=tk.BOTH, expand=True)
  175.  
  176. def create_build_panel(self):
  177. self.build_panel = ttk.Frame(self.info_frame)
  178. status_frame = ttk.Frame(self.build_panel)
  179. status_frame.pack(fill=tk.X, pady=5)
  180.  
  181. self.build_status_labels = {}
  182. buildings = [
  183. ("住所", "提高休息恢复效率", "每级增加10%体力恢复"),
  184. ("工具", "提升收集效率", "每级增加20%收集量"),
  185. ("防御", "减少遭遇危险概率", "每级减少15%危险几率"),
  186. ("农田", "解锁种植功能", "1级解锁基础种植")
  187. ]
  188. for idx, (name, effect, detail) in enumerate(buildings):
  189. frame = ttk.Frame(status_frame)
  190. frame.grid(row=0, column=idx, padx=10)
  191. ttk.Label(frame, text=f"🏗️ {name}", font=("微软雅黑", 10, "bold")).pack()
  192. self.build_status_labels[name] = ttk.Label(frame, text="等级 0")
  193. self.build_status_labels[name].pack()
  194. ttk.Label(frame, text=detail, foreground="#888").pack()
  195.  
  196. self.build_tree_frame = ttk.Frame(self.build_panel)
  197. self.build_tree_frame.pack(fill=tk.BOTH, expand=True, pady=10)
  198.  
  199. def create_farm_panel(self):
  200. self.farm_panel = ttk.Frame(self.info_frame)
  201. self.farm_status_frame = ttk.Frame(self.farm_panel)
  202. self.farm_status_frame.pack(fill=tk.X, pady=5)
  203.  
  204. self.farm_status_labels = {
  205. 'crop': ttk.Label(self.farm_status_frame, text="当前作物:无", font=("微软雅黑", 10)),
  206. 'growth': ttk.Label(self.farm_status_frame, text="生长阶段:0/3", font=("微软雅黑", 10)),
  207. 'effect': ttk.Label(self.farm_status_frame, text="农田等级:0", font=("微软雅黑", 10))
  208. }
  209. for label in self.farm_status_labels.values():
  210. label.pack(side=tk.LEFT, padx=15)
  211.  
  212. self.farm_action_frame = ttk.Frame(self.farm_panel)
  213. self.farm_action_frame.pack(fill=tk.BOTH, expand=True)
  214. # endregion
  215.  
  216. # region 核心游戏逻辑
  217. def prev_area(self):
  218. self.current_area_idx = (self.current_area_idx - 1) % len(self.areas)
  219. self.add_time(0.5)
  220. self.update_display()
  221.  
  222. def next_area(self):
  223. self.current_area_idx = (self.current_area_idx + 1) % len(self.areas)
  224. self.add_time(0.5)
  225. self.update_display()
  226.  
  227. def generate_scene_art(self):
  228. scenes = {
  229. "沙滩": "╔══════════════════╗\n║ ________║\n║ (🌴 🏖️ 🐚) ║\n║  ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄║\n╚══════════════════╝",
  230. "棕榈树林": "╔══════════════════╗\n║ \\ | / ║\n║ '-.O.-' ║\n║ / | \\ ║\n╚══════════════════╝",
  231. "岩石海岸": "╔══════════════════╗\n║ ░░░░░▄▄▄▄▄▄▄▄▄ ║\n║ ░░▄███████████▄ ║\n╚══════════════════╝",
  232. "淡水溪流": "╔══════════════════╗\n║ ~ ~ ~ ~ ~ ~ ║\n║~ ~ ~ ~ ║\n╚══════════════════╝",
  233. "山洞": "╔══════════════════╗\n║ /\\ ║\n║ / \\ 🕳️ ║\n║ /____\\_________ ║\n╚══════════════════╝",
  234. "丛林深处": "╔══════════════════╗\n║ ▒▒▒▒▒▒▒▒▒▒▒▒ ║\n║ ▒▒▒▒▒▒▒▒▒▒▒▒▒▒ ║\n╚══════════════════╝",
  235. "废弃营地": "╔══════════════════╗\n║ ░░▄▀▄▀▀▀▀▄▀▄░░ ║\n║ ░█░░░░░░░░▀▄░ ║\n╚══════════════════╝"
  236. }
  237. return scenes.get(self.current_area, "未知区域")
  238.  
  239. def get_area_resources_info(self):
  240. resource_map = {
  241. "沙滩": {'木材': (1,3), '鱼': (1,2)},
  242. "棕榈树林": {'木材': (2,4), '食物': (1,2)},
  243. "岩石海岸": {'食物': (1,2), '石头': (1,3)},
  244. "淡水溪流": {'淡水': (2,5)},
  245. "山洞": {'石头': (3,5)},
  246. "丛林深处": {'木材': (3,5), '食物': (1,3), '种子': (1,2)},
  247. "废弃营地": {'木材': (1,4), '淡水': (1,3), '食物': (1,3),
  248. '石头': (1,2), '种子': (1,3)}
  249. }
  250. current_res = resource_map.get(self.current_area, {})
  251. return " | ".join([f"{k}({v[0]}-{v[1]})" for k,v in current_res.items()]) if current_res else "该区域没有可收集资源"
  252.  
  253. def add_time(self, hours):
  254. original_date = self.current_time.date()
  255. self.current_time += timedelta(hours=hours)
  256.  
  257. # 实时状态消耗
  258. self.health = max(0, self.health - 0.2 * hours)
  259. self.stamina = max(0, self.stamina - 0.5 * hours)
  260.  
  261. # 实时作物生长
  262. if self.farm['planted'] and self.base_levels['农田'] > 0:
  263. season_factor = 1.5 if self.seasons[self.current_time.month] == "🌸春季" else 1.0
  264. growth = hours * 0.125 * season_factor
  265. prev_stage = int(self.farm['growth_stage'])
  266. self.farm['growth_stage'] = min(3, self.farm['growth_stage'] + growth)
  267. if int(self.farm['growth_stage']) > prev_stage:
  268. self.add_log(f"作物进入第{int(self.farm['growth_stage'])}阶段", "#2ecc71", '种植')
  269.  
  270. if self.current_time.date() != original_date:
  271. self.daily_update()
  272.  
  273. # 新增状态刷新
  274. self.refresh_farm_panel()
  275. self.update_display()
  276.  
  277. def daily_update(self):
  278. if random.random() <0.3 and self.resources['食物']>0:
  279. lost = random.randint(1,2)
  280. self.resources['食物'] = max(0, self.resources['食物'] - lost)
  281. self.add_log(f"食物腐败损失{lost}单位", "#e67e22", '系统')
  282. self.refresh_inventory()
  283.  
  284. def gather_resources(self):
  285. if self.stamina < 20:
  286. self.add_log("体力不足!需要至少20体力才能收集", "#e74c3c", '危险')
  287. return
  288.  
  289. self.add_time(2)
  290. self.stamina = max(0, self.stamina - 20)
  291. resource_map = {
  292. "沙滩": {'木材':(1,3), '鱼':(1,2)},
  293. "棕榈树林": {'木材':(2,4), '食物':(1,2)},
  294. "岩石海岸": {'食物':(1,2), '石头':(1,3)},
  295. "淡水溪流": {'淡水':(2,5)},
  296. "山洞": {'石头':(3,5)},
  297. "丛林深处": {'木材':(3,5), '食物':(1,3), '种子':(1,2)},
  298. "废弃营地": {'木材':(1,4), '淡水':(1,3), '食物':(1,3), '石头':(1,2), '种子':(1,3)}
  299. }
  300. season_bonus = 1.15 if self.seasons[self.current_time.month] == "🍂秋季" else 1.0
  301. gains = {}
  302. for res, rng in resource_map.get(self.current_area, {}).items():
  303. base_gain = random.randint(rng[0], rng[1])
  304. gain = int(round(base_gain * season_bonus * self.base_levels['工具']))
  305. gains[res] = gains.get(res, 0) + gain
  306. self.resources[res] = max(0, self.resources[res] + gain)
  307.  
  308. self.add_log("收集获得:" + " ".join([f"{k}×{v}" for k,v in gains.items()]), "#2ecc71", '收集')
  309. self.refresh_inventory()
  310.  
  311. if random.random() < 0.35:
  312. self.handle_danger()
  313.  
  314. def handle_danger(self):
  315. dangers = [
  316. ("🐍 毒蛇袭击!", "需要消耗1食物治疗", '食物', 1),
  317. ("🌧️ 暴雨来袭!", "需要消耗2木材生火", '木材', 2),
  318. ("🌴 树木倒塌!", "需要消耗1石头制作工具", '石头', 1)
  319. ]
  320. danger = random.choice(dangers)
  321. res_type = danger[2]
  322. res_cost = danger[3]
  323.  
  324. if self.resources[res_type] >= res_cost:
  325. self.resources[res_type] = max(0, self.resources[res_type] - res_cost)
  326. health_loss = random.randint(5, 15)
  327. self.health = max(0, self.health - health_loss)
  328. self.add_log(f"{danger[0]} {danger[1]},处理成功!(健康-{health_loss})", "#2ecc71", '危险')
  329. else:
  330. health_loss = random.randint(25, 35)
  331. self.health = max(0, self.health - health_loss)
  332. self.add_log(f"{danger[0]} 资源不足{danger[1]},处理失败!(健康-{health_loss})", "#e74c3c", '危险')
  333. self.refresh_inventory()
  334. self.update_display()
  335.  
  336. def check_status(self):
  337. if self.health <= 0:
  338. messagebox.showinfo("游戏结束", "你的健康状况恶化,没能生存下去...")
  339. self.root.destroy()
  340. elif all(v >=50 for v in self.resources.values()) and self.base_levels['住所'] >=3:
  341. messagebox.showinfo("胜利", "你成功建造了坚固的避难所,生存希望大增!")
  342. self.root.destroy()
  343.  
  344. def rest(self):
  345. if self.resources['鱼'] <= 0 and self.resources['食物'] <= 0:
  346. messagebox.showwarning("无法休息", "需要至少1单位鱼或食物才能休息!")
  347. return
  348.  
  349. self.add_time(8)
  350. self.stamina = min(100, self.stamina + 30 + self.base_levels['住所']*10)
  351.  
  352. if self.resources['鱼'] > 0:
  353. self.resources['鱼'] = max(0, self.resources['鱼'] - 1)
  354. health_gain = 15
  355. else:
  356. self.resources['食物'] = max(0, self.resources['食物'] - 1)
  357. health_gain = 10
  358.  
  359. self.health = min(100, self.health + health_gain)
  360. self.add_log(f"休息恢复体力", "#3498db", '系统')
  361. self.refresh_inventory()
  362. self.update_display()
  363.  
  364. def build_project(self, cost, name):
  365. level_map = {"升级住所":"住所", "制作工具":"工具", "建造防御":"防御", "开辟农田":"农田"}
  366. key = level_map[name]
  367.  
  368. if all(self.resources[k] >= v for k,v in cost.items()):
  369. self.add_time(4)
  370. for k,v in cost.items():
  371. self.resources[k] = max(0, self.resources[k] - v)
  372. self.base_levels[key] += 1
  373. self.add_log(f"{name}建造完成!", "#9b59b6", '建造')
  374. self.refresh_inventory()
  375. self.refresh_build_panel()
  376. if key == "农田":
  377. self.refresh_farm_panel()
  378. self.update_display()
  379. else:
  380. messagebox.showerror("资源不足", "缺少必要资源!")
  381.  
  382. def plant_crop(self, crop_type, seeds_needed):
  383. if self.resources['种子'] < seeds_needed:
  384. messagebox.showwarning("种子不足", f"需要{seeds_needed}个种子!")
  385. return
  386. self.add_time(1)
  387. self.resources['种子'] = max(0, self.resources['种子'] - seeds_needed)
  388. self.farm.update(planted=True, growth_stage=0.0, crop_type=crop_type)
  389. self.add_log(f"种植{crop_type}成功", "#2ecc71", '种植')
  390. self.refresh_inventory()
  391. self.refresh_farm_panel() # 立即刷新农田状态
  392.  
  393. def harvest_crop(self):
  394. base_yield = 5 if self.farm['crop_type'] == "普通作物" else 15
  395. total = base_yield + self.base_levels['工具']*2 + self.base_levels['农田']*3
  396. self.resources['食物'] = max(0, self.resources['食物'] + total)
  397. self.farm['planted'] = False
  398. self.add_log(f"收获{total}单位食物", "#f1c40f", '种植')
  399. self.refresh_inventory()
  400. self.refresh_farm_panel()
  401. # endregion
  402.  
  403. # region 界面更新方法
  404. def refresh_inventory(self):
  405. self.inventory_tree.delete(*self.inventory_tree.get_children())
  406. for item, qty in self.resources.items():
  407. self.inventory_tree.insert('', 'end', values=(item, qty))
  408.  
  409. def refresh_build_panel(self):
  410. level_map = {
  411. "住所": self.base_levels['住所'],
  412. "工具": self.base_levels['工具'],
  413. "防御": self.base_levels['防御'],
  414. "农田": self.base_levels['农田']
  415. }
  416. for name, label in self.build_status_labels.items():
  417. current_level = level_map.get(name, 0)
  418. label.config(text=f"等级 {current_level}")
  419.  
  420. for widget in self.build_tree_frame.winfo_children():
  421. widget.destroy()
  422.  
  423. projects = [
  424. ("升级住所", {"木材":15, "石头":10}, "提高休息恢复效率", self.base_levels['住所'] < 5),
  425. ("制作工具", {"木材":8, "石头":5}, "提升收集效率", self.base_levels['工具'] < 3),
  426. ("建造防御", {"木材":20, "石头":15}, "减少遭遇危险概率", self.base_levels['防御'] < 3),
  427. ("开辟农田", {"木材":25, "石头":10}, "解锁种植功能", self.base_levels['农田'] == 0)
  428. ]
  429.  
  430. for name, cost, desc, condition in projects:
  431. if not condition: continue
  432. frame = ttk.Frame(self.build_tree_frame)
  433. frame.pack(pady=5, fill=tk.X, padx=10)
  434.  
  435. ttk.Label(frame, text=name, width=15, anchor=tk.W).pack(side=tk.LEFT)
  436. ttk.Label(frame, text=desc, width=25, foreground="#888").pack(side=tk.LEFT)
  437. ttk.Label(frame, text=" ".join([f"{k}×{v}" for k,v in cost.items()]),
  438. width=15, foreground="#e67e22").pack(side=tk.LEFT)
  439. ttk.Button(frame, text="建造", width=8,
  440. command=lambda c=cost.copy(),n=name: self.build_project(c,n)).pack(side=tk.RIGHT)
  441.  
  442. def refresh_farm_panel(self):
  443. self.farm_status_labels['crop'].config(
  444. text=f"当前作物:{self.farm['crop_type'] or '无'}")
  445. self.farm_status_labels['growth'].config(
  446. text=f"生长阶段:{self.farm['growth_stage']:.1f}/3")
  447. self.farm_status_labels['effect'].config(
  448. text=f"农田等级:{self.base_levels['农田']}(每级+20%产量)")
  449.  
  450. for widget in self.farm_action_frame.winfo_children():
  451. widget.destroy()
  452.  
  453. if self.base_levels['农田'] == 0:
  454. ttk.Label(self.farm_action_frame,
  455. text="需要先建造农田才能种植!",
  456. foreground="#e74c3c").pack(pady=20)
  457. return
  458.  
  459. if self.farm['planted']:
  460. if self.farm['growth_stage'] >= 3:
  461. ttk.Button(self.farm_action_frame, text="🪴 收获作物",
  462. command=self.harvest_crop,
  463. style='Action.TButton').pack(pady=15)
  464. else:
  465. ttk.Label(self.farm_action_frame,
  466. text="作物生长中,请耐心等待...",
  467. foreground="#2ecc71").pack(pady=15)
  468. else:
  469. ttk.Label(self.farm_action_frame,
  470. text="选择要种植的作物:",
  471. font=("微软雅黑", 11)).pack(pady=10)
  472.  
  473. crop_frame = ttk.Frame(self.farm_action_frame)
  474. crop_frame.pack()
  475.  
  476. if self.resources['种子'] >=1:
  477. ttk.Button(crop_frame, text="🌾 普通作物\n(需要1种子)",
  478. command=lambda: self.plant_crop("普通作物",1),
  479. width=15,
  480. style='Action.TButton').pack(side=tk.LEFT, padx=10)
  481. if self.resources['种子'] >=3:
  482. ttk.Button(crop_frame, text="🎃 高产作物\n(需要3种子)",
  483. command=lambda: self.plant_crop("高产作物",3),
  484. width=15,
  485. style='Action.TButton').pack(side=tk.LEFT, padx=10)
  486.  
  487. def update_display(self):
  488. self.area_name_label.config(text=f"🏝️ {self.current_area}")
  489. self.resource_info_label.config(text=self.get_area_resources_info())
  490. self.scene_ascii.config(text=self.generate_scene_art())
  491. self.time_label.config(text=f"🕒 {self.current_time.strftime('%Y年%m月%d日 %H:%M')}")
  492. self.season_label.config(text=f"🌡️ {self.seasons[self.current_time.month]}")
  493. self.health_bar['value'] = self.health
  494. self.stamina_bar['value'] = self.stamina
  495. for key, label in self.resource_labels.items():
  496. label.config(text=str(self.resources[key]))
  497. self.check_status()
  498.  
  499. def show_logs(self):
  500. self.hide_all_panels()
  501. self.log_panel.pack(fill=tk.BOTH, expand=True)
  502. self.info_frame.configure(text="生存日志")
  503.  
  504. def show_inventory(self):
  505. self.hide_all_panels()
  506. self.inventory_panel.pack(fill=tk.BOTH, expand=True)
  507. self.info_frame.configure(text="库存信息")
  508. self.refresh_inventory()
  509.  
  510. def show_build(self):
  511. self.hide_all_panels()
  512. self.build_panel.pack(fill=tk.BOTH, expand=True)
  513. self.info_frame.configure(text="基地建设")
  514. self.refresh_build_panel()
  515.  
  516. def show_farm(self):
  517. self.hide_all_panels()
  518. self.farm_panel.pack(fill=tk.BOTH, expand=True)
  519. self.info_frame.configure(text="农田管理")
  520. self.refresh_farm_panel()
  521.  
  522. def hide_all_panels(self):
  523. for panel in [self.log_panel, self.inventory_panel, self.build_panel, self.farm_panel]:
  524. panel.pack_forget()
  525. # endregion
  526.  
  527. # region 存档系统
  528. def save_game(self):
  529. filepath = filedialog.asksaveasfilename(
  530. defaultextension=".sav",
  531. filetypes=[("存档文件", "*.sav")]
  532. )
  533. if filepath:
  534. try:
  535. # 获取当前日志内容
  536. self.log_text.configure(state='normal')
  537. logs = self.log_text.get(1.0, "end-1c")
  538. self.log_text.configure(state='disabled')
  539.  
  540. save_data = {
  541. 'resources': self.resources,
  542. 'base_levels': self.base_levels,
  543. 'current_area_idx': self.current_area_idx,
  544. 'farm': self.farm,
  545. 'health': self.health,
  546. 'stamina': self.stamina,
  547. 'current_time': self.current_time.isoformat(),
  548. 'log_buffer': self.log_buffer,
  549. 'logs': logs
  550. }
  551. with open(filepath, 'w', encoding='utf-8') as f:
  552. json.dump(save_data, f, ensure_ascii=False, indent=2)
  553. self.add_log("游戏存档保存成功", "#27ae60", '系统')
  554. except Exception as e:
  555. messagebox.showerror("保存失败", f"无法保存存档: {str(e)}")
  556.  
  557. def load_game(self):
  558. filepath = filedialog.askopenfilename(
  559. filetypes=[("存档文件", "*.sav")]
  560. )
  561. if filepath:
  562. try:
  563. with open(filepath, 'r', encoding='utf-8') as f:
  564. save_data = json.load(f)
  565.  
  566. # 恢复游戏状态
  567. self.resources = save_data['resources']
  568. self.base_levels = save_data['base_levels']
  569. self.current_area_idx = save_data['current_area_idx']
  570. self.farm = save_data['farm']
  571. self.health = save_data['health']
  572. self.stamina = save_data['stamina']
  573. self.current_time = datetime.fromisoformat(save_data['current_time'])
  574. self.log_buffer = save_data['log_buffer']
  575.  
  576. # 恢复日志显示
  577. self.log_text.configure(state='normal')
  578. self.log_text.delete(1.0, 'end')
  579. self.log_text.insert('end', save_data['logs'])
  580. self.log_text.configure(state='disabled')
  581.  
  582. # 刷新所有界面
  583. self.update_display()
  584. self.refresh_inventory()
  585. self.refresh_build_panel()
  586. self.refresh_farm_panel()
  587. self.apply_log_filter()
  588.  
  589. self.add_log(f"成功加载存档:{os.path.basename(filepath)}", "#2980b9", '系统')
  590. except Exception as e:
  591. messagebox.showerror("加载失败", f"无效的存档文件: {str(e)}")
  592. # endregion
  593.  
  594. # region 日志系统
  595. def add_log(self, message, color="#bdc3c7", log_type='系统'):
  596. timestamp = self.current_time.strftime("[%m-%d %H:%M]")
  597. self.log_text.configure(state='normal')
  598. self.log_text.insert('end', f"{timestamp} {message}\n")
  599. line_num = int(self.log_text.index('end-1c').split('.')[0])
  600. self.log_buffer.append({'start':f"{line_num}.0", 'end':f"{line_num+1}.0", 'type':log_type})
  601. self.log_text.tag_add(log_type, "end-2l linestart", "end-1l lineend")
  602. self.log_text.tag_config(log_type, foreground=color)
  603. if line_num > self.max_log_lines: self.log_text.delete(1.0, "2.0")
  604. self.apply_log_filter()
  605. self.log_text.see('end')
  606. self.log_text.configure(state='disabled')
  607. if SOUND_ENABLED: self.play_sound(log_type)
  608.  
  609. def apply_log_filter(self, event=None):
  610. filter_type = self.filter_combo.get()
  611. self.log_text.configure(state='normal')
  612. self.log_text.tag_remove('hidden', 1.0, 'end')
  613. if filter_type != '全部':
  614. for log in self.log_buffer:
  615. if log['type'] != filter_type:
  616. self.log_text.tag_add('hidden', log['start'], log['end'])
  617. self.log_text.tag_configure('hidden', elide=True)
  618. self.log_text.configure(state='disabled')
  619.  
  620. def play_sound(self, log_type):
  621. sound_map = {'危险':'alert', '收集':'collect', '建造':'build', '系统':'system', '种植':'plant'}
  622. try:
  623. sound = pygame.mixer.Sound(f"sounds/{sound_map.get(log_type, 'default')}.wav")
  624. sound.set_volume(0.3)
  625. sound.play()
  626. except: pass
  627. # endregion
  628.  
  629. if __name__ == "__main__":
  630. root = tk.Tk()
  631. game = IslandSurvivalGame(root)
  632. root.mainloop()
  633.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement