This commit is contained in:
2025-06-16 07:59:50 +08:00
commit 7a6cd423fc
54 changed files with 4068 additions and 0 deletions

136
scripts/core/GameScene.cs Normal file
View File

@ -0,0 +1,136 @@
using Godot;
using System;
using System.Collections.Generic;
public partial class GameScene : Control
{
// 资源类型枚举
public enum ResourceType
{
IronOre,
CopperOre,
IronIngot,
CopperIngot
}
// 资源数据结构
public class ResourceData
{
public string Name { get; set; }
public int Amount { get; set; }
public ResourceType Type { get; set; }
public bool IsProcessed { get; set; }
}
// 电力系统数据
private float powerGeneration = 0;
private float powerConsumption = 0;
private float powerStorage = 0;
private float powerDischarge = 0;
// 库存数据保留用于兼容性但主要由InventoryManager管理
private Dictionary<ResourceType, ResourceData> inventory = new Dictionary<ResourceType, ResourceData>();
// UI引用
private Label powerGenerationLabel;
private Label powerConsumptionLabel;
private Label powerStorageLabel;
private Label powerDischargeLabel;
private TabContainer categoryTabs;
private CraftingQueueManager craftingQueue;
public override void _Ready()
{
GD.Print("GameScene _Ready 开始");
// 获取UI引用
powerGenerationLabel = GetNode<Label>("HSplitContainer/LeftPanel/VBoxContainer/PowerInfo/MarginContainer/VBoxContainer/PowerRow1/PowerGeneration");
powerConsumptionLabel = GetNode<Label>("HSplitContainer/LeftPanel/VBoxContainer/PowerInfo/MarginContainer/VBoxContainer/PowerRow1/PowerConsumption");
powerStorageLabel = GetNode<Label>("HSplitContainer/LeftPanel/VBoxContainer/PowerInfo/MarginContainer/VBoxContainer/PowerRow2/PowerStorage");
powerDischargeLabel = GetNode<Label>("HSplitContainer/LeftPanel/VBoxContainer/PowerInfo/MarginContainer/VBoxContainer/PowerRow2/PowerDischarge");
categoryTabs = GetNode<TabContainer>("HSplitContainer/RightPanel/VBoxContainer/CategoryTabs");
craftingQueue = GetNode<CraftingQueueManager>("HSplitContainer/LeftPanel/VBoxContainer/CraftingQueue");
// 初始化库存(保留用于兼容性)
InitializeInventory();
// 更新UI
UpdatePowerUI();
GD.Print("GameScene 初始化完成");
}
private void InitializeInventory()
{
inventory[ResourceType.IronOre] = new ResourceData { Name = "铁矿", Amount = 0, Type = ResourceType.IronOre, IsProcessed = false };
inventory[ResourceType.CopperOre] = new ResourceData { Name = "铜矿", Amount = 0, Type = ResourceType.CopperOre, IsProcessed = false };
inventory[ResourceType.IronIngot] = new ResourceData { Name = "铁块", Amount = 0, Type = ResourceType.IronIngot, IsProcessed = true };
inventory[ResourceType.CopperIngot] = new ResourceData { Name = "铜块", Amount = 0, Type = ResourceType.CopperIngot, IsProcessed = true };
}
private void UpdatePowerUI()
{
powerGenerationLabel.Text = $"发电: {powerGeneration:F1} KW";
powerConsumptionLabel.Text = $"耗电: {powerConsumption:F1} KW";
powerStorageLabel.Text = $"蓄电: {powerStorage:F1} KWh";
powerDischargeLabel.Text = $"放电: {powerDischarge:F1} KW";
}
// 添加资源到库存(保留用于兼容性)
public void AddResource(ResourceType type, int amount)
{
if (inventory.ContainsKey(type))
{
inventory[type].Amount += amount;
}
}
// 更新电力系统
public void UpdatePowerSystem(float generation, float consumption, float storage, float discharge)
{
powerGeneration = generation;
powerConsumption = consumption;
powerStorage = storage;
powerDischarge = discharge;
UpdatePowerUI();
}
public override void _Process(double delta)
{
// 更新电力信息显示
UpdatePowerInfo();
}
private void UpdatePowerInfo()
{
// 这里可以从电力管理器获取实际数据
// 目前使用占位符数据
if (powerGenerationLabel != null)
powerGenerationLabel.Text = "发电: 0 KW";
if (powerConsumptionLabel != null)
powerConsumptionLabel.Text = "耗电: 0 KW";
if (powerStorageLabel != null)
powerStorageLabel.Text = "蓄电: 0 KWh";
if (powerDischargeLabel != null)
powerDischargeLabel.Text = "放电: 0 KW";
}
public override void _Input(InputEvent @event)
{
if (@event is InputEventKey keyEvent && keyEvent.Pressed)
{
// 按C键测试合成铁块
if (keyEvent.Keycode == Key.C)
{
if (craftingQueue != null)
{
craftingQueue.StartIronIngotCrafting();
GD.Print("按下C键尝试开始铁块合成");
}
}
}
}
}

View File

@ -0,0 +1,143 @@
using Godot;
using System.Collections.Generic;
using System.Text.Json;
public partial class CraftingRecipeManager : Node
{
public static CraftingRecipeManager Instance { get; private set; }
public class Ingredient
{
public string ItemId { get; set; }
public int Quantity { get; set; }
}
public class CraftingRecipe
{
public string Id { get; set; }
public string OutputItem { get; set; }
public int OutputQuantity { get; set; }
public string CraftingMethod { get; set; }
public float CraftingTime { get; set; }
public List<Ingredient> Ingredients { get; set; } = new List<Ingredient>();
}
public class CraftingRecipeData
{
public List<CraftingRecipe> Recipes { get; set; } = new List<CraftingRecipe>();
}
private CraftingRecipeData recipeData;
private Dictionary<string, CraftingRecipe> recipeMap = new Dictionary<string, CraftingRecipe>();
private Dictionary<string, List<CraftingRecipe>> outputItemMap = new Dictionary<string, List<CraftingRecipe>>();
public override void _Ready()
{
if (Instance == null)
{
Instance = this;
LoadCraftingRecipes();
}
else
{
QueueFree();
}
}
private void LoadCraftingRecipes()
{
string configPath = "res://data/config/crafting_recipes.json";
if (!FileAccess.FileExists(configPath))
{
GD.PrintErr($"合成配方配置文件不存在: {configPath}");
return;
}
using var file = FileAccess.Open(configPath, FileAccess.ModeFlags.Read);
if (file == null)
{
GD.PrintErr($"无法打开合成配方配置文件: {configPath}");
return;
}
string jsonContent = file.GetAsText();
try
{
var options = new JsonSerializerOptions
{
PropertyNameCaseInsensitive = true
};
recipeData = JsonSerializer.Deserialize<CraftingRecipeData>(jsonContent, options);
if (recipeData?.Recipes != null)
{
// 构建配方映射
foreach (var recipe in recipeData.Recipes)
{
recipeMap[recipe.Id] = recipe;
// 按输出物品分组
if (!outputItemMap.ContainsKey(recipe.OutputItem))
{
outputItemMap[recipe.OutputItem] = new List<CraftingRecipe>();
}
outputItemMap[recipe.OutputItem].Add(recipe);
GD.Print($"加载合成配方: {recipe.Id} - {recipe.OutputItem} ({recipe.CraftingMethod})");
}
GD.Print($"成功加载 {recipeData.Recipes.Count} 个合成配方");
}
}
catch (JsonException e)
{
GD.PrintErr($"解析合成配方配置文件失败: {e.Message}");
}
}
public List<CraftingRecipe> GetAllRecipes()
{
return recipeData?.Recipes ?? new List<CraftingRecipe>();
}
public CraftingRecipe GetRecipe(string recipeId)
{
return recipeMap.GetValueOrDefault(recipeId);
}
public List<CraftingRecipe> GetRecipesForItem(string itemId)
{
return outputItemMap.GetValueOrDefault(itemId) ?? new List<CraftingRecipe>();
}
public bool CanCraft(string recipeId)
{
var recipe = GetRecipe(recipeId);
if (recipe == null || InventoryManager.Instance == null)
{
return false;
}
// 检查是否有足够的材料
foreach (var ingredient in recipe.Ingredients)
{
if (InventoryManager.Instance.GetItemQuantity(ingredient.ItemId) < ingredient.Quantity)
{
return false;
}
}
return true;
}
public override void _ExitTree()
{
if (Instance == this)
{
Instance = null;
}
}
}

197
scripts/data/GameData.cs Normal file
View File

