import { _decorator, Component, Node, Vec3, find, BoxCollider2D, RigidBody2D, Collider2D, Contact2DType, IPhysics2DContact, ERigidBody2DType } from 'cc'; import { sp } from 'cc'; import EventBus, { GameEvents } from '../../Core/EventBus'; import { EnemyAttackStateManager } from '../EnemyAttackStateManager'; import { GroundBurnAreaManager } from './GroundBurnAreaManager'; import { PhysicsManager } from '../../Core/PhysicsManager'; const { ccclass, property } = _decorator; /** * 地面燃烧区域组件 * 用于在地面创建固定范围的燃烧区域,对进入区域的敌人造成持续伤害 */ @ccclass('GroundBurnArea') export class GroundBurnArea extends Component { private _duration: number = 0; private _damage: number = 0; private _tickInterval: number = 0; private _isActive: boolean = false; private _burnEffectNode: Node | null = null; // 燃烧特效节点 private _enemiesInArea: Set = new Set(); // 区域内的敌人 private _damageTimer: number = 0; // 伤害计时器 /** * 组件加载时的初始化 */ protected onLoad(): void { // 立即禁用RigidBody2D组件,防止在物理世界未准备好时激活 const rigidBody = this.node.getComponent(RigidBody2D); if (rigidBody) { rigidBody.enabled = false; } // 也禁用BoxCollider2D组件,确保完全避免物理系统访问 const collider = this.node.getComponent(BoxCollider2D); if (collider) { collider.enabled = false; } } /** * 初始化地面燃烧区域 * @param position 燃烧区域位置 * @param duration 持续时间(秒) * @param damage 每次伤害值 * @param tickInterval 伤害间隔(秒) */ public initGroundBurnArea(position: Vec3, duration: number, damage: number, tickInterval: number): void { this._duration = duration; this._damage = damage; this._tickInterval = tickInterval; this._isActive = true; this._damageTimer = 0; // 设置节点位置 this.node.setWorldPosition(position); // 获取预制体中的火焰特效节点 this.setupFlameEffect(); // 先禁用RigidBody2D组件,避免在物理世界未准备好时激活 const rigidBody = this.node.getComponent(RigidBody2D); if (rigidBody) { rigidBody.enabled = false; } // 设置碰撞器 this.setupCollider(); console.log(`[GroundBurnArea] 初始化地面燃烧区域 - 位置: (${position.x.toFixed(1)}, ${position.y.toFixed(1)}), 持续时间: ${duration}秒, 伤害: ${damage}, 间隔: ${tickInterval}秒`); // 启动燃烧区域 this.startBurnArea(); } /** * 设置碰撞器 */ private setupCollider(): void { // 延迟设置碰撞器,确保物理系统已初始化 this.scheduleOnce(() => { this.trySetupCollider(); }, 0.2); // 增加延迟时间到0.2秒 } private trySetupCollider(): void { // 检查物理系统是否已初始化 const physicsManager = PhysicsManager.getInstance(); if (!physicsManager) { console.warn('[GroundBurnArea] 物理系统未初始化,延迟重试'); // 延迟重试 this.scheduleOnce(() => { this.trySetupCollider(); }, 0.1); return; } const physicsSystem = physicsManager.getSystem(); if (!physicsSystem || !physicsSystem.enable) { console.warn('[GroundBurnArea] 物理系统未启用,延迟重试'); // 延迟重试 this.scheduleOnce(() => { this.trySetupCollider(); }, 0.1); return; } // 获取碰撞器组件 const collider = this.node.getComponent(BoxCollider2D); if (!collider) { console.error('[GroundBurnArea] 未找到 BoxCollider2D 组件'); return; } // 重新启用碰撞器组件 collider.enabled = true; // 获取刚体组件并确保启用碰撞监听 const rigidBody = this.node.getComponent(RigidBody2D); if (rigidBody) { try { rigidBody.type = ERigidBody2DType.Static; rigidBody.enabledContactListener = true; // 重新启用RigidBody2D组件 rigidBody.enabled = true; } catch (error) { console.error('[GroundBurnArea] 设置刚体组件时出错:', error); // 如果设置失败,再次延迟重试 this.scheduleOnce(() => { this.trySetupCollider(); }, 0.1); return; } } // 监听碰撞事件(移除之前的监听器避免重复) collider.off(Contact2DType.BEGIN_CONTACT, this.onBeginContact, this); collider.off(Contact2DType.END_CONTACT, this.onEndContact, this); collider.on(Contact2DType.BEGIN_CONTACT, this.onBeginContact, this); collider.on(Contact2DType.END_CONTACT, this.onEndContact, this); console.log(`[GroundBurnArea] 碰撞器设置完成,碰撞器启用: ${collider.enabled}, 刚体启用: ${rigidBody?.enabled}`); // 验证碰撞器设置 if (!collider.enabled) { console.error('[GroundBurnArea] 碰撞器未启用!'); } if (rigidBody && !rigidBody.enabled) { console.error('[GroundBurnArea] 刚体未启用!'); } if (rigidBody && !rigidBody.enabledContactListener) { console.error('[GroundBurnArea] 刚体碰撞监听未启用!'); } } /** * 敌人进入燃烧区域 */ private onBeginContact(selfCollider: Collider2D, otherCollider: Collider2D, contact: IPhysics2DContact | null): void { const enemyNode = otherCollider.node; console.log(`[GroundBurnArea] 碰撞检测 - 节点名称: ${enemyNode.name}, 父节点: ${enemyNode.parent?.name || 'null'}`); // 检查是否是敌人 if (this.isEnemyNode(enemyNode)) { // 仅记录可攻击的敌人进入燃烧区域(隐身等状态不记录) const attackStateManager = EnemyAttackStateManager.getInstance(); if (attackStateManager && !attackStateManager.isEnemyAttackable(enemyNode)) { console.log(`[GroundBurnArea] 敌人不可攻击(隐身等),不加入区域: ${enemyNode.name}`); return; } this._enemiesInArea.add(enemyNode); console.log(`[GroundBurnArea] 敌人进入燃烧区域: ${enemyNode.name}, 区域内敌人数量: ${this._enemiesInArea.size}`); } else { console.log(`[GroundBurnArea] 非敌人节点进入燃烧区域: ${enemyNode.name}`); } } /** * 敌人离开燃烧区域 */ private onEndContact(selfCollider: Collider2D, otherCollider: Collider2D, contact: IPhysics2DContact | null): void { const enemyNode = otherCollider.node; // 检查是否是敌人 if (this.isEnemyNode(enemyNode)) { this._enemiesInArea.delete(enemyNode); console.log(`[GroundBurnArea] 敌人离开燃烧区域: ${enemyNode.name}, 区域内敌人数量: ${this._enemiesInArea.size}`); } } /** * 检查是否是敌人节点 */ private isEnemyNode(node: Node): boolean { if (!node || !node.name) { return false; } // 检查是否为EnemySprite子节点 if (node.name === 'EnemySprite' && node.parent) { const hasEnemyComponent = node.parent.getComponent('EnemyInstance') !== null; console.log(`[GroundBurnArea] EnemySprite检测 - 节点: ${node.name}, 父节点: ${node.parent.name}, 有EnemyInstance组件: ${hasEnemyComponent}`); return hasEnemyComponent; } // 检查节点名称 const nameCheck = ( node.name.includes('Enemy') || node.name.includes('enemy') || node.name.includes('僵尸') || node.name.includes('Zombie') || node.name.includes('zombie') ); // 检查父节点名称 const parentCheck = ( node.parent?.name === 'enemyContainer' || node.parent?.name === 'EnemyContainer' || node.parent?.name?.includes('enemy') || node.parent?.name?.includes('Enemy') ); // 检查是否有EnemyInstance组件 const componentCheck = node.getComponent('EnemyInstance') !== null; const isEnemy = nameCheck || parentCheck || componentCheck; console.log(`[GroundBurnArea] 敌人检测 - 节点: ${node.name}, 父节点: ${node.parent?.name || 'null'}, 名称检查: ${nameCheck}, 父节点检查: ${parentCheck}, 组件检查: ${componentCheck}, 是敌人: ${isEnemy}`); return isEnemy; } /** * 启动燃烧区域 */ private startBurnArea(): void { if (!this._isActive) { return; } console.log(`[GroundBurnArea] 启动地面燃烧区域 - 持续时间: ${this._duration}秒`); // 启动更新循环 this.schedule(this.updateBurnArea, 0.1); // 每0.1秒更新一次 // 设置区域销毁定时器 this.scheduleOnce(() => { this.destroyBurnArea(); }, this._duration); } /** * 更新燃烧区域 */ private updateBurnArea(deltaTime: number): void { if (!this._isActive) { return; } // 更新伤害计时器 this._damageTimer += deltaTime; // 检查是否到了造成伤害的时间 if (this._damageTimer >= this._tickInterval) { console.log(`[GroundBurnArea] 燃烧区域伤害检查 - 区域内敌人数量: ${this._enemiesInArea.size}, 伤害值: ${this._damage}`); this.dealDamageToEnemiesInArea(); this._damageTimer = 0; } // 清理无效的敌人节点 this.cleanupInvalidEnemies(); } /** * 对区域内的敌人造成伤害 */ private dealDamageToEnemiesInArea(): void { if (this._enemiesInArea.size === 0) { return; } console.log(`[GroundBurnArea] 对区域内 ${this._enemiesInArea.size} 个敌人造成燃烧伤害: ${this._damage}`); const eventBus = EventBus.getInstance(); const attackStateManager = EnemyAttackStateManager.getInstance(); // 对每个区域内的敌人造成伤害 for (const enemyNode of this._enemiesInArea) { if (enemyNode && enemyNode.isValid) { // 检查敌人是否处于漂移状态 const enemyInstance = enemyNode.getComponent('EnemyInstance') as any; if (enemyInstance && enemyInstance.isDrifting()) { console.log(`[GroundBurnArea] 敌人 ${enemyNode.name} 处于漂移状态,跳过燃烧伤害`); continue; } // 检查敌人是否可攻击(隐身等状态不可受伤害) if (attackStateManager && !attackStateManager.isEnemyAttackable(enemyNode)) { console.log(`[GroundBurnArea] 敌人不可攻击,跳过燃烧伤害: ${enemyNode.name}`); continue; } const damageData = { enemyNode: enemyNode, damage: this._damage, isCritical: false, source: 'GroundBurnArea' }; eventBus.emit(GameEvents.APPLY_DAMAGE_TO_ENEMY, damageData); } } } /** * 清理无效的敌人节点 */ private cleanupInvalidEnemies(): void { const invalidEnemies: Node[] = []; for (const enemyNode of this._enemiesInArea) { if (!enemyNode || !enemyNode.isValid) { invalidEnemies.push(enemyNode); } } // 移除无效的敌人 for (const invalidEnemy of invalidEnemies) { this._enemiesInArea.delete(invalidEnemy); } } /** * 设置火焰特效 */ private setupFlameEffect(): void { // 查找预制体中的 FlameEffect 子节点 const flameEffectNode = this.node.getChildByName('FlameEffect'); if (flameEffectNode) { this._burnEffectNode = flameEffectNode; // 启动火焰特效动画 const skeleton = flameEffectNode.getComponent(sp.Skeleton); if (skeleton) { skeleton.setAnimation(0, 'animation', true); console.log('[GroundBurnArea] 火焰特效节点已找到并开始播放动画'); } else { console.warn('[GroundBurnArea] FlameEffect 节点缺少 sp.Skeleton 组件'); } } else { console.warn('[GroundBurnArea] 未找到 FlameEffect 子节点,请检查预制体配置'); } } /** * 设置燃烧特效节点 */ public setBurnEffectNode(effectNode: Node): void { this._burnEffectNode = effectNode; } /** * 销毁燃烧区域 */ public destroyBurnArea(): void { console.log(`[GroundBurnArea] 销毁地面燃烧区域`); this._isActive = false; this.unscheduleAllCallbacks(); // 清空敌人列表 this._enemiesInArea.clear(); // 销毁燃烧特效节点 if (this._burnEffectNode && this._burnEffectNode.isValid) { console.log(`[GroundBurnArea] 销毁燃烧特效节点`); this._burnEffectNode.destroy(); this._burnEffectNode = null; } // 通知管理器移除此燃烧区域 const manager = GroundBurnAreaManager.getInstance(); if (manager) { manager.removeBurnArea(this.node); } // 销毁节点 if (this.node && this.node.isValid) { this.node.destroy(); } } /** * 获取燃烧区域是否激活 */ public isActive(): boolean { return this._isActive; } /** * 获取区域内敌人数量 */ public getEnemyCount(): number { return this._enemiesInArea.size; } /** * 组件销毁时清理资源 */ protected onDestroy(): void { this._isActive = false; this.unscheduleAllCallbacks(); // 清空敌人列表 this._enemiesInArea.clear(); // 清理燃烧特效节点 if (this._burnEffectNode && this._burnEffectNode.isValid) { console.log(`[GroundBurnArea] 组件销毁时清理燃烧特效节点`); this._burnEffectNode.destroy(); this._burnEffectNode = null; } // 通知管理器移除此燃烧区域 const manager = GroundBurnAreaManager.getInstance(); if (manager) { manager.removeBurnArea(this.node); } console.log(`[GroundBurnArea] 地面燃烧区域组件已销毁`); } }