mirror of
https://github.com/gongxh0901/kunpocc-behaviortree.git
synced 2025-12-27 00:58:18 +00:00
添加根据数据创建行为树的方法
This commit is contained in:
@@ -64,6 +64,11 @@ export namespace BT {
|
||||
maxChildren: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* 注册节点名 到 节点构造函数的映射
|
||||
*/
|
||||
const NODE_NAME_TO_CONSTRUCTOR_MAP = new Map<string, any>();
|
||||
|
||||
/**
|
||||
* 节点元数据存储
|
||||
*/
|
||||
@@ -111,6 +116,7 @@ export namespace BT {
|
||||
parameters
|
||||
};
|
||||
NODE_METADATA_MAP.set(constructor, fullMetadata);
|
||||
NODE_NAME_TO_CONSTRUCTOR_MAP.set(name, constructor);
|
||||
return constructor;
|
||||
};
|
||||
}
|
||||
@@ -131,6 +137,7 @@ export namespace BT {
|
||||
parameters
|
||||
};
|
||||
NODE_METADATA_MAP.set(constructor, fullMetadata);
|
||||
NODE_NAME_TO_CONSTRUCTOR_MAP.set(name, constructor);
|
||||
return constructor;
|
||||
};
|
||||
}
|
||||
@@ -151,6 +158,7 @@ export namespace BT {
|
||||
parameters
|
||||
};
|
||||
NODE_METADATA_MAP.set(constructor, fullMetadata);
|
||||
NODE_NAME_TO_CONSTRUCTOR_MAP.set(name, constructor);
|
||||
return constructor;
|
||||
};
|
||||
}
|
||||
@@ -171,6 +179,7 @@ export namespace BT {
|
||||
parameters
|
||||
};
|
||||
NODE_METADATA_MAP.set(constructor, fullMetadata);
|
||||
NODE_NAME_TO_CONSTRUCTOR_MAP.set(name, constructor);
|
||||
return constructor;
|
||||
};
|
||||
}
|
||||
@@ -181,6 +190,20 @@ export namespace BT {
|
||||
export function getAllNodeMetadata(): Map<any, NodeMetadata> {
|
||||
return new Map(NODE_METADATA_MAP);
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过节点名 获取 节点构造函数
|
||||
*/
|
||||
export function getNodeConstructor(name: string): any {
|
||||
return NODE_NAME_TO_CONSTRUCTOR_MAP.get(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过节点构造函数 找到节点元数据
|
||||
*/
|
||||
export function getNodeMetadata(ctor: any): NodeMetadata {
|
||||
return NODE_METADATA_MAP.get(ctor)!;
|
||||
}
|
||||
}
|
||||
|
||||
let _global = globalThis || window || global;
|
||||
|
||||
@@ -51,7 +51,7 @@ export class WaitTime extends LeafNode {
|
||||
private _value: number = 0;
|
||||
constructor(duration: number = 0) {
|
||||
super();
|
||||
this._max = duration * 1000;
|
||||
this._max = duration;
|
||||
}
|
||||
|
||||
protected override open(): void {
|
||||
@@ -61,7 +61,7 @@ export class WaitTime extends LeafNode {
|
||||
|
||||
public tick(): Status {
|
||||
const currTime = new Date().getTime();
|
||||
if (currTime - this._value >= this._max) {
|
||||
if (currTime - this._value >= this._max * 1000) {
|
||||
return Status.SUCCESS;
|
||||
}
|
||||
return Status.RUNNING;
|
||||
|
||||
@@ -56,7 +56,7 @@ export class LimitTime extends NumericDecorator {
|
||||
*/
|
||||
constructor(child: IBTNode, max: number = 1) {
|
||||
super(child);
|
||||
this._max = max * 1000;
|
||||
this._max = max;
|
||||
}
|
||||
|
||||
protected override open(): void {
|
||||
@@ -65,7 +65,7 @@ export class LimitTime extends NumericDecorator {
|
||||
|
||||
public tick(): Status {
|
||||
const currentTime = Date.now();
|
||||
if (currentTime - this._value > this._max) {
|
||||
if (currentTime - this._value > this._max * 1000) {
|
||||
return Status.FAILURE;
|
||||
}
|
||||
return this.children[0]!._execute();
|
||||
|
||||
71
src/behaviortree/Factory.ts
Normal file
71
src/behaviortree/Factory.ts
Normal file
@@ -0,0 +1,71 @@
|
||||
/**
|
||||
* @Author: Gongxh
|
||||
* @Date: 2025-09-16
|
||||
* @Description: 根据数据创建一颗行为树
|
||||
*/
|
||||
|
||||
import { BehaviorTree } from "./BehaviorTree";
|
||||
import { BT } from "./BT";
|
||||
import { IBTNode } from "./BTNode/BTNode";
|
||||
|
||||
interface INodeConfig {
|
||||
id: string,
|
||||
className: string,
|
||||
parameters: Record<string, any>,
|
||||
children: string[]
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据节点配置递归创建节点
|
||||
* @param info 节点配置
|
||||
* @param nodeMap 所有节点配置的映射表
|
||||
* @returns 创建的节点实例
|
||||
*/
|
||||
function createNodeRecursively(info: INodeConfig, nodeMap: Map<string, INodeConfig>): IBTNode {
|
||||
// 获取节点构造函数
|
||||
const ctor = BT.getNodeConstructor(info.className);
|
||||
if (!ctor) {
|
||||
throw new Error(`未找到节点【${info.className}】的构造函数`);
|
||||
}
|
||||
|
||||
// 递归创建子节点
|
||||
const childNodes: IBTNode[] = [];
|
||||
for (const childId of info.children || []) {
|
||||
const childInfo = nodeMap.get(childId);
|
||||
if (!childInfo) {
|
||||
throw new Error(`未找到子节点【${childId}】,行为树配置导出信息错误`);
|
||||
}
|
||||
const childNode = createNodeRecursively(childInfo, nodeMap);
|
||||
childNodes.push(childNode);
|
||||
}
|
||||
|
||||
// 创建节点实例
|
||||
let btnode: IBTNode;
|
||||
const metadata = BT.getNodeMetadata(ctor);
|
||||
if (metadata.type === BT.Type.Action || metadata.type === BT.Type.Condition) {
|
||||
btnode = new ctor();
|
||||
} else if (metadata.type === BT.Type.Decorator) {
|
||||
btnode = new ctor(childNodes[0]!);
|
||||
} else {
|
||||
btnode = new ctor(...childNodes);
|
||||
}
|
||||
// 设置节点参数
|
||||
for (const key in info.parameters) {
|
||||
(btnode as any)[key] = info.parameters[key];
|
||||
}
|
||||
return btnode;
|
||||
}
|
||||
|
||||
export function createBehaviorTree<T>(config: INodeConfig[], entity: T): BehaviorTree<T> {
|
||||
// 验证配置
|
||||
if (!config || !Array.isArray(config) || config.length === 0) {
|
||||
throw new Error("Config is empty or invalid");
|
||||
}
|
||||
|
||||
// 创建配置映射表
|
||||
const nodeMap = new Map<string, INodeConfig>();
|
||||
for (const info of config) {
|
||||
nodeMap.set(info.id, info);
|
||||
}
|
||||
return new BehaviorTree(entity, createNodeRecursively(config[0]!, nodeMap));
|
||||
}
|
||||
@@ -2,4 +2,4 @@ export enum Status {
|
||||
FAILURE,
|
||||
SUCCESS,
|
||||
RUNNING,
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user