@ -0,0 +1,197 @@
using Godot;
using System;
using System.Collections.Generic;
using System.Linq;
public partial class GameData : Node
{
// 物品分类枚举
public enum ItemCategory
{
RawMaterial, // 原材料
ProcessedMaterial, // 冶炼成品
Building, // 建筑
Component, // 组件
Product // 产品
}
// 物品数据结构
public class ItemData
{
public string Id { get; set; } // 物品ID
public string Name { get; set; } // 物品名称
public ItemCategory Category { get; set; } // 物品分类
public string Description { get; set; } // 物品描述
public Dictionary<string, int> Recipe { get; set; } // 合成配方
public float CraftTime { get; set; } // 合成时间
public float PowerConsumption { get; set; } // 耗电量
public string IconPath { get; set; } // 图标路径
}
// 单例实例
private static GameData instance;
public static GameData Instance
{
get
{
return instance;
}
}
// 物品数据字典
private Dictionary<string, ItemData> items = new Dictionary<string, ItemData>();
public override void _Ready()
{
instance = this; // 设置单例实例
LoadItemsFromCSV();
}
// 从CSV文件加载物品数据
private void LoadItemsFromCSV()
{
try
{
// 读取CSV文件
string csvPath = "res://data/config/items.csv";
if (!Godot.FileAccess.FileExists(csvPath))
{
GD.PrintErr("物品数据文件不存在: " + csvPath);
return;
}
var file = Godot.FileAccess.Open(csvPath, Godot.FileAccess.ModeFlags.Read);
if (file == null)
{
GD.PrintErr("无法打开物品数据文件: " + csvPath);
return;
}
// 读取标题行
string header = file.GetLine();
string[] headers = header.Split(',');
// 读取数据行
while (!file.EofReached())
{
string line = file.GetLine();
if (string.IsNullOrEmpty(line)) continue;
string[] values = line.Split(',');
if (values.Length != headers.Length) continue;
// 创建物品数据
var item = new ItemData
{
Id = values[0],
Name = values[1],
Category = (ItemCategory)Enum.Parse(typeof(ItemCategory), values[2]),
Description = values[3],
Recipe = ParseRecipe(values[4]),
CraftTime = float.Parse(values[5]),
PowerConsumption = float.Parse(values[6]),
IconPath = values[7]
};
AddItem(item);
}
file.Close();
GD.Print("成功加载物品数据");
}
catch (Exception e)
{
GD.PrintErr("加载物品数据时出错: " + e.Message);
}
}
// 解析配方字符串
private Dictionary<string, int> ParseRecipe(string recipeStr)
{
if (string.IsNullOrEmpty(recipeStr) || recipeStr == "null")
return null;
var recipe = new Dictionary<string, int>();
string[] pairs = recipeStr.Split(';');
foreach (string pair in pairs)
{
string[] parts = pair.Split(':');
if (parts.Length == 2)
{
string itemId = parts[0];
int amount = int.Parse(parts[1]);
recipe[itemId] = amount;
}
}
return recipe;
}
// 添加物品
private void AddItem(ItemData item)
{
items[item.Id] = item;
}
// 获取物品数据
public ItemData GetItem(string id)
{
if (items.ContainsKey(id))
{
return items[id];
}
return null;
}
// 获取所有物品
public Dictionary<string, ItemData> GetAllItems()
{
return items;
}
// 获取指定分类的所有物品
public Dictionary<string, ItemData> GetItemsByCategory(ItemCategory category)
{
var result = new Dictionary<string, ItemData>();
foreach (var item in items)
{
if (item.Value.Category == category)
{
result[item.Key] = item.Value;
}
}
return result;
}
// 检查是否有足够的材料进行合成
public bool HasEnoughMaterials(string itemId, Dictionary<string, int> inventory)
{
var item = GetItem(itemId);
if (item == null || item.Recipe == null) return false;
foreach (var requirement in item.Recipe)
{
if (!inventory.ContainsKey(requirement.Key) ||
inventory[requirement.Key] < requirement.Value)
{
return false;
}
}
return true;
}
// 计算合成所需时间
public float GetCraftTime(string itemId)
{
var item = GetItem(itemId);
return item?.CraftTime ?? 0f;
}
// 计算合成所需电力
public float GetPowerConsumption(string itemId)
{
var item = GetItem(itemId);
return item?.PowerConsumption ?? 0f;
}
}

View File

@ -0,0 +1,169 @@
using Godot;
using System;
using System.Collections.Generic;
using System.Text.Json;
public partial class ResourceCategoryManager : Node
{
// 资源分类数据结构
public class ResourceCategory
{
public string CategoryName { get; set; }
public List<string> ItemIds { get; set; }
}
// 单例实例
private static ResourceCategoryManager instance;
public static ResourceCategoryManager Instance
{
get
{
return instance;
}
}
// 资源分类列表
private List<ResourceCategory> categories = new List<ResourceCategory>();
public override void _Ready()
{
GD.Print("ResourceCategoryManager _Ready 开始");
instance = this; // 设置单例实例
LoadResourceCategories();
}
// 从JSON文件加载资源分类配置
private void LoadResourceCategories()
{
try
{
string jsonPath = "res://data/config/resource_categories.json";
GD.Print($"尝试加载配置文件: {jsonPath}");
if (!Godot.FileAccess.FileExists(jsonPath))
{
GD.PrintErr("资源分类配置文件不存在: " + jsonPath);
return;
}
var file = Godot.FileAccess.Open(jsonPath, Godot.FileAccess.ModeFlags.Read);
if (file == null)
{
GD.PrintErr("无法打开资源分类配置文件: " + jsonPath);
return;
}
string jsonContent = file.GetAsText();
file.Close();
// GD.Print($"JSON文件内容长度: {jsonContent.Length}");
// GD.Print($"JSON文件内容: {jsonContent}");
// 解析JSON
var options = new JsonSerializerOptions
{
PropertyNameCaseInsensitive = true
};
categories = JsonSerializer.Deserialize<List<ResourceCategory>>(jsonContent, options);
if (categories == null)
{
GD.PrintErr("JSON反序列化结果为null");
categories = new List<ResourceCategory>();
return;
}
GD.Print($"成功加载资源分类配置,共 {categories.Count} 个分类");
// 打印每个分类的详细信息
foreach (var category in categories)
{
GD.Print($"分类: {category.CategoryName}, 物品数量: {category.ItemIds?.Count ?? 0}");
if (category.ItemIds != null)
{
foreach (var itemId in category.ItemIds)
{
GD.Print($" - {itemId}");
}
}
}
}
catch (Exception e)
{
GD.PrintErr("加载资源分类配置时出错: " + e.Message);
GD.PrintErr("堆栈跟踪: " + e.StackTrace);
}
}
// 获取所有分类
public List<ResourceCategory> GetAllCategories()
{
GD.Print($"GetAllCategories 被调用,返回 {categories.Count} 个分类");
return categories;
}
// 根据分类名称获取分类
public ResourceCategory GetCategoryByName(string categoryName)
{
return categories.Find(c => c.CategoryName == categoryName);
}
// 根据物品ID获取所属分类
public ResourceCategory GetCategoryByItemId(string itemId)
{
return categories.Find(c => c.ItemIds.Contains(itemId));
}
// 获取指定分类的所有物品数据
public Dictionary<string, GameData.ItemData> GetItemsByCategory(string categoryName)
{
GD.Print($"GetItemsByCategory 被调用,分类名称: {categoryName}");
var category = GetCategoryByName(categoryName);
if (category == null)
{
GD.PrintErr($"未找到分类: {categoryName}");
return new Dictionary<string, GameData.ItemData>();
}
GD.Print($"找到分类 {categoryName},包含 {category.ItemIds?.Count ?? 0} 个物品ID");
// 检查GameData.Instance
if (GameData.Instance == null)
{
GD.PrintErr("GameData.Instance 为 null");
return new Dictionary<string, GameData.ItemData>();
}
var result = new Dictionary<string, GameData.ItemData>();
foreach (string itemId in category.ItemIds)
{
// GD.Print($"尝试获取物品: {itemId}");
var item = GameData.Instance.GetItem(itemId);
if (item != null)
{
GD.Print($"成功获取物品: {itemId} - {item.Name}");
result[itemId] = item;
}
else
{
GD.PrintErr($"未找到物品: {itemId}");
}
}
GD.Print($"GetItemsByCategory 返回 {result.Count} 个物品");
return result;
}
// 获取分类名称列表
public List<string> GetCategoryNames()
{
var names = new List<string>();
foreach (var category in categories)
{
names.Add(category.CategoryName);
}
return names;
}
}

View File

@ -0,0 +1,121 @@
using Godot;
using System.Collections.Generic;
using System.Text.Json;
public partial class InventoryCategoryManager : Node
{
public static InventoryCategoryManager Instance { get; private set; }
public class InventoryCategory
{
public string CategoryName { get; set; }
public List<string> Items { get; set; } = new List<string>();
}
public class InventoryCategoryData
{
public List<InventoryCategory> Categories { get; set; } = new List<InventoryCategory>();
}
private InventoryCategoryData categoryData;
private Dictionary<string, InventoryCategory> categoryMap = new Dictionary<string, InventoryCategory>();
public override void _Ready()
{
if (Instance == null)
{
Instance = this;
LoadInventoryCategories();
}
else
{
QueueFree();
}
}
private void LoadInventoryCategories()
{
string configPath = "res://data/config/inventory_categories.json";
if (!FileAccess.FileExists(configPath))
{
GD.PrintErr($"库存分类配置文件不存在: {configPath}");
return;
}
using var file = FileAccess.Open(configPath, FileAccess.ModeFlags.Read);
if (file == null)
{
GD.PrintErr($"无法打开库存分类配置文件: {configPath}");
return;
}
string jsonContent = file.GetAsText();
try
{
var options = new JsonSerializerOptions
{
PropertyNameCaseInsensitive = true
};
categoryData = JsonSerializer.Deserialize<InventoryCategoryData>(jsonContent, options);
if (categoryData?.Categories != null)
{
// 构建分类映射
foreach (var category in categoryData.Categories)
{
categoryMap[category.CategoryName] = category;
GD.Print($"加载库存分类: {category.CategoryName}, 包含 {category.Items.Count} 个物品");
}
GD.Print($"成功加载 {categoryData.Categories.Count} 个库存分类");
}
}
catch (JsonException e)
{
GD.PrintErr($"解析库存分类配置文件失败: {e.Message}");
}
}
public List<InventoryCategory> GetAllCategories()
{
return categoryData?.Categories ?? new List<InventoryCategory>();
}
public InventoryCategory GetCategory(string categoryName)
{
return categoryMap.GetValueOrDefault(categoryName);
}
public Dictionary<string, GameData.ItemData> GetItemsByCategory(string categoryName)
{
var result = new Dictionary<string, GameData.ItemData>();
var category = GetCategory(categoryName);
if (category == null || GameData.Instance == null)
{
return result;
}
foreach (var itemId in category.Items)
{
var itemData = GameData.Instance.GetItem(itemId);
if (itemData != null)
{
result[itemId] = itemData;
}
}
return result;
}
public override void _ExitTree()
{
if (Instance == this)
{
Instance = null;
}
}
}

