采矿行为树示例

This commit is contained in:
YHH
2025-06-25 17:50:40 +08:00
parent 01084a8897
commit 0b4a6b77e2
28 changed files with 3119 additions and 2054 deletions

View File

@@ -0,0 +1,289 @@
import { Component, _decorator, Node, Label, ProgressBar, UITransform, Widget, Canvas, find, director, Color, Sprite, Layers, Graphics } from 'cc';
import { MinerStatusUI } from './MinerStatusUI';
const { ccclass, property } = _decorator;
/**
* 状态UI管理器
* 负责创建和管理游戏对象的状态显示界面
*/
@ccclass('StatusUIManager')
export class StatusUIManager extends Component {
/**
* 为矿工创建状态显示UI
*/
static createStatusUIForMiner(miner: Node): MinerStatusUI | null {
const canvas = find('Canvas') || director.getScene()?.getChildByName('Canvas');
if (!canvas) {
console.error('[StatusUIManager] 未找到Canvas');
return null;
}
const minerIndex = this.extractMinerIndex(miner.name);
const yOffset = minerIndex * 20;
const uiRoot = new Node(`${miner.name}_StatusUI`);
canvas.addChild(uiRoot);
const uiTransform = uiRoot.addComponent(UITransform);
uiTransform.setContentSize(200, 100);
const borderNode = new Node('Border');
uiRoot.addChild(borderNode);
const borderTransform = borderNode.addComponent(UITransform);
borderTransform.setContentSize(202, 102);
const borderGraphics = borderNode.addComponent(Graphics);
borderGraphics.fillColor = new Color(100, 100, 100, 120);
borderGraphics.rect(-101, -51, 202, 102);
borderGraphics.fill();
const borderWidget = borderNode.addComponent(Widget);
borderWidget.isAlignTop = true;
borderWidget.isAlignBottom = true;
borderWidget.isAlignLeft = true;
borderWidget.isAlignRight = true;
borderWidget.top = -1;
borderWidget.bottom = -1;
borderWidget.left = -1;
borderWidget.right = -1;
borderWidget.updateAlignment();
const backgroundNode = new Node('Background');
uiRoot.addChild(backgroundNode);
const backgroundTransform = backgroundNode.addComponent(UITransform);
backgroundTransform.setContentSize(200, 100);
const backgroundGraphics = backgroundNode.addComponent(Graphics);
backgroundGraphics.fillColor = new Color(0, 0, 0, 100);
backgroundGraphics.rect(-100, -50, 200, 100);
backgroundGraphics.fill();
const statusUI = uiRoot.addComponent(MinerStatusUI);
statusUI.setFollowTarget(miner);
statusUI.yOffset = 100 + yOffset;
const nameNode = new Node('NameLabel');
uiRoot.addChild(nameNode);
const nameTransform = nameNode.addComponent(UITransform);
nameTransform.setContentSize(200, 25);
const nameLabel = nameNode.addComponent(Label);
nameLabel.string = miner.name;
nameLabel.fontSize = 16;
nameLabel.color = new Color(255, 255, 255, 255);
const nameWidget = nameNode.addComponent(Widget);
nameWidget.isAlignTop = true;
nameWidget.top = 0;
nameWidget.isAlignHorizontalCenter = true;
nameWidget.updateAlignment();
// 创建状态标签
const statusNode = new Node('StatusLabel');
uiRoot.addChild(statusNode);
const statusTransform = statusNode.addComponent(UITransform);
statusTransform.setContentSize(200, 20);
const statusLabel = statusNode.addComponent(Label);
statusLabel.string = '待机中';
statusLabel.fontSize = 14;
statusLabel.color = new Color(200, 200, 200, 255);
// 设置状态标签位置
const statusWidget = statusNode.addComponent(Widget);
statusWidget.isAlignTop = true;
statusWidget.top = 25;
statusWidget.isAlignHorizontalCenter = true;
statusWidget.updateAlignment();
// 创建体力进度条
const staminaBarNode = new Node('StaminaBar');
uiRoot.addChild(staminaBarNode);
const staminaBarTransform = staminaBarNode.addComponent(UITransform);
staminaBarTransform.setContentSize(150, 8);
const staminaBar = staminaBarNode.addComponent(ProgressBar);
staminaBar.progress = 1.0;
// 创建体力进度条背景
const staminaBgNode = new Node('Background');
staminaBarNode.addChild(staminaBgNode);
const staminaBgTransform = staminaBgNode.addComponent(UITransform);
staminaBgTransform.setContentSize(150, 8);
const staminaBgGraphics = staminaBgNode.addComponent(Graphics);
staminaBgGraphics.fillColor = new Color(50, 50, 50, 255);
staminaBgGraphics.rect(-75, -4, 150, 8);
staminaBgGraphics.fill();
// 创建体力进度条填充
const staminaFillNode = new Node('Bar');
staminaBarNode.addChild(staminaFillNode);
const staminaFillTransform = staminaFillNode.addComponent(UITransform);
staminaFillTransform.setContentSize(150, 8);
const staminaFillGraphics = staminaFillNode.addComponent(Graphics);
staminaFillGraphics.fillColor = new Color(0, 255, 0, 255);
staminaFillGraphics.rect(-75, -4, 150, 8);
staminaFillGraphics.fill();
// 设置体力进度条位置
const staminaWidget = staminaBarNode.addComponent(Widget);
staminaWidget.isAlignTop = true;
staminaWidget.top = 45;
staminaWidget.isAlignHorizontalCenter = true;
staminaWidget.updateAlignment();
// 创建动作进度条
const actionBarNode = new Node('ActionProgressBar');
uiRoot.addChild(actionBarNode);
const actionBarTransform = actionBarNode.addComponent(UITransform);
actionBarTransform.setContentSize(150, 6);
const actionBar = actionBarNode.addComponent(ProgressBar);
actionBar.progress = 0;
actionBarNode.active = false; // 初始隐藏
// 创建动作进度条背景
const actionBgNode = new Node('Background');
actionBarNode.addChild(actionBgNode);
const actionBgTransform = actionBgNode.addComponent(UITransform);
actionBgTransform.setContentSize(150, 6);
const actionBgGraphics = actionBgNode.addComponent(Graphics);
actionBgGraphics.fillColor = new Color(50, 50, 50, 255);
actionBgGraphics.rect(-75, -3, 150, 6);
actionBgGraphics.fill();
// 创建动作进度条填充
const actionFillNode = new Node('Bar');
actionBarNode.addChild(actionFillNode);
const actionFillTransform = actionFillNode.addComponent(UITransform);
actionFillTransform.setContentSize(150, 6);
const actionFillGraphics = actionFillNode.addComponent(Graphics);
actionFillGraphics.fillColor = new Color(255, 255, 0, 255);
actionFillGraphics.rect(-75, -3, 150, 6);
actionFillGraphics.fill();
// 设置动作进度条位置
const actionWidget = actionBarNode.addComponent(Widget);
actionWidget.isAlignTop = true;
actionWidget.top = 55;
actionWidget.isAlignHorizontalCenter = true;
actionWidget.updateAlignment();
// 创建动作标签
const actionLabelNode = new Node('ActionLabel');
uiRoot.addChild(actionLabelNode);
const actionLabelTransform = actionLabelNode.addComponent(UITransform);
actionLabelTransform.setContentSize(200, 15);
const actionLabel = actionLabelNode.addComponent(Label);
actionLabel.string = '';
actionLabel.fontSize = 12;
actionLabel.color = new Color(255, 255, 0, 255);
// 设置动作标签位置
const actionLabelWidget = actionLabelNode.addComponent(Widget);
actionLabelWidget.isAlignTop = true;
actionLabelWidget.top = 65;
actionLabelWidget.isAlignHorizontalCenter = true;
actionLabelWidget.updateAlignment();
// 创建矿石数量标签
const oreCountNode = new Node('OreCountLabel');
uiRoot.addChild(oreCountNode);
const oreCountTransform = oreCountNode.addComponent(UITransform);
oreCountTransform.setContentSize(100, 15);
const oreCountLabel = oreCountNode.addComponent(Label);
oreCountLabel.string = '💎0';
oreCountLabel.fontSize = 12;
oreCountLabel.color = new Color(255, 215, 0, 255); // 金色
// 设置矿石数量标签位置(居中显示)
const oreCountWidget = oreCountNode.addComponent(Widget);
oreCountWidget.isAlignTop = true;
oreCountWidget.top = 80;
oreCountWidget.isAlignHorizontalCenter = true;
oreCountWidget.updateAlignment();
statusUI.nameLabel = nameLabel;
statusUI.statusLabel = statusLabel;
statusUI.staminaBar = staminaBar;
statusUI.actionProgressBar = actionBar;
statusUI.actionLabel = actionLabel;
statusUI.oreCountLabel = oreCountLabel;
statusUI.warehouseCountLabel = null;
StatusUIManager.setNodeLayerRecursively(uiRoot, Layers.Enum.UI_2D);
return statusUI;
}
/**
* 递归设置节点及其子节点的层级
*/
private static setNodeLayerRecursively(node: Node, layer: number) {
node.layer = layer;
for (const child of node.children) {
StatusUIManager.setNodeLayerRecursively(child, layer);
}
}
/**
* 从矿工名字中提取索引号
*/
private static extractMinerIndex(minerName: string): number {
const match = minerName.match(/Miner_(\d+)/);
if (match) {
return parseInt(match[1]) - 1;
}
return 0;
}
/**
* 为仓库创建存储量显示UI
*/
static createWarehouseUI(warehouse: Node): MinerStatusUI | null {
const canvas = find('Canvas') || director.getScene()?.getChildByName('Canvas');
if (!canvas) {
console.error('[StatusUIManager] 未找到Canvas');
return null;
}
const uiRoot = new Node(`${warehouse.name}_StorageUI`);
canvas.addChild(uiRoot);
const uiTransform = uiRoot.addComponent(UITransform);
uiTransform.setContentSize(120, 40);
const backgroundNode = new Node('Background');
uiRoot.addChild(backgroundNode);
const backgroundTransform = backgroundNode.addComponent(UITransform);
backgroundTransform.setContentSize(120, 40);
const backgroundGraphics = backgroundNode.addComponent(Graphics);
backgroundGraphics.fillColor = new Color(0, 0, 0, 120);
backgroundGraphics.rect(-60, -20, 120, 40);
backgroundGraphics.fill();
const storageNode = new Node('StorageLabel');
uiRoot.addChild(storageNode);
const storageTransform = storageNode.addComponent(UITransform);
storageTransform.setContentSize(120, 30);
const storageLabel = storageNode.addComponent(Label);
storageLabel.string = '🏭 总存储: 0';
storageLabel.fontSize = 14;
storageLabel.color = new Color(255, 255, 255, 255);
const storageWidget = storageNode.addComponent(Widget);
storageWidget.isAlignHorizontalCenter = true;
storageWidget.isAlignVerticalCenter = true;
storageWidget.updateAlignment();
const statusUI = uiRoot.addComponent(MinerStatusUI);
statusUI.setFollowTarget(warehouse);
statusUI.yOffset = 150;
statusUI.nameLabel = null;
statusUI.statusLabel = null;
statusUI.staminaBar = null;
statusUI.actionProgressBar = null;
statusUI.actionLabel = null;
statusUI.oreCountLabel = null;
statusUI.warehouseCountLabel = storageLabel;
StatusUIManager.setNodeLayerRecursively(uiRoot, Layers.Enum.UI_2D);
return statusUI;
}
}