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

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