View File

@ -0,0 +1,368 @@
using Godot;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
public partial class InventoryManager : Node
{
// 库存数据结构
public class InventoryItem
{
public string ItemId { get; set; }
public int Quantity { get; set; }
public InventoryItem(string itemId, int quantity = 0)
{
ItemId = itemId;
Quantity = quantity;
}
}
// 单例实例
private static InventoryManager instance;
public static InventoryManager Instance
{
get
{
return instance;
}
}
// 库存数据字典 - 物品ID -> 库存项
private Dictionary<string, InventoryItem> inventory = new Dictionary<string, InventoryItem>();
// 线程锁
private readonly object inventoryLock = new object();
// 事件委托
public delegate void InventoryChangedEventHandler(string itemId, int oldQuantity, int newQuantity);
public event InventoryChangedEventHandler InventoryChanged;
public override void _Ready()
{
GD.Print("InventoryManager _Ready 开始");
// 确保单例
if (instance == null)
{
instance = this;
InitializeInventory();
}
else
{
GD.PrintErr("InventoryManager 实例已存在!");
QueueFree();
}
}
// 初始化库存
private void InitializeInventory()
{
GD.Print("初始化库存系统");
lock (inventoryLock)
{
// 为所有已知物品创建库存条目初始数量为0
if (GameData.Instance != null)
{
var allItems = GameData.Instance.GetAllItems();
foreach (var item in allItems)
{
inventory[item.Key] = new InventoryItem(item.Key, 0);
}
GD.Print($"初始化了 {inventory.Count} 个物品的库存条目");
}
else
{
GD.PrintErr("GameData.Instance 为 null无法初始化库存");
}
}
// 添加一些测试数据
AddTestData();
}
// 添加测试数据
private void AddTestData()
{
GD.Print("添加测试库存数据");
AddItem("iron_ore", 100);
AddItem("copper_ore", 50);
AddItem("coal_ore", 75);
AddItem("water", 200);
AddItem("iron_ingot", 25);
AddItem("copper_ingot", 15);
}
// 添加物品到库存
public bool AddItem(string itemId, int quantity)
{
if (quantity <= 0) return false;
lock (inventoryLock)
{
int oldQuantity = GetItemQuantityUnsafe(itemId);
if (!inventory.ContainsKey(itemId))
{
inventory[itemId] = new InventoryItem(itemId, quantity);
}
else
{
inventory[itemId].Quantity += quantity;
}
int newQuantity = inventory[itemId].Quantity;
GD.Print($"添加物品: {itemId} +{quantity} (总量: {newQuantity})");
// 在锁外触发事件
CallDeferred(nameof(TriggerInventoryChanged), itemId, oldQuantity, newQuantity);
return true;
}
}
// 从库存中移除物品
public bool RemoveItem(string itemId, int quantity)
{
if (quantity <= 0) return false;
lock (inventoryLock)
{
if (!inventory.ContainsKey(itemId)) return false;
int oldQuantity = inventory[itemId].Quantity;
if (oldQuantity < quantity) return false; // 库存不足
inventory[itemId].Quantity -= quantity;
int newQuantity = inventory[itemId].Quantity;
GD.Print($"移除物品: {itemId} -{quantity} (剩余: {newQuantity})");
// 在锁外触发事件
CallDeferred(nameof(TriggerInventoryChanged), itemId, oldQuantity, newQuantity);
return true;
}
}
// 设置物品数量
public void SetItemQuantity(string itemId, int quantity)
{
lock (inventoryLock)
{
int oldQuantity = GetItemQuantityUnsafe(itemId);
if (!inventory.ContainsKey(itemId))
{
inventory[itemId] = new InventoryItem(itemId, quantity);
}
else
{
inventory[itemId].Quantity = quantity;
}
GD.Print($"设置物品数量: {itemId} = {quantity}");
// 在锁外触发事件
CallDeferred(nameof(TriggerInventoryChanged), itemId, oldQuantity, quantity);
}
}
// 获取物品数量(线程安全)
public int GetItemQuantity(string itemId)
{
lock (inventoryLock)
{
return GetItemQuantityUnsafe(itemId);
}
}
// 获取物品数量(非线程安全,内部使用)
private int GetItemQuantityUnsafe(string itemId)
{
if (inventory.ContainsKey(itemId))
{
return inventory[itemId].Quantity;
}
return 0;
}
// 检查是否有足够的物品
public bool HasEnoughItems(string itemId, int requiredQuantity)
{
return GetItemQuantity(itemId) >= requiredQuantity;
}
// 检查是否有足够的材料(用于配方检查)
public bool HasEnoughMaterials(Dictionary<string, int> recipe)
{
if (recipe == null) return true;
lock (inventoryLock)
{
foreach (var requirement in recipe)
{
if (GetItemQuantityUnsafe(requirement.Key) < requirement.Value)
{
return false;
}
}
return true;
}
}
// 消耗材料(用于生产)
public bool ConsumeMaterials(Dictionary<string, int> recipe)
{
if (recipe == null) return true;
lock (inventoryLock)
{
// 先检查是否有足够材料
foreach (var requirement in recipe)
{
if (GetItemQuantityUnsafe(requirement.Key) < requirement.Value)
{
return false;
}
}
// 消耗材料
foreach (var requirement in recipe)
{
int oldQuantity = GetItemQuantityUnsafe(requirement.Key);
inventory[requirement.Key].Quantity -= requirement.Value;
int newQuantity = inventory[requirement.Key].Quantity;
// 在锁外触发事件
CallDeferred(nameof(TriggerInventoryChanged), requirement.Key, oldQuantity, newQuantity);
}
return true;
}
}
// 获取所有库存物品
public Dictionary<string, InventoryItem> GetAllInventory()
{
lock (inventoryLock)
{
var result = new Dictionary<string, InventoryItem>();
foreach (var item in inventory)
{
result[item.Key] = new InventoryItem(item.Value.ItemId, item.Value.Quantity);
}
return result;
}
}
// 获取有库存的物品(数量>0
public Dictionary<string, InventoryItem> GetAvailableItems()
{
lock (inventoryLock)
{
var result = new Dictionary<string, InventoryItem>();
foreach (var item in inventory)
{
if (item.Value.Quantity > 0)
{
result[item.Key] = new InventoryItem(item.Value.ItemId, item.Value.Quantity);
}
}
return result;
}
}
// 获取指定分类的库存物品
public Dictionary<string, InventoryItem> GetInventoryByCategory(GameData.ItemCategory category)
{
lock (inventoryLock)
{
var result = new Dictionary<string, InventoryItem>();
foreach (var item in inventory)
{
var itemData = GameData.Instance?.GetItem(item.Key);
if (itemData != null && itemData.Category == category)
{
result[item.Key] = new InventoryItem(item.Value.ItemId, item.Value.Quantity);
}
}
return result;
}
}
// 清空库存
public void ClearInventory()
{
Dictionary<string, int> oldQuantities;
lock (inventoryLock)
{
oldQuantities = new Dictionary<string, int>();
foreach (var item in inventory)
{
oldQuantities[item.Key] = item.Value.Quantity;
item.Value.Quantity = 0;
}
GD.Print("清空所有库存");
}
// 在锁外触发事件
foreach (var item in oldQuantities)
{
if (item.Value > 0)
{
CallDeferred(nameof(TriggerInventoryChanged), item.Key, item.Value, 0);
}
}
}
// 获取库存总数量
public int GetTotalItemCount()
{
lock (inventoryLock)
{
return inventory.Values.Sum(item => item.Quantity);
}
}
// 调试:打印所有库存
public void PrintInventory()
{
lock (inventoryLock)
{
GD.Print("=== 当前库存 ===");
foreach (var item in inventory)
{
if (item.Value.Quantity > 0)
{
var itemData = GameData.Instance?.GetItem(item.Key);
string itemName = itemData?.Name ?? item.Key;
GD.Print($"{itemName}: {item.Value.Quantity}");
}
}
GD.Print("===============");
}
}
// 触发库存变化事件(在主线程中调用)
private void TriggerInventoryChanged(string itemId, int oldQuantity, int newQuantity)
{
InventoryChanged?.Invoke(itemId, oldQuantity, newQuantity);
}
// 清理单例
public override void _ExitTree()
{
if (instance == this)
{
instance = null;
}
}
}

View File

