采矿行为树示例
This commit is contained in:
@@ -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;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user