UNPKG

@esengine/ai

Version:

用于Laya、Cocos Creator等JavaScript游戏引擎的高性能AI系统库:行为树、实用AI和有限状态机

1,885 lines (1,879 loc) 289 kB
/** * @esengine/ai v2.0.30 * 高性能TypeScript AI系统库 - 行为树、实用AI和有限状态机 * * @author yhh * @license MIT */ /** * 高性能伪随机数生成器 * 使用xorshift128算法,比原生Math.random()更快且质量更好 * * @example * ```typescript * // 设置种子(可选,默认使用当前时间) * Random.setSeed(12345); * * // 生成0-1之间的随机数 * const value = Random.value(); * * // 生成指定范围的随机数 * const rangeValue = Random.range(10, 20); * * // 生成随机整数 * const intValue = Random.integer(1, 100); * * // 随机布尔值 * const bool = Random.boolean(); * * // 带概率的布尔值 * const probBool = Random.chance(0.7); // 70%概率返回true * ``` */ class Random { /** * 设置随机数种子 * @param seed 种子值,如果不提供则使用当前时间 */ static setSeed(seed) { if (seed === undefined) { seed = Date.now(); } // 使用种子初始化四个状态变量 this._x = seed >>> 0; this._y = (seed * 1812433253 + 1) >>> 0; this._z = (this._y * 1812433253 + 1) >>> 0; this._w = (this._z * 1812433253 + 1) >>> 0; // 确保所有状态变量都非零 if (this._x === 0) this._x = 1; if (this._y === 0) this._y = 1; if (this._z === 0) this._z = 1; if (this._w === 0) this._w = 1; this._initialized = true; // 预热生成器 for (let i = 0; i < 10; i++) { this.next(); } } /** * 生成下一个32位无符号整数(内部使用) * 使用xorshift128算法 */ static next() { if (!this._initialized) { this.setSeed(); } const t = this._x ^ (this._x << 11); this._x = this._y; this._y = this._z; this._z = this._w; this._w = (this._w ^ (this._w >>> 19)) ^ (t ^ (t >>> 8)); return this._w >>> 0; // 确保返回无符号32位整数 } /** * 生成0到1之间的随机浮点数(不包括1) * @returns 0 <= value < 1的随机数 */ static value() { return this.next() / 0x100000000; // 2^32 } /** * 生成指定范围内的随机浮点数 * @param min 最小值(包含) * @param max 最大值(不包含) * @returns min <= value < max的随机数 */ static range(min = 0, max = 1) { if (min >= max) { throw new Error(`最小值(${min})必须小于最大值(${max})`); } return min + (max - min) * this.value(); } /** * 生成指定范围内的随机整数 * @param min 最小值(包含) * @param max 最大值(包含) * @returns min <= value <= max的随机整数 */ static integer(min, max) { if (!Number.isInteger(min) || !Number.isInteger(max)) { throw new Error('最小值和最大值必须是整数'); } if (min > max) { throw new Error(`最小值(${min})必须小于等于最大值(${max})`); } return Math.floor(this.range(min, max + 1)); } /** * 生成随机布尔值 * @returns 随机的true或false */ static boolean() { return this.value() < 0.5; } /** * 根据概率生成布尔值 * @param probability 返回true的概率(0-1之间) * @returns 根据概率返回的布尔值 */ static chance(probability) { if (probability < 0 || probability > 1) { throw new Error(`概率值必须在0-1之间,当前值: ${probability}`); } return this.value() < probability; } /** * 从数组中随机选择一个元素 * @param array 要选择的数组 * @returns 随机选中的元素 */ static choice(array) { if (array.length === 0) { throw new Error('数组不能为空'); } const index = this.integer(0, array.length - 1); return array[index]; // 使用非空断言,因为我们已经检查了数组长度 } /** * 从数组中随机选择多个不重复的元素 * @param array 要选择的数组 * @param count 选择的数量 * @returns 随机选中的元素数组 */ static sample(array, count) { if (count < 0 || count > array.length) { throw new Error(`选择数量(${count})必须在0-${array.length}之间`); } if (count === 0) { return []; } if (count === array.length) { return [...array]; } // 对于小的选择数量,使用Set避免重复 if (count <= array.length / 2) { const result = []; const indices = new Set(); while (result.length < count) { const index = this.integer(0, array.length - 1); if (!indices.has(index)) { indices.add(index); result.push(array[index]); } } return result; } else { // 对于大的选择数量,使用Fisher-Yates洗牌算法的部分版本 const shuffled = [...array]; for (let i = 0; i < count; i++) { const j = this.integer(i, shuffled.length - 1); [shuffled[i], shuffled[j]] = [shuffled[j], shuffled[i]]; } return shuffled.slice(0, count); } } /** * 生成符合正态分布的随机数(Box-Muller变换) * @param mean 均值 * @param standardDeviation 标准差 * @returns 符合正态分布的随机数 */ static gaussian(mean = 0, standardDeviation = 1) { // 使用Box-Muller变换生成正态分布随机数 const u1 = this.value(); const u2 = this.value(); const z0 = Math.sqrt(-2 * Math.log(u1)) * Math.cos(2 * Math.PI * u2); return z0 * standardDeviation + mean; } /** * 获取当前随机数生成器的状态(用于保存/恢复) * @returns 生成器状态对象 */ static getState() { if (!this._initialized) { this.setSeed(); } return { x: this._x, y: this._y, z: this._z, w: this._w }; } /** * 恢复随机数生成器的状态 * @param state 要恢复的状态对象 */ static setState(state) { this._x = state.x; this._y = state.y; this._z = state.z; this._w = state.w; this._initialized = true; } } Random._x = 123456789; Random._y = 362436069; Random._z = 521288629; Random._w = 88675123; Random._initialized = false; /** * 数组扩展器和高效数据结构工具 * 提供栈、队列等数据结构的高效实现 */ class ArrayExt { /** * 将数组打乱顺序(Fisher-Yates洗牌算法) * 时间复杂度: O(n),空间复杂度: O(1) * * @param list 要打乱的数组 * @throws {Error} 当数组为null或undefined时抛出错误 */ static shuffle(list) { if (!list) { throw new Error('数组不能为null或undefined'); } // 优化:从后往前遍历,减少一次减法运算 for (let i = list.length - 1; i > 0; i--) { const j = Random.integer(0, i); // 使用解构赋值进行交换,更简洁 [list[i], list[j]] = [list[j], list[i]]; } } /** * 取出数组第一个项(不移除) * @param list 目标数组 * @returns 第一个元素 * @throws {Error} 当数组为空时抛出错误 */ static peek(list) { if (list.length === 0) { throw new Error('无法从空数组中获取元素'); } return list[0]; } /** * 向数组头部添加一个项 * @param list 目标数组 * @param item 要添加的项 */ static unshift(list, item) { list.unshift(item); } /** * 移除数组第一个项并返回它 * @param list 目标数组 * @returns 移除的元素,如果数组为空则返回undefined */ static pop(list) { return list.shift(); } /** * 向数组尾部添加一个项 * @param list 目标数组 * @param item 要添加的项 */ static append(list, item) { list.push(item); } /** * 移除数组最后一个项并返回它 * @param list 目标数组 * @returns 移除的元素,如果数组为空则返回undefined */ static removeLast(list) { return list.pop(); } /** * 检查数组是否为空 * @param list 目标数组 * @returns 是否为空 */ static isEmpty(list) { return list.length === 0; } /** * 获取数组大小 * @param list 目标数组 * @returns 数组长度 */ static size(list) { return list.length; } /** * 清空数组 * @param list 目标数组 */ static clear(list) { list.length = 0; } } /** * 高效的双端队列实现 * 使用环形缓冲区,避免数组头部插入的性能问题 * * @template T 队列中元素的类型 * * @example * ```typescript * const deque = new Deque<number>(32); * deque.push(1); * deque.unshift(0); * console.log(deque.peekFirst()); // 0 * console.log(deque.peekLast()); // 1 * ``` */ class Deque { /** * 创建双端队列 * @param initialCapacity 初始容量,必须大于0,默认16 */ constructor(initialCapacity = 16) { this._head = 0; this._tail = 0; this._size = 0; if (initialCapacity <= 0) { throw new Error('初始容量必须大于0'); } this._capacity = Math.max(initialCapacity, 4); this._buffer = new Array(this._capacity); } /** * 向队列头部添加元素 * @param item 要添加的元素 */ unshift(item) { if (this._size === this._capacity) { this._resize(); } this._head = (this._head - 1 + this._capacity) % this._capacity; this._buffer[this._head] = item; this._size++; } /** * 向队列尾部添加元素 * @param item 要添加的元素 */ push(item) { if (this._size === this._capacity) { this._resize(); } this._buffer[this._tail] = item; this._tail = (this._tail + 1) % this._capacity; this._size++; } /** * 从队列头部移除元素 * @returns 移除的元素,如果队列为空则返回undefined */ shift() { if (this._size === 0) { return undefined; } const item = this._buffer[this._head]; this._buffer[this._head] = undefined; this._head = (this._head + 1) % this._capacity; this._size--; return item; } /** * 从队列尾部移除元素 * @returns 移除的元素,如果队列为空则返回undefined */ pop() { if (this._size === 0) { return undefined; } this._tail = (this._tail - 1 + this._capacity) % this._capacity; const item = this._buffer[this._tail]; this._buffer[this._tail] = undefined; this._size--; return item; } /** * 查看队列头部元素(不移除) * @returns 头部元素,如果队列为空则返回undefined */ peekFirst() { return this._size > 0 ? this._buffer[this._head] : undefined; } /** * 查看队列尾部元素(不移除) * @returns 尾部元素,如果队列为空则返回undefined */ peekLast() { if (this._size === 0) { return undefined; } const lastIndex = (this._tail - 1 + this._capacity) % this._capacity; return this._buffer[lastIndex]; } /** * 获取队列大小 */ get size() { return this._size; } /** * 检查队列是否为空 */ get isEmpty() { return this._size === 0; } /** * 清空队列 */ clear() { for (let i = 0; i < this._capacity; i++) { this._buffer[i] = undefined; } this._head = 0; this._tail = 0; this._size = 0; } /** * 扩容队列(内部使用) * 当队列满时自动调用,容量翻倍 */ _resize() { const newCapacity = this._capacity * 2; const newBuffer = new Array(newCapacity); // 复制现有元素到新缓冲区 for (let i = 0; i < this._size; i++) { newBuffer[i] = this._buffer[(this._head + i) % this._capacity]; } this._buffer = newBuffer; this._head = 0; this._tail = this._size; this._capacity = newCapacity; } /** * 将队列转换为数组 * @returns 包含队列所有元素的数组(从头到尾的顺序) */ toArray() { const result = []; for (let i = 0; i < this._size; i++) { const item = this._buffer[(this._head + i) % this._capacity]; if (item !== undefined) { result.push(item); } } return result; } } /** * 高性能断言工具类 * * @description * 提供类型安全的断言方法,支持开发和生产环境的不同行为。 * 在生产环境中可以禁用断言以提高性能。 * * @example * ```typescript * // 基本断言 * Assert.isTrue(player.health > 0, '玩家血量必须大于0'); * Assert.isNotNull(gameObject, '游戏对象不能为空'); * * // 类型安全的断言 * const value: unknown = getData(); * Assert.isNumber(value, '数据必须是数字'); * // 现在 value 的类型被缩窄为 number * * // 配置断言行为 * Assert.setEnabled(false); // 在生产环境中禁用 * ``` */ class Assert { /** * 设置是否启用断言 * @param enabled 是否启用 */ static setEnabled(enabled) { this._enabled = enabled; } /** * 设置断言失败时的行为 * @param throwOnFailure 是否抛出异常,false则仅记录到控制台 */ static setThrowOnFailure(throwOnFailure) { this._throwOnFailure = throwOnFailure; } /** * 断言失败处理 * @param message 错误消息 * @param args 附加参数 */ static fail(message, ...args) { const errorMessage = message || '断言失败'; if (this._throwOnFailure) { throw new Error(errorMessage); } else { console.assert(false, errorMessage, ...args); throw new Error(errorMessage); // 总是抛出错误,因为这是fail方法 } } /** * 断言条件为真 * @param condition 要检查的条件 * @param message 失败时的错误消息 * @param args 附加参数 */ static isTrue(condition, message, ...args) { if (!this._enabled) return; if (!condition) { this.fail(message || '条件必须为真', ...args); } } /** * 断言条件为假 * @param condition 要检查的条件 * @param message 失败时的错误消息 * @param args 附加参数 */ static isFalse(condition, message, ...args) { if (!this._enabled) return; if (condition) { this.fail(message || '条件必须为假', ...args); } } /** * 断言对象不为null或undefined * @param obj 要检查的对象 * @param message 失败时的错误消息 * @param args 附加参数 */ static isNotNull(obj, message, ...args) { if (!this._enabled) return; if (obj == null) { this.fail(message || '对象不能为null或undefined', ...args); } } /** * 断言对象为null或undefined * @param obj 要检查的对象 * @param message 失败时的错误消息 * @param args 附加参数 */ static isNull(obj, message, ...args) { if (!this._enabled) return; if (obj != null) { this.fail(message || '对象必须为null或undefined', ...args); } } /** * 断言值为数字类型 * @param value 要检查的值 * @param message 失败时的错误消息 * @param args 附加参数 */ static isNumber(value, message, ...args) { if (!this._enabled) return; if (typeof value !== 'number' || isNaN(value)) { this.fail(message || '值必须是有效数字', ...args); } } /** * 断言值为字符串类型 * @param value 要检查的值 * @param message 失败时的错误消息 * @param args 附加参数 */ static isString(value, message, ...args) { if (!this._enabled) return; if (typeof value !== 'string') { this.fail(message || '值必须是字符串', ...args); } } /** * 断言值为布尔类型 * @param value 要检查的值 * @param message 失败时的错误消息 * @param args 附加参数 */ static isBoolean(value, message, ...args) { if (!this._enabled) return; if (typeof value !== 'boolean') { this.fail(message || '值必须是布尔值', ...args); } } /** * 断言值为函数类型 * @param value 要检查的值 * @param message 失败时的错误消息 * @param args 附加参数 */ static isFunction(value, message, ...args) { if (!this._enabled) return; if (typeof value !== 'function') { this.fail(message || '值必须是函数', ...args); } } /** * 断言值为对象类型(非null) * @param value 要检查的值 * @param message 失败时的错误消息 * @param args 附加参数 */ static isObject(value, message, ...args) { if (!this._enabled) return; if (typeof value !== 'object' || value === null) { this.fail(message || '值必须是对象', ...args); } } /** * 断言数组不为空 * @param array 要检查的数组 * @param message 失败时的错误消息 * @param args 附加参数 */ static isNotEmpty(array, message, ...args) { if (!this._enabled) return; this.isNotNull(array, message, ...args); if (array.length === 0) { this.fail(message || '数组不能为空', ...args); } } /** * 断言字符串不为空 * @param str 要检查的字符串 * @param message 失败时的错误消息 * @param args 附加参数 */ static isNotEmptyString(str, message, ...args) { if (!this._enabled) return; this.isNotNull(str, message, ...args); if (str.trim().length === 0) { this.fail(message || '字符串不能为空', ...args); } } /** * 断言数值在指定范围内 * @param value 要检查的数值 * @param min 最小值(包含) * @param max 最大值(包含) * @param message 失败时的错误消息 * @param args 附加参数 */ static inRange(value, min, max, message, ...args) { if (!this._enabled) return; this.isNumber(value, message, ...args); if (value < min || value > max) { this.fail(message || `值必须在 ${min} 到 ${max} 之间`, ...args); } } /** * 断言值是指定类型的实例 * @param value 要检查的值 * @param constructor 构造函数 * @param message 失败时的错误消息 * @param args 附加参数 */ static isInstanceOf(value, constructor, message, ...args) { if (!this._enabled) return; if (!(value instanceof constructor)) { this.fail(message || `值必须是 ${constructor.name} 的实例`, ...args); } } /** * 断言数组包含指定元素 * @param array 要检查的数组 * @param element 要查找的元素 * @param message 失败时的错误消息 * @param args 附加参数 */ static contains(array, element, message, ...args) { if (!this._enabled) return; this.isNotNull(array, message, ...args); if (!array.includes(element)) { this.fail(message || '数组必须包含指定元素', ...args); } } /** * 获取当前断言配置 * @returns 配置对象 */ static getConfig() { return { enabled: this._enabled, throwOnFailure: this._throwOnFailure }; } } /** 是否启用断言检查 */ Assert._enabled = true; /** 是否在断言失败时抛出异常而不是仅记录 */ Assert._throwOnFailure = false; /** * 日志级别枚举 */ var LogLevel; (function (LogLevel) { /** 调试信息 */ LogLevel[LogLevel["Debug"] = 0] = "Debug"; /** 一般信息 */ LogLevel[LogLevel["Info"] = 1] = "Info"; /** 警告信息 */ LogLevel[LogLevel["Warn"] = 2] = "Warn"; /** 错误信息 */ LogLevel[LogLevel["Error"] = 3] = "Error"; /** 关闭日志 */ LogLevel[LogLevel["None"] = 4] = "None"; })(LogLevel || (LogLevel = {})); /** * 高性能日志系统 * * @description * 提供分级日志记录功能,支持性能优化模式。 * 在性能模式下,会跳过不必要的字符串格式化和时间戳计算。 * 支持批量输出和延迟日志记录。 * * @example * ```typescript * // 基本使用 * Logger.info('游戏开始'); * Logger.warn('玩家血量低', { health: 10 }); * Logger.error('网络连接失败', error); * * // 配置日志系统 * Logger.configure({ * minLevel: LogLevel.Warn, * enableTimestamp: true, * performanceMode: false, * batchMode: true, * batchSize: 50 * }); * * // 性能敏感的代码中 * Logger.setPerformanceMode(true); * ``` */ class Logger { /** * 配置日志系统 * @param config 日志配置 */ static configure(config) { this._config = { ...this._config, ...config }; // 配置批量模式 if (config.batchMode !== undefined) { this._batchConfig.enabled = config.batchMode; } if (config.batchSize !== undefined) { this._batchConfig.maxSize = Math.max(1, config.batchSize); } if (config.batchFlushInterval !== undefined) { this._batchConfig.flushInterval = Math.max(100, config.batchFlushInterval); } // 初始化性能模式 this._initializePerformanceMode(); } /** * 初始化性能模式 */ static _initializePerformanceMode() { if (this._config.performanceMode) { // 在性能模式下,使用最简化的日志函数 this._fastLog = (message, data) => { if (data !== undefined) { console.log(message, data); } else { console.log(message); } }; } else { this._fastLog = null; } } /** * 设置最小日志级别 * @param level 最小日志级别 */ static setMinLevel(level) { this._config.minLevel = level; } /** * 设置性能模式 * @param enabled 是否启用性能模式 */ static setPerformanceMode(enabled) { this._config.performanceMode = enabled; this._initializePerformanceMode(); } /** * 启用批量模式 * @param enabled 是否启用 * @param maxSize 批量大小 * @param flushInterval 刷新间隔(毫秒) */ static setBatchMode(enabled, maxSize = 50, flushInterval = 1000) { this._batchConfig.enabled = enabled; this._batchConfig.maxSize = Math.max(1, maxSize); this._batchConfig.flushInterval = Math.max(100, flushInterval); if (!enabled) { this.flushLogs(); // 禁用时立即刷新所有日志 } } /** * 记录调试信息 * @param message 消息 * @param data 附加数据 */ static debug(message, data) { this._log(LogLevel.Debug, message, data); } /** * 记录一般信息 * @param message 消息 * @param data 附加数据 */ static info(message, data) { this._log(LogLevel.Info, message, data); } /** * 记录警告信息 * @param message 消息 * @param data 附加数据 */ static warn(message, data) { this._log(LogLevel.Warn, message, data); } /** * 记录错误信息 * @param message 消息 * @param error 错误对象或附加数据 */ static error(message, error) { this._log(LogLevel.Error, message, error); } /** * 内部日志记录方法 * @param level 日志级别 * @param message 消息 * @param data 附加数据 */ static _log(level, message, data) { // 检查日志级别 if (level < this._config.minLevel || this._config.minLevel === LogLevel.None) { return; } if (this._config.performanceMode && this._fastLog) { // 超高性能模式:跳过所有格式化 this._fastLog(message, data); return; } if (this._batchConfig.enabled) { // 批量模式:添加到缓冲区 this._addToBatch(level, message, data); } else if (this._config.performanceMode) { // 性能模式:简化输出 this._performanceLog(level, message, data); } else { // 标准模式:完整格式化 this._standardLog(level, message, data); } } /** * 添加日志到批量缓冲区 */ static _addToBatch(level, message, data) { const entry = { level, message, data, timestamp: Date.now(), prefix: this._config.prefix }; this._logBuffer.push(entry); // 检查是否需要刷新 const now = Date.now(); const shouldFlushBySize = this._logBuffer.length >= this._batchConfig.maxSize; const shouldFlushByTime = (now - this._batchConfig.lastFlushTime) >= this._batchConfig.flushInterval; if (shouldFlushBySize || shouldFlushByTime) { this.flushLogs(); } } /** * 刷新批量日志 */ static flushLogs() { if (this._logBuffer.length === 0) { return; } // 批量输出所有日志 for (const entry of this._logBuffer) { if (this._config.performanceMode) { this._performanceLogEntry(entry); } else { this._standardLogEntry(entry); } } // 清空缓冲区 this._logBuffer.length = 0; this._batchConfig.lastFlushTime = Date.now(); } /** * 性能模式输出日志条目 */ static _performanceLogEntry(entry) { const levelName = this._levelNames[entry.level]; const prefix = entry.prefix ? `[${entry.prefix}] ` : ''; if (entry.data !== undefined) { console.log(`${prefix}[${levelName}] ${entry.message}`, entry.data); } else { console.log(`${prefix}[${levelName}] ${entry.message}`); } } /** * 标准模式输出日志条目 */ static _standardLogEntry(entry) { const timestamp = this._config.enableTimestamp ? this._formatTimestamp(entry.timestamp) : ''; const levelName = this._levelNames[entry.level]; const prefix = entry.prefix ? `[${entry.prefix}] ` : ''; const style = this._levelStyles[entry.level]; let logMessage = `${prefix}${timestamp}[${levelName}] ${entry.message}`; const consoleMethod = this._getConsoleMethod(entry.level); if (entry.data !== undefined) { if (style && typeof console.log === 'function') { consoleMethod(`%c${logMessage}`, style, entry.data); } else { consoleMethod(logMessage, entry.data); } } else { if (style && typeof console.log === 'function') { consoleMethod(`%c${logMessage}`, style); } else { consoleMethod(logMessage); } } // 错误级别且启用堆栈跟踪 if (entry.level === LogLevel.Error && this._config.enableStackTrace && entry.data instanceof Error) { console.trace(entry.data); } } /** * 格式化时间戳 */ static _formatTimestamp(timestamp) { const date = new Date(timestamp); const hours = date.getHours().toString().padStart(2, '0'); const minutes = date.getMinutes().toString().padStart(2, '0'); const seconds = date.getSeconds().toString().padStart(2, '0'); const milliseconds = date.getMilliseconds().toString().padStart(3, '0'); return `[${hours}:${minutes}:${seconds}.${milliseconds}] `; } /** * 性能模式日志输出 * @param level 日志级别 * @param message 消息 * @param data 附加数据 */ static _performanceLog(level, message, data) { const levelName = this._levelNames[level]; const prefix = this._config.prefix ? `[${this._config.prefix}] ` : ''; if (data !== undefined) { console.log(`${prefix}[${levelName}] ${message}`, data); } else { console.log(`${prefix}[${levelName}] ${message}`); } } /** * 标准模式日志输出 * @param level 日志级别 * @param message 消息 * @param data 附加数据 */ static _standardLog(level, message, data) { const timestamp = this._config.enableTimestamp ? this._getTimestamp() : ''; const levelName = this._levelNames[level]; const prefix = this._config.prefix ? `[${this._config.prefix}] ` : ''; const style = this._levelStyles[level]; let logMessage = `${prefix}${timestamp}[${levelName}] ${message}`; // 根据日志级别选择合适的console方法 const consoleMethod = this._getConsoleMethod(level); if (data !== undefined) { if (style && typeof console.log === 'function') { consoleMethod(`%c${logMessage}`, style, data); } else { consoleMethod(logMessage, data); } } else { if (style && typeof console.log === 'function') { consoleMethod(`%c${logMessage}`, style); } else { consoleMethod(logMessage); } } // 错误级别且启用堆栈跟踪 if (level === LogLevel.Error && this._config.enableStackTrace && data instanceof Error) { console.trace(data); } } /** * 获取时间戳字符串 * @returns 格式化的时间戳 */ static _getTimestamp() { const now = new Date(); const hours = now.getHours().toString().padStart(2, '0'); const minutes = now.getMinutes().toString().padStart(2, '0'); const seconds = now.getSeconds().toString().padStart(2, '0'); const milliseconds = now.getMilliseconds().toString().padStart(3, '0'); return `[${hours}:${minutes}:${seconds}.${milliseconds}] `; } /** * 根据日志级别获取对应的console方法 * @param level 日志级别 * @returns console方法 */ static _getConsoleMethod(level) { switch (level) { case LogLevel.Debug: return console.debug || console.log; case LogLevel.Info: return console.info || console.log; case LogLevel.Warn: return console.warn || console.log; case LogLevel.Error: return console.error || console.log; default: return console.log; } } /** * 获取当前配置 * @returns 当前日志配置的副本 */ static getConfig() { return { ...this._config }; } /** * 创建带前缀的日志器 * @param prefix 前缀 * @returns 新的日志器实例 */ static createPrefixed(prefix) { return new PrefixedLogger(prefix); } } Logger._config = { minLevel: LogLevel.Debug, enableTimestamp: true, enableStackTrace: true, performanceMode: false, prefix: '' }; /** 批量日志缓冲区 */ Logger._logBuffer = []; /** 批量模式配置 */ Logger._batchConfig = { enabled: false, maxSize: 50, flushInterval: 1000, // 1秒 lastFlushTime: 0 }; /** 性能模式下的简化日志函数 */ Logger._fastLog = null; /** 日志级别名称映射 */ Logger._levelNames = { [LogLevel.Debug]: 'DEBUG', [LogLevel.Info]: 'INFO', [LogLevel.Warn]: 'WARN', [LogLevel.Error]: 'ERROR', [LogLevel.None]: 'NONE' }; /** 日志级别样式映射(用于浏览器控制台) */ Logger._levelStyles = { [LogLevel.Debug]: 'color: #888', [LogLevel.Info]: 'color: #007acc', [LogLevel.Warn]: 'color: #ff8c00', [LogLevel.Error]: 'color: #ff4444; font-weight: bold', [LogLevel.None]: '' }; /** * 带前缀的日志器 * 用于为特定模块或组件创建专用的日志器 */ class PrefixedLogger { constructor(_prefix) { this._prefix = _prefix; } debug(message, data) { Logger.debug(`[${this._prefix}] ${message}`, data); } info(message, data) { Logger.info(`[${this._prefix}] ${message}`, data); } warn(message, data) { Logger.warn(`[${this._prefix}] ${message}`, data); } error(message, error) { Logger.error(`[${this._prefix}] ${message}`, error); } } /** * 全局时间管理器 * * @description * 提供高性能的时间管理功能,减少重复的时间计算开销。 * 使用时间池化技术,在每帧开始时统一计算时间,避免多次调用performance.now()。 * * @example * ```typescript * // 在游戏主循环开始时更新时间 * TimeManager.updateFrame(); * * // 获取当前时间(无额外计算开销) * const currentTime = TimeManager.getCurrentTime(); * const deltaTime = TimeManager.getDeltaTime(); * * // 配置时间管理器 * TimeManager.configure({ * maxDeltaTime: 0.1, * timeScale: 1.0, * useHighPrecision: true * }); * ``` */ class TimeManager { /** * 配置时间管理器 * @param config 配置选项 */ static configure(config) { if (config.maxDeltaTime !== undefined) { this._maxDeltaTime = Math.max(0.001, config.maxDeltaTime); } if (config.timeScale !== undefined) { this._timeScale = Math.max(0, config.timeScale); } if (config.useHighPrecision !== undefined) { this._useHighPrecision = config.useHighPrecision; } } /** * 初始化时间管理器 */ static initialize() { if (this._initialized) { return; } const now = this._getSystemTime(); this._startTime = now; this._currentTime = 0; this._lastTime = 0; this._deltaTime = 0; this._unscaledDeltaTime = 0; this._frameCount = 0; this._initialized = true; } /** * 更新帧时间(应在每帧开始时调用) * @param externalDeltaTime 可选的外部提供的时间差 */ static updateFrame(externalDeltaTime) { if (!this._initialized) { this.initialize(); } this._frameCount++; if (externalDeltaTime !== undefined) { // 使用外部提供的时间差 this._unscaledDeltaTime = Math.max(0, externalDeltaTime); } else { // 计算系统时间差 const systemTime = this._getSystemTime(); const currentSystemTime = (systemTime - this._startTime) / 1000; if (this._frameCount === 1) { // 第一帧,设置初始时间 this._lastTime = currentSystemTime; this._unscaledDeltaTime = 0; // 第一帧时间差为0 } else { this._unscaledDeltaTime = currentSystemTime - this._lastTime; this._lastTime = currentSystemTime; // 更新lastTime为当前系统时间 } } // 限制最大时间差,防止时间跳跃 this._unscaledDeltaTime = Math.min(this._unscaledDeltaTime, this._maxDeltaTime); // 应用时间缩放 this._deltaTime = this._unscaledDeltaTime * this._timeScale; // 更新当前时间 this._currentTime += this._deltaTime; // 触发时间更新回调 this._triggerUpdateCallbacks(); } /** * 获取系统时间(毫秒) */ static _getSystemTime() { return this._useHighPrecision ? performance.now() : Date.now(); } /** * 触发时间更新回调 */ static _triggerUpdateCallbacks() { for (let i = 0; i < this._updateCallbacks.length; i++) { try { this._updateCallbacks[i](this._deltaTime); } catch (error) { console.error('时间更新回调执行失败:', error); } } } /** * 获取当前时间(秒) * @returns 从初始化开始的累计时间 */ static getCurrentTime() { return this._currentTime; } /** * 获取帧间时间差(秒) * @returns 当前帧与上一帧的时间差 */ static getDeltaTime() { return this._deltaTime; } /** * 获取未缩放的帧间时间差(秒) * @returns 未应用时间缩放的帧间时间差 */ static getUnscaledDeltaTime() { return this._unscaledDeltaTime; } /** * 获取时间缩放比例 */ static getTimeScale() { return this._timeScale; } /** * 设置时间缩放比例 * @param scale 缩放比例,0表示暂停,1表示正常速度 */ static setTimeScale(scale) { this._timeScale = Math.max(0, scale); } /** * 获取帧计数 */ static getFrameCount() { return this._frameCount; } /** * 获取平均帧率 */ static getAverageFPS() { if (this._currentTime <= 0) { return 0; } return this._frameCount / this._currentTime; } /** * 获取当前帧率 */ static getCurrentFPS() { if (this._unscaledDeltaTime <= 0) { return 0; } return 1 / this._unscaledDeltaTime; } /** * 添加时间更新回调 * @param callback 回调函数 */ static addUpdateCallback(callback) { if (this._updateCallbacks.indexOf(callback) === -1) { this._updateCallbacks.push(callback); } } /** * 移除时间更新回调 * @param callback 要移除的回调函数 */ static removeUpdateCallback(callback) { const index = this._updateCallbacks.indexOf(callback); if (index !== -1) { this._updateCallbacks.splice(index, 1); } } /** * 清除所有时间更新回调 */ static clearUpdateCallbacks() { this._updateCallbacks.length = 0; } /** * 重置时间管理器 */ static reset() { this._initialized = false; this._frameCount = 0; this._currentTime = 0; this._lastTime = 0; this._deltaTime = 0; this._unscaledDeltaTime = 0; this._timeScale = 1.0; // 重置时间缩放 this._maxDeltaTime = 0.1; // 重置最大时间差 this.clearUpdateCallbacks(); } /** * 获取时间管理器统计信息 */ static getStats() { return { currentTime: this._currentTime, deltaTime: this._deltaTime, unscaledDeltaTime: this._unscaledDeltaTime, timeScale: this._timeScale, frameCount: this._frameCount, averageFPS: this.getAverageFPS(), currentFPS: this.getCurrentFPS(), maxDeltaTime: this._maxDeltaTime, useHighPrecision: this._useHighPrecision }; } } /** 当前时间(秒) */ TimeManager._currentTime = 0; /** 上一帧时间(秒) */ TimeManager._lastTime = 0; /** 帧间时间差(秒) */ TimeManager._deltaTime = 0; /** 未缩放的帧间时间差(秒) */ TimeManager._unscaledDeltaTime = 0; /** 时间缩放比例 */ TimeManager._timeScale = 1.0; /** 最大允许的帧间时间差(防止时间跳跃) */ TimeManager._maxDeltaTime = 0.1; /** 是否使用高精度时间 */ TimeManager._useHighPrecision = true; /** 是否已初始化 */ TimeManager._initialized = false; /** 帧计数器 */ TimeManager._frameCount = 0; /** 启动时间 */ TimeManager._startTime = 0; /** 时间更新回调列表 */ TimeManager._updateCallbacks = []; /** * 错误处理级别枚举 */ var ErrorLevel; (function (ErrorLevel) { /** 开发模式 - 严格检查,抛出所有错误 */ ErrorLevel[ErrorLevel["Development"] = 0] = "Development"; /** 测试模式 - 记录错误但不中断执行 */ ErrorLevel[ErrorLevel["Testing"] = 1] = "Testing"; /** 生产模式 - 最小化错误处理,优先性能 */ ErrorLevel[ErrorLevel["Production"] = 2] = "Production"; /** 静默模式 - 完全禁用错误处理 */ ErrorLevel[ErrorLevel["Silent"] = 3] = "Silent"; })(ErrorLevel || (ErrorLevel = {})); /** * 高性能错误处理系统 * * @description * 提供可配置的错误处理策略,支持开发和生产环境的不同行为。 * 在生产环境中可以完全禁用错误检查以提高性能。 * * @example * ```typescript * // 配置错误处理器 * ErrorHandler.configure({ * level: ErrorLevel.Development, * enableAssertions: true, * enableTypeChecking: true * }); * * // 使用断言 * ErrorHandler.assert(player.health > 0, '玩家血量必须大于0'); * * // 类型检查 * ErrorHandler.checkType(value, 'number', '值必须是数字'); * * // 性能监控 * const result = ErrorHandler.monitor('expensiveFunction', () => { * return expensiveOperation(); * }); * ``` */ class ErrorHandler { /** * 配置错误处理器 * @param config 配置选项 */ static configure(config) { this._config = { ...this._config, ...config }; } /** * 设置错误处理级别 * @param level 错误处理级别 */ static setLevel(level) { this._config.level = level; // 根据级别自动调整其他配置 switch (level) { case ErrorLevel.Development: this._config.enableAssertions = true; this._config.enableTypeChecking = true; break; case ErrorLevel.Testing: this._config.enableAssertions = true; this._config.enableTypeChecking = false; break; case ErrorLevel.Production: this._config.enableAssertions = false; this._config.enableTypeChecking = false; break; case ErrorLevel.Silent: this._config.enableAssertions = false; this._config.enableTypeChecking = false; this._config.enablePerformanceMonitoring = false; break; } } /** * 断言检查 * @param condition 条件 * @param message 错误消息 * @param context 上下文信息 */ static assert(condition, message, context) { if (!this._config.enableAssertions || this._config.level === ErrorLevel.Silent) { return; } this._errorStats.totalAssertions++; if (!condition) { const error = new Error(`断言失败: ${message}`); this._handleError(error, context); } } /** * 类型检查 * @param value 要检查的值 * @param expectedType 期望的类型 * @param message 错误消息 * @param context 上下文信息 */ static checkType(value, expectedType, message, context) { if (!this._config.enableTypeChecking || this._config.level === ErrorLevel.Silent) { return; } this._errorStats.totalTypeChecks++; const actualType = typeof value; if (actualType !== expectedType) { const errorMessage = message || `类型检查失败: 期望 ${expectedType}, 实际 ${actualType}`; const error = new Error(errorMessage); this._handleError(error, context); } } /** * 非空检查 * @param value 要检查的值 * @param message 错误消息 * @param context 上下文信息 */ static checkNotNull(value, message, context) { if (!this._config.enableTypeChecking || this._config.level === ErrorLevel.Silent) { return; } this._errorStats.totalTypeChecks++; if (value == null) { const errorMessage = message || '值不能为null或undefined'; const error = new Error(errorMessage); this._handleError(error, context); } } /** * 范围检查 * @param value 要检查的值 * @param min 最小值 * @param max 最大值 * @param message 错误消息 * @param context 上下文信息 */ static checkRange(value, min, max, message, context) { if (!this._config.enableAssertions || this._config.level === ErrorLevel.Silent) { return; } this._errorStats.totalAssertions++; if (value < min || value > max) { const errorMessage = message || `值 ${value} 超出范围 [${min}, ${max}]`; const error = new Error(errorMessage); this._handleError(error, context); } } /** * 数组边界检查 * @param array 数组 * @param index 索引 * @param message 错误消息 * @param context 上下文信息 */ static checkArrayBounds(array, index, message, context) { if (!this._config.enableAssertions || this._config.level === ErrorLevel.Silent) { return; } this._errorStats.totalAssertions++; if (index < 0 || index >= array.length) { const errorMessage = message || `数组索引 ${index} 超出边界 [0, ${array.length - 1}]`; const error = new Error(errorMessage); this._handleError(error, context); } } /** * 性能监控装饰器 * @param name 函数名称 * @param fn 要监控的函数 * @returns 函数执行结果 */ static monitor(name, fn) { if (!this._config.enablePerformanceMonitoring || this._config.level === ErrorLevel.Silent) { return fn(); } const startTime = performance.now(); try { const result = fn(); const endTime = performance.now(); this._recordPerformance(name, endTime - startTime); return result; } catch (error) { const endTime = performance.now(); this._recordPerformance(name, endTime - startTime); throw error; } } /** * 异步性能监控 * @param name 函数名称 * @param fn 要监控的异步函数 * @returns Promise结果 */ static async monitorAsync(name, fn) { if (!this._config.enablePerformanceMonitoring || this._config.level === ErrorLevel.Silent) { return fn(); } const startTime = performance.now(); try { const result = await fn(); const endTime = performance.now(); this._recordPerformance(name, endTime - startTime); return result; } catch (error) { const endTime = performance.now(); this._recordPerformance(name, endTime - startTime); throw error; } } /** * 记录性能数据 */ static _recordPerformance(name, executionTime) { let data = this._performanceData.get(name); if (!data) { data = { functionName: name, executionTime: 0, callCount: 0, averageTime: 0, maxTime: 0, minTime: Infinity }; this._performanceData.set(name, data); } data.callCount++; data.executionTime += executionTime; data.averageTime = data.executionTime / data.callCount; data.maxTime = Math.max(data.maxTime, executionTime); data.minTime = Math.min(data.minTime, executionTime); } /** * 处理错误 */ static _handleError(error, context) { this._errorStats.totalErrors++; // 调用错误回调 if (this._config.onError) { try { this._config.onError(error, context); } catch (callbackError) { console.error('错误回调执行失败:', callbackError); } } // 根据错误级别决定行为 switch (this._config.level) { case ErrorLevel.Development: throw error; // 开发模式:抛出错误 case ErrorLevel.Testing: console.error('错误:', error.message, context); throw error; // 测试模式:记录并抛出 case ErrorLevel.Production: console.warn('错误:', error.message); throw error; // 生产模式:警告并抛出 } throw error; // 默认行为 } /** * 发出警告 * @param message 警告消息 * @param context 上下文信息 */ static warn(message, context) { if (this._config.level === ErrorLevel.Silent) { return; } this._errorStats.totalWarnings++; // 调用警告回调 if (this._config.onWarning) { try { this._config.onWarning(message, context); } catch (callbackError) { console.error('警告回调执行失败:', callbackError); } } // 根据错误级别决定输出方式 switch (this._config.level) { case ErrorLevel.Development: case ErrorLevel.Testing: console.warn('警告:', message, context); break; case ErrorLevel.Production: console.warn('警告:', message); break; } } /** * 获取性能统计信息 */ static getPerformanceStats() { return new Map(this._performanceData); } /** * 获取错误统计信息 */ static getErrorStats() { return { ...this._errorStats }; } /** * 重置统计信息 */ static resetStats() { this._performanceData.clear(); this._errorStats = { totalErrors: 0, totalWarnings: 0, totalAssertions: 0, totalTypeChecks: 0 }; } /** * 获取当前配置 */ static getConfig() { return { ...this._config }; } /** * 创建带错误处理的函数包装器 * @param fn 原函数 * @param name 函数名称 * @param enableMonitoring 是否启用性能监控 * @returns 包装后的函数 */ static wrap(fn, name, enableMonitoring = false) { return (...args) => { try { if (enableMonitoring) { return this.monitor(name, () => fn(...args)); } else { return fn(...args); } } catch (error) { this._handleError(error instanceof Error ? error : new Error(String(error)), { args, functionName: name }); } }; } } ErrorHandler._config = { level: ErrorLevel.Development, enableAssertions: true, enableTypeChecking: true, enablePerformanceMonitoring: false }; /** 性能监控数据 */ ErrorHandler._performanceData = new Map(); /** 错误统计 */ ErrorHandler._errorStats = { totalErrors: 0, totalWarnings: 0, totalAssertions: 0, totalTypeChecks: 0 }; /** * 错误处理装饰器工厂 * @param options 装饰器选项 */ function errorHandler(options = {}) { return function (target, propertyKey, descriptor) { const originalMethod = descriptor.value; const methodName = options.name || `${target.constructor.name}.${propertyKey}`; descriptor.value = function (...args) { // 类型检查 if (options.enableTypeChecking) { for (let i = 0; i < args.length; i++) { if (args[i] == null) { ErrorHandler.warn(`方法 ${methodName} 的第 ${i + 1} 个参数为null或undefined`); } } } // 执行方法 if (options.enableMonitoring) { return ErrorHandler.monitor(methodName, () => originalMethod.apply(this, args)); } else { try { return originalMethod.apply(this, args); } catch (error) { const errorInstance = error instanceof Error ? error : new Error(String(error)); ErrorHandler.warn(`方法 ${methodName} 执行失败`, { error: errorInstance, args, instance: this }); throw errorInstance; } } }; return descriptor; }; } /** * 高性能事件管理器 * * @description * 提供带自动清理机制的事件管理系统,防止内存泄漏。 * 支持弱引用、优先级、一次性监听器等高级功能。 * * @example * ```typescript * const eventManager = new EventManager({ * enableAutoCleanup: true, * cleanupInterval: 30000, // 30秒清理一次 * maxListeners: 1000 * }); * * // 添加监听器 * const listenerId = eventManager.on('playerDeath', (data) => { * console.log('玩家死亡:', data); * }); * * // 添加弱引用监听器(自动清理) * eventManager.onWeak('gameUpdate', callback, gameObject); * * // 触发事件 * eventManager.emit('playerDeath', { playerId: 123 }); * * // 移除监听器 * eventManager.off('playerDeath', listenerId); * ``` */ class EventManager { /** * 创建事件管理器 * @param config 配置选项 */ constructor(config = {}) { this._listeners = new Map(); this._cleanupTimer = null; this._nextListenerId = 1; this._config = { enableAutoCleanup: config.enableAutoCleanup ?? true, cleanupInterval: config.cleanupInterval ?? 30000, // 30秒 maxListeners: config.maxListeners ?? 1000, listenerExpirationTime: config.listenerExpirationTime ?? 300000, // 5分钟 enablePerformanceMonitoring: config.enablePerformanceMonitoring ?? false }; this._stats = { totalListeners: 0, activeListeners: 0, totalEvents: 0, averageEventTime: 0, lastCleanupTime: Date.now() }; // 启动自动清理 if (this._config.enableAutoCleanup) { this._startAutoCleanup(); } } /** * 添加事件监听器 * @param eventName 事件名称 * @param callback 回调函数 * @param options 监听器选项 * @returns 监听器ID */ on(eventName, callback, options = {}) { const listenerId = this._generateListenerId(); const listener = { callback, id: listenerId, createdAt: Date.now(), lastCalledAt: 0, callCount: 0, once: options.once ?? false, priority: options.priority ?? 0, weak: options.weak ?? false, owner: options.owner || undefined }; // 检查监听器数量限制 if (this._stats.totalListeners >= this._config.maxListeners) { console.warn(`事件监听器数量已达到上限 ${this._config.maxListeners}`); this.cleanup(); // 尝试清理 if (this._stats.totalListeners >= this._config.maxListeners) { throw new Error('无法添加更多事件监听器,已达到上限'); } } // 添加到监听器列表 if (!this._listeners.has(eventName)) { this._listeners.set(eventName, []); } const listeners = this._