@ -0,0 +1,265 @@
using Godot;
using System.Collections.Generic;
public partial class InventoryTableManager : VBoxContainer
{
private PackedScene inventoryItemScene;
private Dictionary<string, GridContainer> categoryContainers = new Dictionary<string, GridContainer>();
public override void _Ready()
{
GD.Print("InventoryTableManager _Ready 开始");
// 加载库存物品场景
inventoryItemScene = GD.Load<PackedScene>("res://scenes/InventoryItem.tscn");
if (inventoryItemScene == null)
{
GD.PrintErr("无法加载InventoryItem场景");
return;
}
// 初始化库存显示
InitializeInventoryDisplay();
// 订阅库存变化事件
if (InventoryManager.Instance != null)
{
InventoryManager.Instance.InventoryChanged += OnInventoryChanged;
}
GD.Print("InventoryTableManager 初始化完成");
}
private void InitializeInventoryDisplay()
{
GD.Print("初始化库存Table显示");
// 等待InventoryCategoryManager初始化
if (InventoryCategoryManager.Instance == null)
{
CallDeferred(nameof(InitializeInventoryDisplay));
return;
}
CreateCategoryBlocks();
UpdateInventoryDisplay();
}
private void CreateCategoryBlocks()
{
// 清空现有内容
foreach (Node child in GetChildren())
{
child.QueueFree();
}
categoryContainers.Clear();
var categories = InventoryCategoryManager.Instance.GetAllCategories();
foreach (var category in categories)
{
CreateCategoryBlock(category);
}
}
private void CreateCategoryBlock(InventoryCategoryManager.InventoryCategory category)
{
GD.Print($"创建库存分类块: {category.CategoryName}");
// 创建分类容器
var categoryContainer = new VBoxContainer();
categoryContainer.Name = $"{category.CategoryName}Block";
// 添加顶部间距
var topSpacer = new Control();
topSpacer.CustomMinimumSize = new Vector2(0, 10);
categoryContainer.AddChild(topSpacer);
// 创建标题行
var titleContainer = new HBoxContainer();
// 分类名称标签
var titleLabel = new Label();
titleLabel.Text = category.CategoryName;
titleLabel.HorizontalAlignment = HorizontalAlignment.Left;
titleLabel.AddThemeFontSizeOverride("font_size", 14);
titleLabel.Modulate = new Color(0.9f, 0.9f, 0.9f, 1.0f);
titleContainer.AddChild(titleLabel);
// 添加小间距
var labelSpacer = new Control();
labelSpacer.CustomMinimumSize = new Vector2(10, 0);
titleContainer.AddChild(labelSpacer);
// HSeparator 横线分隔符
var separator = new HSeparator();
separator.SizeFlagsHorizontal = Control.SizeFlags.ExpandFill;
separator.SizeFlagsVertical = Control.SizeFlags.ShrinkCenter;
titleContainer.AddChild(separator);
categoryContainer.AddChild(titleContainer);
// 添加小间距
var spacer = new Control();
spacer.CustomMinimumSize = new Vector2(0, 5);
categoryContainer.AddChild(spacer);
// 创建物品列表容器 - 使用GridContainer实现每行2个物品
var itemsContainer = new GridContainer();
itemsContainer.Name = $"{category.CategoryName}Items";
itemsContainer.Columns = 2; // 每行2列
itemsContainer.SizeFlagsHorizontal = Control.SizeFlags.ExpandFill;
itemsContainer.AddThemeConstantOverride("h_separation", 4); // 减少水平间距
itemsContainer.AddThemeConstantOverride("v_separation", 4); // 垂直间距
categoryContainer.AddChild(itemsContainer);
// 保存容器引用
categoryContainers[category.CategoryName] = itemsContainer;
// 添加到主容器
AddChild(categoryContainer);
}
private void OnInventoryChanged(string itemId, int oldQuantity, int newQuantity)
{
GD.Print($"库存Table变化: {itemId} {oldQuantity} -> {newQuantity}");
UpdateInventoryDisplay();
}
private void UpdateInventoryDisplay()
{
if (InventoryManager.Instance == null || InventoryCategoryManager.Instance == null)
{
return;
}
// 清空所有分类的物品显示
foreach (var container in categoryContainers.Values)
{
foreach (Node child in container.GetChildren())
{
child.QueueFree();
}
}
// 获取所有分类并更新显示
var categories = InventoryCategoryManager.Instance.GetAllCategories();
foreach (var category in categories)
{
UpdateCategoryDisplay(category);
}
}
private void UpdateCategoryDisplay(InventoryCategoryManager.InventoryCategory category)
{
if (!categoryContainers.ContainsKey(category.CategoryName))
{
return;
}
var container = categoryContainers[category.CategoryName];
var items = InventoryCategoryManager.Instance.GetItemsByCategory(category.CategoryName);
foreach (var kvp in items)
{
var itemId = kvp.Key;
var itemData = kvp.Value;
// 获取库存数量
int quantity = InventoryManager.Instance.GetItemQuantity(itemId);
// 只显示有库存的物品或者显示所有物品包括0数量
// 这里我们选择显示所有物品0数量的显示为灰色
CreateInventoryItemDisplay(container, itemData, quantity);
}
}
private void CreateInventoryItemDisplay(GridContainer container, GameData.ItemData itemData, int quantity)
{
// 实例化库存物品UI
var inventoryItem = inventoryItemScene.Instantiate<Control>();
if (inventoryItem == null)
{
GD.PrintErr($"无法实例化InventoryItem for {itemData.Name}");
return;
}
// 设置尺寸标志,让物品能够填充分配的空间
inventoryItem.SizeFlagsHorizontal = Control.SizeFlags.ExpandFill;
inventoryItem.SizeFlagsVertical = Control.SizeFlags.ShrinkCenter;
// 设置图标
var iconTexture = inventoryItem.GetNode<TextureRect>("MarginContainer/HBoxContainer/IconTexture");
if (iconTexture != null && !string.IsNullOrEmpty(itemData.IconPath))
{
// 检查文件是否存在
if (Godot.FileAccess.FileExists(itemData.IconPath))
{
var texture = GD.Load<Texture2D>(itemData.IconPath);
if (texture != null)
{
iconTexture.Texture = texture;
}
}
else
{
// 使用默认图标
var defaultIcon = GD.Load<Texture2D>("res://assets/textures/icon.svg");
if (defaultIcon != null)
{
iconTexture.Texture = defaultIcon;
}
}
}
// 设置名称
var nameLabel = inventoryItem.GetNode<Label>("MarginContainer/HBoxContainer/NameLabel");
if (nameLabel != null)
{
nameLabel.Text = itemData.Name;
// 如果数量为0设置为灰色
if (quantity == 0)
{
nameLabel.Modulate = new Color(0.6f, 0.6f, 0.6f, 1.0f);
}
else
{
nameLabel.Modulate = new Color(1.0f, 1.0f, 1.0f, 1.0f);
}
}
// 设置数量
var quantityLabel = inventoryItem.GetNode<Label>("MarginContainer/HBoxContainer/QuantityLabel");
if (quantityLabel != null)
{
quantityLabel.Text = quantity.ToString();
// 根据数量设置颜色
if (quantity == 0)
{
quantityLabel.Modulate = new Color(0.6f, 0.6f, 0.6f, 1.0f);
}
else if (quantity < 10)
{
quantityLabel.Modulate = new Color(1.0f, 0.8f, 0.4f, 1.0f); // 橙色 - 库存较低
}
else
{
quantityLabel.Modulate = new Color(0.8f, 1.0f, 0.8f, 1.0f); // 绿色 - 库存充足
}
}
container.AddChild(inventoryItem);
}
public override void _ExitTree()
{
// 取消订阅事件
if (InventoryManager.Instance != null)
{
InventoryManager.Instance.InventoryChanged -= OnInventoryChanged;
}
}
}

View File

