项目重构,破坏性更新

This commit is contained in:
gongxh
2025-09-02 17:05:46 +08:00
parent 0b6b6c0be3
commit 7cd19a373b
18 changed files with 1059 additions and 989 deletions

View File

@@ -1,61 +1,97 @@
import { Blackboard } from "./Blackboard";
import { BaseNode } from "./BTNode/BaseNode";
import { createUUID } from "./header";
import { Ticker } from "./Ticker";
/**
* 行为树
* 所有节点全部添加到树中
*/
export class BehaviorTree {
/** 行为树ID @internal */
private _id: string;
/** 行为树跟节点 @internal */
export class BehaviorTree<T> {
/**
* @internal
*/
private _root: BaseNode;
/**
* @internal
*/
private _blackboard: Blackboard;
/**
* @internal
*/
private _subject: T;
/**
* 节点ID计数器每个树实例独立管理
* @internal
*/
private _nodeIdCounter: number = 0;
get root(): BaseNode { return this._root; }
get blackboard() { return this._blackboard }
get subject(): T { return this._subject; }
/**
* constructor
* @param subject 主体
* @param root 根节点
*/
constructor(root: BaseNode) {
this._id = createUUID();
constructor(subject: T, root: BaseNode) {
this._root = root;
this._blackboard = new Blackboard();
this._subject = subject;
// 构造时就初始化所有节点ID避免运行时检查
this._initializeAllNodeIds(this._root);
}
/**
* 执行
* @param subject 主体
* @param blackboard 黑板
* @param ticker 更新器
* 执行行为树
*/
public tick(subject: any, blackboard: Blackboard, ticker?: Ticker): void {
ticker = ticker || new Ticker(subject, blackboard, this);
ticker.openNodes.length = 0;
this._root._execute(ticker);
// 上次打开的节点
let lastOpenNodes = (blackboard.get("openNodes", this._id) || []) as BaseNode[];
// 当前打开的节点
let currOpenNodes = ticker.openNodes;
let start = 0;
for (let i = 0; i < Math.min(lastOpenNodes.length, currOpenNodes.length); i++) {
start = i + 1;
if (lastOpenNodes[i] !== currOpenNodes[i]) {
break;
}
}
// 关闭不需要的节点
for (let i = lastOpenNodes.length - 1; i >= start; i--) {
lastOpenNodes[i]._close(ticker);
}
/* POPULATE BLACKBOARD */
blackboard.set("openNodes", currOpenNodes, this._id);
blackboard.set("nodeCount", ticker.nodeCount, this._id);
public tick(): void {
this._root._execute(this);
}
get id(): string {
return this._id;
/**
* 生成节点ID
* 每个树实例独立管理节点ID避免全局状态污染
* @internal
*/
private _generateNodeId(): string {
return `${++this._nodeIdCounter}`;
}
get root(): BaseNode {
return this._root;
/**
* 递归初始化所有节点ID
* 在构造时一次性完成,避免运行时检查
* @param node 要初始化的节点
* @internal
*/
private _initializeAllNodeIds(node: BaseNode): void {
// 设置当前节点ID
node.id = this._generateNodeId();
// 递归设置所有子节点ID
for (const child of node.children) {
this._initializeAllNodeIds(child);
}
}
/**
* 完全重置行为树(核武器级别的重置)
* 清空黑板并重置所有节点状态
*/
public reset(): void {
this._blackboard.clear();
// 重置所有节点的状态
this._root.cleanupAll();
}
/**
* 重置指定记忆节点的记忆状态
* 用于精确控制记忆节点的重置,而不影响其他状态
* @param node 记忆节点
*/
public resetMemoryNode(node: BaseNode): void {
// 通过黑板标记该节点需要重置记忆
this._blackboard.set(`reset_memory`, true, node);
}
}