@ -0,0 +1,384 @@
using Godot;
using System.Collections.Generic;
public partial class CraftingQueueManager : Panel
{
public class CraftingQueueItem
{
public string RecipeId { get; set; }
public int Quantity { get; set; } = 1;
public float RemainingTime { get; set; }
public float TotalTime { get; set; }
public bool IsActive { get; set; }
}
private const int MAX_QUEUE_SIZE = 8;
private List<CraftingQueueItem> craftingQueue = new List<CraftingQueueItem>();
private List<Panel> slotPanels = new List<Panel>();
public override void _Ready()
{
GD.Print("CraftingQueueManager _Ready 开始");
// 获取所有槽位面板
var queueContainer = GetNode<HBoxContainer>("MarginContainer/VBoxContainer/QueueContainer");
for (int i = 1; i <= MAX_QUEUE_SIZE; i++)
{
var slot = queueContainer.GetNode<Panel>($"Slot{i}");
slotPanels.Add(slot);
}
// 初始化队列显示
UpdateQueueDisplay();
GD.Print("CraftingQueueManager 初始化完成");
}
public override void _Process(double delta)
{
ProcessCrafting((float)delta);
}
private void ProcessCrafting(float deltaTime)
{
if (craftingQueue.Count == 0) return;
// 处理第一个(当前正在制作的)物品
var currentItem = craftingQueue[0];
if (!currentItem.IsActive)
{
// 开始制作
currentItem.IsActive = true;
GD.Print($"开始制作: {currentItem.RecipeId}");
// 重新更新显示以确保进度条正确初始化
UpdateQueueDisplay();
return; // 这一帧先不处理时间让UI先更新
}
currentItem.RemainingTime -= deltaTime;
if (currentItem.RemainingTime <= 0)
{
// 制作完成
CompleteCrafting(currentItem);
craftingQueue.RemoveAt(0);
UpdateQueueDisplay();
}
else
{
// 更新进度显示
float progress = 1.0f - (currentItem.RemainingTime / currentItem.TotalTime);
UpdateSlotProgress(0, progress);
}
}
private void CompleteCrafting(CraftingQueueItem item)
{
var recipe = CraftingRecipeManager.Instance?.GetRecipe(item.RecipeId);
if (recipe == null || InventoryManager.Instance == null)
{
GD.PrintErr($"无法完成制作: {item.RecipeId}");
return;
}
// 添加产品到库存(数量 = 配方产出数量 × 批量数量)
int totalOutputQuantity = recipe.OutputQuantity * item.Quantity;
InventoryManager.Instance.AddItem(recipe.OutputItem, totalOutputQuantity);
GD.Print($"制作完成: {recipe.OutputItem} x{totalOutputQuantity} (批量: {item.Quantity})");
}
public bool AddToQueue(string recipeId, int quantity = 1)
{
if (craftingQueue.Count >= MAX_QUEUE_SIZE)
{
GD.Print("合成队列已满");
return false;
}
var recipe = CraftingRecipeManager.Instance?.GetRecipe(recipeId);
if (recipe == null)
{
GD.PrintErr($"找不到配方: {recipeId}");
return false;
}
// 检查是否有足够的材料制作指定数量
foreach (var ingredient in recipe.Ingredients)
{
int requiredQuantity = ingredient.Quantity * quantity;
if (InventoryManager.Instance.GetItemQuantity(ingredient.ItemId) < requiredQuantity)
{
GD.Print($"材料不足,无法制作 {quantity} 个: {recipeId}");
return false;
}
}
// 扣除材料(数量 = 配方需求 × 批量数量)
foreach (var ingredient in recipe.Ingredients)
{
int totalRequired = ingredient.Quantity * quantity;
InventoryManager.Instance.RemoveItem(ingredient.ItemId, totalRequired);
GD.Print($"扣除材料: {ingredient.ItemId} x{totalRequired} (批量: {quantity})");
}
// 计算总制作时间(时间 = 基础时间 × 数量)
float totalCraftingTime = recipe.CraftingTime * quantity;
var queueItem = new CraftingQueueItem
{
RecipeId = recipeId,
Quantity = quantity,
RemainingTime = totalCraftingTime,
TotalTime = totalCraftingTime,
IsActive = false
};
craftingQueue.Add(queueItem);
UpdateQueueDisplay();
GD.Print($"添加到合成队列: {recipeId} x{quantity},总时间: {totalCraftingTime}s已扣除材料");
return true;
}
private void UpdateQueueDisplay()
{
// 清空所有槽位
for (int i = 0; i < slotPanels.Count; i++)
{
ClearSlot(i);
}
// 显示队列中的物品
for (int i = 0; i < craftingQueue.Count && i < slotPanels.Count; i++)
{
var queueItem = craftingQueue[i];
var recipe = CraftingRecipeManager.Instance?.GetRecipe(queueItem.RecipeId);
if (recipe != null)
{
UpdateSlotDisplay(i, recipe, queueItem);
}
}
}
private void UpdateSlotDisplay(int slotIndex, CraftingRecipeManager.CraftingRecipe recipe, CraftingQueueItem queueItem)
{
var slot = slotPanels[slotIndex];
// 立即清除现有的子节点而不是使用QueueFree
var childrenToRemove = new List<Node>();
foreach (Node child in slot.GetChildren())
{
childrenToRemove.Add(child);
}
foreach (Node child in childrenToRemove)
{
slot.RemoveChild(child);
child.QueueFree();
}
// 创建背景层(灰色)
var backgroundRect = new ColorRect();
backgroundRect.Name = "Background";
backgroundRect.Color = new Color(0.3f, 0.3f, 0.3f, 1.0f);
backgroundRect.AnchorLeft = 0.0f;
backgroundRect.AnchorTop = 0.0f;
backgroundRect.AnchorRight = 1.0f;
backgroundRect.AnchorBottom = 1.0f;
slot.AddChild(backgroundRect);
// 创建图标显示层
var iconTexture = new TextureRect();
iconTexture.Name = "ProductIcon";
iconTexture.ExpandMode = TextureRect.ExpandModeEnum.FitWidthProportional;
iconTexture.StretchMode = TextureRect.StretchModeEnum.KeepAspectCentered;
iconTexture.AnchorLeft = 0.1f;
iconTexture.AnchorTop = 0.1f;
iconTexture.AnchorRight = 0.9f;
iconTexture.AnchorBottom = 0.9f;
// 获取产物的图标
var outputItemData = GameData.Instance?.GetItem(recipe.OutputItem);
if (outputItemData != null && !string.IsNullOrEmpty(outputItemData.IconPath))
{
// 尝试加载物品图标
if (FileAccess.FileExists(outputItemData.IconPath))
{
var texture = GD.Load<Texture2D>(outputItemData.IconPath);
if (texture != null)
{
iconTexture.Texture = texture;
GD.Print($"槽位{slotIndex}加载产物图标: {outputItemData.IconPath}");
}
else
{
// 使用默认图标
LoadDefaultIcon(iconTexture);
}
}
else
{
// 使用默认图标
LoadDefaultIcon(iconTexture);
}
}
else
{
// 使用默认图标
LoadDefaultIcon(iconTexture);
}
slot.AddChild(iconTexture);
// 创建进度层(白色半透明,覆盖在图标上面)
var progressRect = new ColorRect();
progressRect.Name = "Progress";
progressRect.AnchorLeft = 0.0f;
progressRect.AnchorRight = 1.0f;
progressRect.AnchorBottom = 1.0f;
progressRect.Color = new Color(1.0f, 1.0f, 1.0f, 0.3f); // 白色透明度0.3
// 根据是否激活设置初始进度
if (queueItem.IsActive)
{
float progress = 1.0f - (queueItem.RemainingTime / queueItem.TotalTime);
progressRect.AnchorTop = 1.0f - progress; // 从下往上填充
GD.Print($"槽位{slotIndex}初始化进度条,进度: {progress:F2}");
}
else
{
progressRect.AnchorTop = 1.0f; // 等待状态,无进度显示
}
slot.AddChild(progressRect);
// 添加数量标签如果数量大于1
if (queueItem.Quantity > 1)
{
var quantityLabel = new Label();
quantityLabel.Name = "QuantityLabel";
quantityLabel.Text = queueItem.Quantity.ToString();
quantityLabel.AnchorLeft = 0.6f;
quantityLabel.AnchorTop = 0.6f;
quantityLabel.AnchorRight = 1.0f;
quantityLabel.AnchorBottom = 1.0f;
quantityLabel.HorizontalAlignment = HorizontalAlignment.Center;
quantityLabel.VerticalAlignment = VerticalAlignment.Center;
quantityLabel.AddThemeStyleboxOverride("normal", new StyleBoxFlat());
var styleBox = quantityLabel.GetThemeStylebox("normal") as StyleBoxFlat;
if (styleBox != null)
{
styleBox.BgColor = new Color(0.2f, 0.2f, 0.2f, 0.8f); // 半透明黑色背景
styleBox.CornerRadiusTopLeft = 3;
styleBox.CornerRadiusTopRight = 3;
styleBox.CornerRadiusBottomLeft = 3;
styleBox.CornerRadiusBottomRight = 3;
}
quantityLabel.AddThemeColorOverride("font_color", new Color(1.0f, 1.0f, 1.0f, 1.0f)); // 白色文字
quantityLabel.AddThemeFontSizeOverride("font_size", 8);
slot.AddChild(quantityLabel);
}
// 重置槽位颜色为默认
slot.Modulate = new Color(1.0f, 1.0f, 1.0f, 1.0f);
}
private void LoadDefaultIcon(TextureRect iconTexture)
{
var defaultIcon = GD.Load<Texture2D>("res://assets/textures/icon.svg");
if (defaultIcon != null)
{
iconTexture.Texture = defaultIcon;
GD.Print("使用默认图标 icon.svg");
}
else
{
GD.PrintErr("无法加载默认图标 icon.svg");
}
}
private void UpdateSlotProgress(int slotIndex, float progress)
{
if (slotIndex >= slotPanels.Count)
{
GD.PrintErr($"UpdateSlotProgress: 无效的槽位索引 {slotIndex}");
return;
}
var slot = slotPanels[slotIndex];
if (slot == null || !IsInstanceValid(slot))
{
GD.PrintErr($"UpdateSlotProgress: 槽位{slotIndex}无效");
return;
}
// 安全获取Progress节点
ColorRect progressRect = null;
try
{
if (slot.HasNode("Progress"))
{
progressRect = slot.GetNode<ColorRect>("Progress");
}
else
{
GD.PrintErr($"UpdateSlotProgress: 槽位{slotIndex}没有Progress节点");
return;
}
}
catch (System.Exception e)
{
GD.PrintErr($"UpdateSlotProgress: 获取Progress节点失败: {e.Message}");
return;
}
if (progressRect != null && IsInstanceValid(progressRect))
{
// 从下往上填充progress为0时AnchorTop为1.0progress为1时AnchorTop为0.0
float anchorTop = 1.0f - progress;
progressRect.AnchorTop = anchorTop;
// GD.Print($"更新槽位{slotIndex}进度: {progress:F2}, AnchorTop: {anchorTop:F2}");
}
else
{
GD.PrintErr($"UpdateSlotProgress: 槽位{slotIndex}的Progress节点无效");
}
}
private void ClearSlot(int slotIndex)
{
var slot = slotPanels[slotIndex];
// 立即清除子节点
var childrenToRemove = new List<Node>();
foreach (Node child in slot.GetChildren())
{
childrenToRemove.Add(child);
}
foreach (Node child in childrenToRemove)
{
slot.RemoveChild(child);
child.QueueFree();
}
// 为空槽位添加灰色背景
var backgroundRect = new ColorRect();
backgroundRect.Name = "Background";
backgroundRect.Color = new Color(0.2f, 0.2f, 0.2f, 1.0f); // 更深的灰色表示空槽位
backgroundRect.AnchorLeft = 0.0f;
backgroundRect.AnchorTop = 0.0f;
backgroundRect.AnchorRight = 1.0f;
backgroundRect.AnchorBottom = 1.0f;
slot.AddChild(backgroundRect);
// 重置槽位颜色
slot.Modulate = new Color(1.0f, 1.0f, 1.0f, 1.0f);
}
// 公共方法,供外部调用添加铁块制作
public void StartIronIngotCrafting()
{
AddToQueue("iron_ingot_smelting");
}
}

View File

@ -0,0 +1,192 @@
using Godot;
public partial class ManualCollectionPanel : Control
{
// 采集相关参数
private const float COLLECTION_TIME = 1.0f; // 采集时间1秒
// 状态变量
private bool isCollecting = false;
private float collectionProgress = 0.0f;
private string itemId;
// UI引用
private ColorRect progressFill;
private Color originalProgressColor;
private Color collectingProgressColor = new Color(1.0f, 0.8f, 0.3f, 1.0f); // 采集时的橙色
public override void _Ready()
{
GD.Print("ManualCollectionPanel _Ready 开始");
// 获取进度条引用 - 现在需要从父节点获取
var parent = GetParent<Control>();
if (parent != null)
{
progressFill = parent.GetNode<ColorRect>("MarginContainer/VBoxContainer/ProgressContainer/ProgressFill");
if (progressFill != null)
{
originalProgressColor = progressFill.Color;
GD.Print("成功获取进度条引用");
}
else
{
GD.PrintErr("无法获取进度条引用");
}
}
else
{
GD.PrintErr("无法获取父节点");
}
// 连接鼠标事件
GuiInput += OnGuiInput;
GD.Print("已连接鼠标事件");
GD.Print("ManualCollectionPanel _Ready 完成");
}
// 设置物品ID
public void SetItemId(string id)
{
itemId = id;
GD.Print($"设置手动采集面板物品ID: {itemId}");
}
// 处理输入事件
private void OnGuiInput(InputEvent @event)
{
if (@event is InputEventMouseButton mouseEvent)
{
if (mouseEvent.ButtonIndex == MouseButton.Left)
{
//打印鼠标事件
GD.Print($"鼠标事件: {mouseEvent}");
if (mouseEvent.Pressed)
{
// 开始采集
StartCollection();
}
else
{
// 停止采集
StopCollection();
}
}
}
}
// 开始采集
private void StartCollection()
{
if (string.IsNullOrEmpty(itemId)) return;
isCollecting = true;
collectionProgress = 0.0f;
// 改变进度条颜色表示正在采集
if (progressFill != null)
{
progressFill.Color = collectingProgressColor;
}
GD.Print($"开始采集: {itemId}");
}
// 停止采集
private void StopCollection()
{
if (!isCollecting) return;
isCollecting = false;
collectionProgress = 0.0f;
// 恢复进度条
UpdateProgressBar();
// 恢复原始颜色
if (progressFill != null)
{
progressFill.Color = originalProgressColor;
}
GD.Print($"停止采集: {itemId}");
}
// 完成采集
private void CompleteCollection()
{
if (string.IsNullOrEmpty(itemId)) return;
// 添加物品到库存
if (InventoryManager.Instance != null)
{
InventoryManager.Instance.AddItem(itemId, 1);
GD.Print($"采集完成,获得: {itemId} x1");
}
// 重置采集状态
collectionProgress = 0.0f;
// 如果还在按住,继续下一轮采集
if (isCollecting)
{
GD.Print($"继续采集: {itemId}");
}
else
{
// 恢复进度条显示
UpdateProgressBar();
if (progressFill != null)
{
progressFill.Color = originalProgressColor;
}
}
}
// 更新进度条显示
private void UpdateProgressBar()
{
if (progressFill != null)
{
if (isCollecting)
{
// 采集中显示当前进度
progressFill.AnchorRight = collectionProgress;
}
else
{
// 非采集状态显示满进度(表示可采集)
progressFill.AnchorRight = 0f;
}
}
}
public override void _Process(double delta)
{
if (isCollecting)
{
// 更新采集进度
collectionProgress += (float)delta / COLLECTION_TIME;
// 限制进度在0-1之间
collectionProgress = Mathf.Clamp(collectionProgress, 0.0f, 1.0f);
// 更新进度条显示
UpdateProgressBar();
// 检查是否完成采集
if (collectionProgress >= 1.0f)
{
CompleteCollection();
}
}
}
// 清理
public override void _ExitTree()
{
GuiInput -= OnGuiInput;
}
}

View File

@ -0,0 +1,33 @@
using Godot;
using System.Collections.Generic;
public partial class ResourceGrid : GridContainer
{
[Export]
public PackedScene ItemPanelScene;
public override void _Ready()
{
// 获取基础资源分类的所有物品
var items = ResourceCategoryManager.Instance.GetItemsByCategory("基础资源");
foreach (var item in items.Values)
{
var panel = (Panel)ItemPanelScene.Instantiate();
// 设置图标为白色底色
var icon = panel.GetNode<TextureRect>("HBoxContainer/Icon");
icon.Texture = null;
icon.Modulate = new Color(1, 1, 1, 1); // 白色
// 设置名称
var nameLabel = panel.GetNode<Label>("HBoxContainer/VBoxContainer/TopRow/NameLabel");
nameLabel.Text = item.Name;
// 其余内容可根据需要设置
// ...
AddChild(panel);
}
}
}

View File

@ -0,0 +1,733 @@
using Godot;
using System.Collections.Generic;
public partial class DynamicTabManager : TabContainer
{
private PackedScene itemPanelScene;
private PackedScene craftingItemScene;
public override void _Ready()
{
GD.Print("DynamicTabManager _Ready 开始");
// 设置标签靠左对齐
TabAlignment = TabBar.AlignmentMode.Left;
// 加载ItemPanel场景用于生产线
itemPanelScene = GD.Load<PackedScene>("res://scenes/ItemPanel.tscn");
if (itemPanelScene == null)
{
GD.PrintErr("无法加载ItemPanel场景");
return;
}
// 加载CraftingItem场景用于合成
craftingItemScene = GD.Load<PackedScene>("res://scenes/CraftingItem.tscn");
if (craftingItemScene == null)
{
GD.PrintErr("无法加载CraftingItem场景");
return;
}
GD.Print("开始初始化标签页");
InitializeTabs();
}
private void InitializeTabs()
{
GD.Print("开始创建固定标签页");
// 清空现有标签页
foreach (Node child in GetChildren())
{
child.QueueFree();
}
// 创建固定的标签页
CreateFixedTabs();
GD.Print("成功创建固定标签页");
}
private void CreateFixedTabs()
{
// 创建"合成"标签
CreateTabForCrafting();
// 创建"生产线"标签
CreateTabForProduction();
}
private void CreateTabForCrafting()
{
GD.Print("创建合成标签");
// 创建合成标签的滚动容器
var scrollContainer = new ScrollContainer();
scrollContainer.Name = "CraftingScroll";
// 创建垂直容器来放置所有分类块
var vboxContainer = new VBoxContainer();
vboxContainer.SizeFlagsHorizontal = Control.SizeFlags.ExpandFill;
vboxContainer.SizeFlagsVertical = Control.SizeFlags.ExpandFill;
scrollContainer.AddChild(vboxContainer);
// 获取所有分类
var categoryManager = ResourceCategoryManager.Instance;
if (categoryManager == null)
{
GD.PrintErr("ResourceCategoryManager 实例为null");
return;
}
var allCategories = categoryManager.GetAllCategories();
// 为合成相关的分类创建块
foreach (var category in allCategories)
{
// 合成标签包含:手动采集、冶炼、建筑设施
if (category.CategoryName == "手动采集" ||
category.CategoryName == "冶炼" ||
category.CategoryName == "建筑设施")
{
CreateCategoryBlock(vboxContainer, category, "合成");
}
}
// 添加到TabContainer
AddChild(scrollContainer);
SetTabTitle(GetTabCount() - 1, "合成");
}
private void CreateTabForProduction()
{
GD.Print("创建生产线标签");
// 创建生产线标签的滚动容器
var scrollContainer = new ScrollContainer();
scrollContainer.Name = "ProductionScroll";
// 创建垂直容器来放置所有分类块
var vboxContainer = new VBoxContainer();
vboxContainer.SizeFlagsHorizontal = Control.SizeFlags.ExpandFill;
vboxContainer.SizeFlagsVertical = Control.SizeFlags.ExpandFill;
scrollContainer.AddChild(vboxContainer);
// 获取所有分类
var categoryManager = ResourceCategoryManager.Instance;
if (categoryManager == null)
{
GD.PrintErr("ResourceCategoryManager 实例为null");
return;
}
var allCategories = categoryManager.GetAllCategories();
// 为生产线相关的分类创建块
foreach (var category in allCategories)
{
// 生产线标签包含:生产设备
if (category.CategoryName == "生产设备")
{
CreateCategoryBlock(vboxContainer, category, "生产线");
}
}
// 添加到TabContainer
AddChild(scrollContainer);
SetTabTitle(GetTabCount() - 1, "生产线");
}
private void CreateCategoryBlock(VBoxContainer parentContainer, ResourceCategoryManager.ResourceCategory category, string tabType)
{
GD.Print($"创建分类块: {category.CategoryName}");
// 创建分类块的容器
var categoryContainer = new VBoxContainer();
categoryContainer.Name = $"{category.CategoryName}Block";
// 添加间距
var topSpacer = new Control();
topSpacer.CustomMinimumSize = new Vector2(0, 10);
categoryContainer.AddChild(topSpacer);
// 创建标题行(分类名称 + 横线)
var titleContainer = new HBoxContainer();
// 分类名称标签
var titleLabel = new Label();
titleLabel.Text = category.CategoryName;
titleLabel.HorizontalAlignment = HorizontalAlignment.Left;
titleContainer.AddChild(titleLabel);
// 添加小间距
var labelSpacer = new Control();
labelSpacer.CustomMinimumSize = new Vector2(10, 0);
titleContainer.AddChild(labelSpacer);
// HSeparator 横线分隔符
var separator = new HSeparator();
separator.SizeFlagsHorizontal = Control.SizeFlags.ExpandFill;
separator.SizeFlagsVertical = Control.SizeFlags.ShrinkCenter;
titleContainer.AddChild(separator);
categoryContainer.AddChild(titleContainer);
// 添加小间距
var spacer = new Control();
spacer.CustomMinimumSize = new Vector2(0, 5);
categoryContainer.AddChild(spacer);
// 创建物品网格 - 使用HFlowContainer实现自适应宽度
var flowContainer = new HFlowContainer();
flowContainer.Name = $"{category.CategoryName}Grid";
flowContainer.SizeFlagsHorizontal = Control.SizeFlags.ExpandFill;
flowContainer.AddThemeConstantOverride("h_separation", 10); // 水平间距
flowContainer.AddThemeConstantOverride("v_separation", 8); // 垂直间距
// 添加该分类的所有物品
AddItemsToFlow(flowContainer, category.CategoryName, tabType);
categoryContainer.AddChild(flowContainer);
// 添加到父容器
parentContainer.AddChild(categoryContainer);
}
private void AddItemsToFlow(HFlowContainer flowContainer, string categoryName, string tabType)
{
GD.Print($"为分类 '{categoryName}' 添加物品到流容器,标签类型: {tabType}");
var categoryManager = ResourceCategoryManager.Instance;
if (categoryManager == null)
{
GD.PrintErr("ResourceCategoryManager 实例为null");
return;
}
var items = categoryManager.GetItemsByCategory(categoryName);
GD.Print($"分类 '{categoryName}' 中有 {items.Count} 个物品");
foreach (var kvp in items)
{
var itemId = kvp.Key;
var itemData = kvp.Value;
GD.Print($"创建物品面板: {itemId} - {itemData.Name}");
Control itemPanel;
// 手动采集始终使用ItemPanel保持按住采集功能
if (categoryName == "手动采集")
{
// 手动采集使用ItemPanel
itemPanel = itemPanelScene.Instantiate<Control>();
if (itemPanel == null)
{
GD.PrintErr($"无法实例化ItemPanel for {itemId}");
continue;
}
// 添加手动采集脚本
var manualCollectionScript = new ManualCollectionPanel();
manualCollectionScript.SetAnchorsAndOffsetsPreset(Control.LayoutPreset.FullRect);
manualCollectionScript.MouseFilter = Control.MouseFilterEnum.Stop; // 拦截鼠标事件
itemPanel.AddChild(manualCollectionScript);
manualCollectionScript.SetItemId(itemId);
GD.Print($"为 {itemId} 添加手动采集功能");
// 设置物品数据(手动采集不是生产设备)
SetupItemPanel(itemPanel, itemData, false);
}
// 其他合成物品根据标签类型选择面板
else if (tabType == "合成")
{
// 合成标签的非手动采集物品使用CraftingItem
itemPanel = craftingItemScene.Instantiate<Control>();
if (itemPanel == null)
{
GD.PrintErr($"无法实例化CraftingItem for {itemId}");
continue;
}
// 设置合成物品数据
SetupCraftingItem(itemPanel, itemData, categoryName);
}
else
{
// 生产线标签使用ItemPanel
itemPanel = itemPanelScene.Instantiate<Control>();
if (itemPanel == null)
{
GD.PrintErr($"无法实例化ItemPanel for {itemId}");
continue;
}
// 判断是否为生产设备
bool isProductionDevice = categoryName != "手动采集";
// 设置物品数据
SetupItemPanel(itemPanel, itemData, isProductionDevice);
}
// 添加到流容器
flowContainer.AddChild(itemPanel);
}
}
private void SetupItemPanel(Control itemPanel, GameData.ItemData itemData, bool isProductionDevice = true)
{
try
{
// 设置图标
var iconTexture = itemPanel.GetNode<TextureRect>("MarginContainer/VBoxContainer/TopRow/IconTexture");
if (iconTexture != null && !string.IsNullOrEmpty(itemData.IconPath))
{
// 检查文件是否存在
if (Godot.FileAccess.FileExists(itemData.IconPath))
{
var texture = GD.Load<Texture2D>(itemData.IconPath);
if (texture != null)
{
iconTexture.Texture = texture;
GD.Print($"设置图标成功: {itemData.IconPath}");
}
else
{
GD.PrintErr($"无法加载图标: {itemData.IconPath}");
}
}
else
{
GD.Print($"图标文件不存在: {itemData.IconPath},使用默认图标");
// 默认使用icon.svg
var defaultIcon = GD.Load<Texture2D>("res://assets/textures/icon.svg");
if (defaultIcon != null)
{
iconTexture.Texture = defaultIcon;
}
else
{
GD.PrintErr("无法加载默认图标-1");
}
}
}
// 设置名称
var nameLabel = itemPanel.GetNode<Label>("MarginContainer/VBoxContainer/TopRow/MiddleContainer/TopInfoRow/NameLabel");
if (nameLabel != null)
{
nameLabel.Text = itemData.Name;
GD.Print($"设置名称成功: {itemData.Name}");
}
// 设置产率
var productionLabel = itemPanel.GetNode<Label>("MarginContainer/VBoxContainer/TopRow/MiddleContainer/TopInfoRow/ProductionLabel");
if (productionLabel != null)
{
if (isProductionDevice)
{
productionLabel.Text = "0/s"; // 生产设备显示产率
}
else
{
productionLabel.Text = "手动"; // 手动采集显示"手动"
productionLabel.Modulate = new Color(0.8f, 1.0f, 0.8f, 1.0f); // 淡绿色
}
}
// 根据isProductionDevice决定是否显示设备相关UI
var rightContainer = itemPanel.GetNode<VBoxContainer>("MarginContainer/VBoxContainer/TopRow/RightContainer");
if (rightContainer != null)
{
rightContainer.Visible = isProductionDevice;
}
if (isProductionDevice)
{
// 设置设备数量
var deviceLabel = itemPanel.GetNode<Label>("MarginContainer/VBoxContainer/TopRow/RightContainer/BottomDeviceRow/DeviceLabel");
if (deviceLabel != null)
{
deviceLabel.Text = "设备: 0"; // 默认设备数量
}
// 设置功耗
var powerLabel = itemPanel.GetNode<Label>("MarginContainer/VBoxContainer/TopRow/RightContainer/PowerLabel");
if (powerLabel != null)
{
powerLabel.Text = "-0W"; // 默认功耗
}
}
// 设置进度条
var progressFill = itemPanel.GetNode<ColorRect>("MarginContainer/VBoxContainer/ProgressContainer/ProgressFill");
if (progressFill != null)
{
if (isProductionDevice)
{
progressFill.AnchorRight = 0.0f; // 生产设备默认0%进度
}
else
{
// 手动采集默认0%进度,采集时会动态变化
progressFill.AnchorRight = 0.0f; // 0% 进度
progressFill.Color = new Color(0.3f, 0.8f, 0.3f, 1.0f); // 绿色
}
}
}
catch (System.Exception e)
{
GD.PrintErr($"设置ItemPanel时出错: {e.Message}");
}
}
private void SetupCraftingItem(Control craftingItem, GameData.ItemData itemData, string categoryName)
{
try
{
// 设置图标
var iconTexture = craftingItem.GetNode<TextureRect>("MarginContainer/HBoxContainer/IconTexture");
if (iconTexture != null && !string.IsNullOrEmpty(itemData.IconPath))
{
// 检查文件是否存在
if (Godot.FileAccess.FileExists(itemData.IconPath))
{
var texture = GD.Load<Texture2D>(itemData.IconPath);
if (texture != null)
{
iconTexture.Texture = texture;
GD.Print($"设置合成物品图标成功: {itemData.IconPath}");
}
else
{
LoadDefaultIconForCrafting(iconTexture);
}
}
else
{
GD.Print($"合成物品图标文件不存在: {itemData.IconPath},使用默认图标");
LoadDefaultIconForCrafting(iconTexture);
}
}
// 设置名称
var nameLabel = craftingItem.GetNode<Label>("MarginContainer/HBoxContainer/MiddleContainer/NameLabel");
if (nameLabel != null)
{
nameLabel.Text = itemData.Name;
GD.Print($"设置合成物品名称成功: {itemData.Name}");
}
// 从合成配方系统获取真实信息
var recipes = CraftingRecipeManager.Instance?.GetRecipesForItem(itemData.Id);
var recipe = recipes?.Count > 0 ? recipes[0] : null;
// 设置材料需求(现在在物品名称下面)
var materialsLabel = craftingItem.GetNode<Label>("MarginContainer/HBoxContainer/MiddleContainer/MaterialsLabel");
if (materialsLabel != null)
{
if (recipe != null && recipe.Ingredients.Count > 0)
{
// 显示第一个材料,如果有多个材料可以显示"..."
var firstIngredient = recipe.Ingredients[0];
var itemName = GameData.Instance?.GetItem(firstIngredient.ItemId)?.Name ?? firstIngredient.ItemId;
if (recipe.Ingredients.Count == 1)
{
materialsLabel.Text = $"材料: {firstIngredient.Quantity}x{itemName}";
}
else
{
materialsLabel.Text = $"材料: {firstIngredient.Quantity}x{itemName}...";
}
}
else
{
materialsLabel.Text = "无需材料";
}
}
// 设置合成时间(现在在材料下面)
var craftTimeLabel = craftingItem.GetNode<Label>("MarginContainer/HBoxContainer/MiddleContainer/InfoRow/CraftTimeLabel");
if (craftTimeLabel != null)
{
if (recipe != null)
{
craftTimeLabel.Text = $"{recipe.CraftingTime:F1}s";
}
else
{
craftTimeLabel.Text = "无配方";
craftTimeLabel.Modulate = new Color(1.0f, 0.5f, 0.5f, 1.0f); // 红色表示无配方
}
}
// 设置合成方式(现在在材料下面)
var methodLabel = craftingItem.GetNode<Label>("MarginContainer/HBoxContainer/MiddleContainer/InfoRow/MethodLabel");
if (methodLabel != null)
{
if (recipe != null)
{
methodLabel.Text = recipe.CraftingMethod;
}
else if (categoryName == "手动采集")
{
methodLabel.Text = "手动";
}
else if (categoryName == "冶炼")
{
methodLabel.Text = "冶炼";
}
else
{
methodLabel.Text = "制作";
}
}
// 设置合成按钮
var craftButton = craftingItem.GetNode<Button>("MarginContainer/HBoxContainer/RightContainer/CraftButton");
if (craftButton != null)
{
// 如果没有配方,禁用按钮
if (recipe == null)
{
craftButton.Disabled = true;
craftButton.Text = "无配方";
craftButton.Modulate = new Color(0.6f, 0.6f, 0.6f, 1.0f);
}
else
{
craftButton.Disabled = false;
craftButton.Text = "合成";
craftButton.Modulate = new Color(1.0f, 1.0f, 1.0f, 1.0f);
// 连接按钮点击事件
craftButton.Pressed += () => OnCraftButtonPressed(itemData.Id, craftingItem);
}
}
// 设置数量控制组件
SetupQuantityControls(craftingItem, recipe != null);
}
catch (System.Exception e)
{
GD.PrintErr($"设置CraftingItem时出错: {e.Message}");
}
}
private void LoadDefaultIconForCrafting(TextureRect iconTexture)
{
var defaultIcon = GD.Load<Texture2D>("res://assets/textures/icon.svg");
if (defaultIcon != null)
{
iconTexture.Texture = defaultIcon;
}
else
{
GD.PrintErr("无法加载默认图标");
}
}
private void OnCraftButtonPressed(string itemId, Control craftingItem)
{
GD.Print($"点击合成按钮: {itemId}");
// 检查合成配方管理器是否可用
if (CraftingRecipeManager.Instance == null)
{
GD.PrintErr("CraftingRecipeManager 实例为null无法进行合成");
return;
}
// 查询该物品的合成配方
var recipes = CraftingRecipeManager.Instance.GetRecipesForItem(itemId);
if (recipes == null || recipes.Count == 0)
{
GD.Print($"物品 {itemId} 没有找到合成配方");
return;
}
// 使用第一个找到的配方(后续可以扩展为让用户选择)
var recipe = recipes[0];
GD.Print($"找到合成配方: {recipe.Id} - {recipe.OutputItem}");
// 获取数量输入框的值
int quantity = 1;
try
{
var quantityInput = craftingItem.GetNode<LineEdit>("MarginContainer/HBoxContainer/RightContainer/QuantityContainer/QuantityInput");
if (quantityInput != null)
{
quantity = GetQuantityValue(quantityInput);
}
}
catch (System.Exception e)
{
GD.PrintErr($"获取数量输入值时出错: {e.Message}");
quantity = 1; // 默认为1
}
GD.Print($"准备合成 {quantity} 个 {itemId}");
// 检查是否有足够的材料制作指定数量
bool canCraftAll = true;
var insufficientMaterials = new List<string>();
foreach (var ingredient in recipe.Ingredients)
{
int currentAmount = InventoryManager.Instance?.GetItemQuantity(ingredient.ItemId) ?? 0;
int requiredAmount = ingredient.Quantity * quantity;
if (currentAmount < requiredAmount)
{
canCraftAll = false;
var itemName = GameData.Instance?.GetItem(ingredient.ItemId)?.Name ?? ingredient.ItemId;
insufficientMaterials.Add($"{itemName} (需要 {requiredAmount}, 当前 {currentAmount})");
}
}
if (!canCraftAll)
{
GD.Print($"材料不足,无法合成 {quantity} 个 {itemId}");
foreach (var material in insufficientMaterials)
{
GD.Print($"缺少材料: {material}");
}
return;
}
// 获取合成队列管理器
var craftingQueue = GetCraftingQueueManager();
if (craftingQueue == null)
{
GD.PrintErr("无法找到CraftingQueueManager无法添加到合成队列");
return;
}
// 批量添加到合成队列(一次性添加指定数量)
bool success = craftingQueue.AddToQueue(recipe.Id, quantity);
if (success)
{
GD.Print($"成功添加 {quantity} 个 {itemId} 到合成队列");
}
else
{
GD.Print($"添加 {itemId} 到合成队列失败(可能队列已满)");
}
}
private CraftingQueueManager GetCraftingQueueManager()
{
// 从场景树中查找CraftingQueueManager
// 它应该在GameScene下的左侧面板中
var gameScene = GetTree().CurrentScene;
if (gameScene == null)
{
GD.PrintErr("无法获取当前场景");
return null;
}
// 尝试通过路径查找CraftingQueueManager
var craftingQueue = gameScene.GetNode<CraftingQueueManager>("HSplitContainer/LeftPanel/VBoxContainer/CraftingQueue");
if (craftingQueue == null)
{
GD.PrintErr("无法找到CraftingQueueManager节点");
}
return craftingQueue;
}
private void SetupQuantityControls(Control craftingItem, bool hasRecipe)
{
try
{
var quantityInput = craftingItem.GetNode<LineEdit>("MarginContainer/HBoxContainer/RightContainer/QuantityContainer/QuantityInput");
var minusButton = craftingItem.GetNode<Button>("MarginContainer/HBoxContainer/RightContainer/QuantityContainer/MinusButton");
var plusButton = craftingItem.GetNode<Button>("MarginContainer/HBoxContainer/RightContainer/QuantityContainer/PlusButton");
if (quantityInput != null && minusButton != null && plusButton != null)
{
// 设置初始值
quantityInput.Text = "1";
// 如果没有配方,禁用数量控制
quantityInput.Editable = hasRecipe;
minusButton.Disabled = !hasRecipe;
plusButton.Disabled = !hasRecipe;
if (!hasRecipe)
{
quantityInput.Modulate = new Color(0.6f, 0.6f, 0.6f, 1.0f);
minusButton.Modulate = new Color(0.6f, 0.6f, 0.6f, 1.0f);
plusButton.Modulate = new Color(0.6f, 0.6f, 0.6f, 1.0f);
}
// 连接减号按钮事件
minusButton.Pressed += () => {
int currentValue = GetQuantityValue(quantityInput);
if (currentValue > 1)
{
quantityInput.Text = (currentValue - 1).ToString();
}
};
// 连接加号按钮事件
plusButton.Pressed += () => {
int currentValue = GetQuantityValue(quantityInput);
if (currentValue < 99) // 限制最大值为99
{
quantityInput.Text = (currentValue + 1).ToString();
}
};
// 连接输入框文本变化事件
quantityInput.TextChanged += (string newText) => {
ValidateQuantityInput(quantityInput, newText);
};
}
}
catch (System.Exception e)
{
GD.PrintErr($"设置数量控制组件时出错: {e.Message}");
}
}
private int GetQuantityValue(LineEdit quantityInput)
{
if (int.TryParse(quantityInput.Text, out int value))
{
return Mathf.Clamp(value, 1, 99);
}
return 1;
}
private void ValidateQuantityInput(LineEdit quantityInput, string newText)
{
// 只允许数字输入
if (string.IsNullOrEmpty(newText))
{
quantityInput.Text = "1";
return;
}
if (int.TryParse(newText, out int value))
{
// 限制范围在1-99之间
value = Mathf.Clamp(value, 1, 99);
if (value.ToString() != newText)
{
quantityInput.Text = value.ToString();
quantityInput.CaretColumn = quantityInput.Text.Length;
}
}
else
{
// 如果不是有效数字恢复为1
quantityInput.Text = "1";
quantityInput.CaretColumn = quantityInput.Text.Length;
}
}
}

60
scripts/ui/MainMenu.cs Normal file
View File

@ -0,0 +1,60 @@
using Godot;
public partial class MainMenu : Control
{
// 主菜单控制脚本
public override void _Ready()
{
GD.Print("主菜单已加载");
}
// 新游戏按钮点击事件
private void _OnNewGameBtnPressed()
{
GD.Print("点击了新游戏");
// 切换到游戏场景
GetTree().ChangeSceneToFile("res://scenes/game_scene.tscn");
}
// 载入存档按钮点击事件
private void _OnLoadGameBtnPressed()
{
GD.Print("点击了载入存档");
// 这里可以实现存档载入逻辑
// LoadGame();
}
// 设置按钮点击事件
private void _OnSettingsBtnPressed()
{
GD.Print("点击了设置");
// 这里可以切换到设置界面
// GetTree().ChangeSceneToFile("res://scenes/settings_scene.tscn");
}
// 退出游戏按钮点击事件
private void _OnExitBtnPressed()
{
GD.Print("点击了退出游戏");
// 退出游戏
GetTree().Quit();
}
// 存档载入函数示例
private void LoadGame()
{
if (FileAccess.FileExists("user://savegame.save"))
{
using var saveFile = FileAccess.Open("user://savegame.save", FileAccess.ModeFlags.Read);
var saveData = saveFile.GetVar();
// 处理存档数据
GD.Print("存档已载入:", saveData);
}
else
{
GD.Print("没有找到存档文件");
}
}
}