import { _decorator, Component, Node, Vec2, Vec3, find, RigidBody2D, Collider2D, Contact2DType, IPhysics2DContact } from 'cc'; const { ccclass, property } = _decorator; @ccclass('BulletController') export class BulletController extends Component { @property public speed: number = 300; @property public damage: number = 10; @property public lifetime: number = 5; private targetEnemy: Node = null; private rigidBody: RigidBody2D = null; private lifeTimer: number = 0; private initialDirection: Vec2 = null; // 存储初始方向 private direction: Vec3 = null; start() { console.log('🚀 子弹开始初始化...'); // 调试碰撞组信息 this.debugCollisionGroups(); // 获取刚体组件 this.rigidBody = this.node.getChildByName('Icon')?.getComponent(RigidBody2D); if (!this.rigidBody) { console.error('❌ 子弹找不到Icon子节点的RigidBody2D组件'); return; } console.log('✅ 子弹刚体组件获取成功'); // 重置刚体的预设速度 this.rigidBody.linearVelocity = new Vec2(0, 0); console.log('🔧 已重置刚体预设速度'); // 设置刚体参数 this.rigidBody.gravityScale = 0; // 不受重力影响 this.rigidBody.linearDamping = 0; // 无阻尼 this.rigidBody.angularDamping = 0; // 无角阻尼 this.rigidBody.allowSleep = false; // 不允许休眠 // 设置子弹生命周期 this.lifeTimer = this.lifetime; // 延迟一帧后再设置方向和速度,确保节点完全初始化 this.scheduleOnce(() => { this.initializeBulletDirection(); }, 0.02); // 注册碰撞事件 const collider = this.node.getChildByName('Icon')?.getComponent(Collider2D); if (collider) { collider.on(Contact2DType.BEGIN_CONTACT, this.onBeginContact, this); console.log('✅ 子弹碰撞事件已注册'); } else { console.error('❌ 子弹找不到Icon子节点的Collider2D组件'); } console.log('🚀 子弹初始化完成'); } // 初始化子弹方向 private initializeBulletDirection() { console.log('🎯 开始初始化子弹方向...'); // 如果没有设置目标,寻找最近的敌人 if (!this.targetEnemy) { this.findNearestEnemy(); } // 设置初始方向 if (this.targetEnemy) { console.log('🎯 设置子弹朝向目标敌人'); this.setDirectionToTarget(); } else { // 没有敌人目标时,设置随机方向 console.log('🎲 没有敌人目标,设置随机发射方向'); const randomAngle = Math.random() * Math.PI * 2; this.direction = new Vec3(Math.cos(randomAngle), Math.sin(randomAngle), 0); console.log('随机方向:', this.direction); } // 设置初始速度 this.updateVelocity(); // 再次确认速度设置 this.scheduleOnce(() => { if (this.rigidBody) { const currentVelocity = this.rigidBody.linearVelocity; console.log('🔍 最终确认子弹速度:', currentVelocity); const speed = Math.sqrt(currentVelocity.x * currentVelocity.x + currentVelocity.y * currentVelocity.y); console.log('🔍 速度大小:', speed); if (speed < 50) { console.warn('⚠️ 子弹速度过低,重新设置...'); this.updateVelocity(); } } }, 0.1); } // 寻找最近的敌人 private findNearestEnemy() { console.log('🔍 子弹开始寻找最近的敌人...'); // 主要路径:Canvas/GameLevelUI/enemyContainer const primaryPath = 'Canvas/GameLevelUI/enemyContainer'; let enemyContainer = find(primaryPath); if (enemyContainer) { console.log('✅ 找到主要敌人容器:', primaryPath); } else { console.log('❌ 主要路径未找到,尝试备用路径...'); // 备用路径 const backupPaths = [ 'Canvas/enemyContainer', 'Canvas/EnemyContainer', 'Canvas/GameLevelUI/EnemyContainer', 'Canvas/GameArea/enemyContainer' ]; for (const path of backupPaths) { enemyContainer = find(path); if (enemyContainer) { console.log('✅ 找到备用敌人容器:', path); break; } } } if (!enemyContainer) { console.log('❌ 未找到任何敌人容器,尝试在整个场景中搜索敌人节点...'); // 如果找不到容器,尝试直接搜索敌人节点 const allEnemies = this.findAllEnemyNodes(); if (allEnemies.length > 0) { this.selectNearestFromEnemies(allEnemies); } else { console.log('❌ 场景中没有找到任何敌人,子弹将随机发射'); } return; } // 打印容器详细信息 console.log('敌人容器详细信息:', { name: enemyContainer.name, childrenCount: enemyContainer.children.length, children: enemyContainer.children.map(child => ({ name: child.name, active: child.active, hasEnemyInstance: !!child.getComponent('EnemyInstance'), hasEnemyComponent: !!child.getComponent('EnemyComponent') })) }); // 在容器中查找敌人 - 使用更宽泛的匹配条件 const enemies = enemyContainer.children.filter(child => { if (!child.active) return false; // 跳过非激活的节点 const name = child.name.toLowerCase(); const hasEnemyComponent = child.getComponent('EnemyInstance') !== null || child.getComponent('EnemyComponent') !== null; return name === 'enemy' || name.includes('enemy') || name.includes('敌人') || hasEnemyComponent || name.startsWith('enemy') || name.endsWith('enemy'); }); console.log(`在容器中找到 ${enemies.length} 个敌人:`, enemies.map(e => ({ name: e.name, position: e.worldPosition }))); if (enemies.length === 0) { console.log('❌ 敌人容器中没有找到敌人,尝试将所有子节点作为潜在目标...'); // 如果没有找到明确的敌人,尝试将所有活动的子节点作为目标 const allActiveChildren = enemyContainer.children.filter(child => child.active); if (allActiveChildren.length > 0) { console.log(`🔍 将 ${allActiveChildren.length} 个活动子节点作为潜在目标`); this.selectNearestFromEnemies(allActiveChildren); } else { console.log('❌ 容器中没有任何活动节点,子弹将随机发射'); } return; } this.selectNearestFromEnemies(enemies); } // 在整个场景中搜索敌人节点 private findAllEnemyNodes(): Node[] { const canvas = find('Canvas'); if (!canvas) return []; const enemies: Node[] = []; this.searchEnemiesRecursive(canvas, enemies); console.log(`在整个场景中找到 ${enemies.length} 个敌人`); return enemies; } // 递归搜索敌人节点 private searchEnemiesRecursive(node: Node, enemies: Node[]) { // 检查当前节点是否为敌人 if (node.active) { const name = node.name.toLowerCase(); const hasEnemyComponent = node.getComponent('EnemyInstance') !== null || node.getComponent('EnemyComponent') !== null; if (name === 'enemy' || name.includes('enemy') || name.includes('敌人') || hasEnemyComponent || name.startsWith('enemy') || name.endsWith('enemy')) { enemies.push(node); console.log(`🎯 找到敌人节点: ${node.name} (路径: ${this.getNodePath(node)})`); } } // 递归搜索子节点 for (const child of node.children) { this.searchEnemiesRecursive(child, enemies); } } // 获取节点的完整路径 private getNodePath(node: Node): string { let path = node.name; let current = node; while (current.parent) { current = current.parent; path = current.name + '/' + path; } return path; } // 从敌人列表中选择最近的 private selectNearestFromEnemies(enemies: Node[]) { let nearestEnemy: Node = null; let nearestDistance = Infinity; const bulletPos = this.node.worldPosition; console.log('子弹当前位置:', bulletPos); for (const enemy of enemies) { try { const enemyPos = enemy.worldPosition; const distance = Vec3.distance(bulletPos, enemyPos); console.log(`敌人 ${enemy.name} 距离: ${distance.toFixed(1)}`); if (distance < nearestDistance) { nearestDistance = distance; nearestEnemy = enemy; } } catch (error) { console.error('计算敌人距离时出错:', error); } } if (nearestEnemy) { this.targetEnemy = nearestEnemy; console.log(`✅ 选定目标敌人: ${nearestEnemy.name}, 距离: ${nearestDistance.toFixed(1)}`); } else { console.log('❌ 无法确定最近敌人,子弹将随机发射'); } } // 设置朝向目标的方向 private setDirectionToTarget() { if (!this.targetEnemy) return; try { const targetPos = this.targetEnemy.worldPosition; const currentPos = this.node.worldPosition; console.log('子弹位置:', currentPos); console.log('目标敌人位置:', targetPos); this.direction = targetPos.subtract(currentPos).normalize(); console.log('计算出的发射方向:', this.direction); } catch (error) { console.error('❌ 计算子弹方向时出错:', error); // 备用方案:随机方向 const randomAngle = Math.random() * Math.PI * 2; this.direction = new Vec3(Math.cos(randomAngle), Math.sin(randomAngle), 0); console.log('使用备用随机方向:', this.direction); } } // 更新子弹速度方向 updateVelocity() { if (!this.rigidBody) { console.error('❌ 刚体组件不存在,无法设置速度'); return; } if (!this.direction) { console.error('❌ 子弹方向未设置,无法更新速度'); return; } // 确保方向向量已归一化 const normalizedDirection = this.direction.clone().normalize(); // 计算速度向量 const velocity = new Vec2( normalizedDirection.x * this.speed, normalizedDirection.y * this.speed ); console.log('🎯 设置子弹速度:', { direction: normalizedDirection, speed: this.speed, velocity: velocity }); // 强制设置速度 this.rigidBody.linearVelocity = velocity; // 立即验证速度是否设置成功 const actualVelocity = this.rigidBody.linearVelocity; const actualSpeed = Math.sqrt(actualVelocity.x * actualVelocity.x + actualVelocity.y * actualVelocity.y); console.log('✅ 子弹速度验证:', { 设置的速度: velocity, 实际速度: actualVelocity, 速度大小: actualSpeed.toFixed(2) }); if (Math.abs(actualSpeed - this.speed) > 10) { console.warn('⚠️ 速度设置可能失败,实际速度与期望不符'); // 尝试再次设置 this.scheduleOnce(() => { this.rigidBody.linearVelocity = velocity; console.log('🔄 重新设置子弹速度'); }, 0.01); } } // 碰撞检测 onBeginContact(selfCollider: Collider2D, otherCollider: Collider2D, contact: IPhysics2DContact | null) { const otherNode = otherCollider.node; console.log('💥 子弹发生碰撞:', { 子弹: selfCollider.node.name, 碰撞对象: otherNode.name, 碰撞对象路径: this.getNodePath(otherNode), 碰撞组: otherCollider.group }); // 检查是否击中敌人 - 使用更灵活的匹配条件 const isEnemy = this.isEnemyNode(otherNode); if (isEnemy) { console.log('🎯 子弹击中敌人:', otherNode.name); // 尝试对敌人造成伤害 this.damageEnemy(otherNode); // 销毁子弹 console.log('💥 子弹击中目标,即将销毁'); this.node.destroy(); } else { console.log('🚫 子弹击中非敌人对象:', otherNode.name); // 如果击中墙体或其他障碍物,也销毁子弹 if (otherNode.name.includes('Wall') || otherNode.name.includes('wall')) { console.log('🧱 子弹击中墙体,销毁子弹'); this.node.destroy(); } } } // 判断节点是否为敌人 private isEnemyNode(node: Node): boolean { const name = node.name.toLowerCase(); const hasEnemyComponent = node.getComponent('EnemyInstance') !== null || node.getComponent('EnemyComponent') !== null; const isEnemyByName = name === 'enemy' || name.includes('enemy') || name.includes('敌人') || name.startsWith('enemy') || name.endsWith('enemy'); console.log('🔍 敌人判定:', { 节点名称: node.name, 名称匹配: isEnemyByName, 组件匹配: hasEnemyComponent, 最终判定: isEnemyByName || hasEnemyComponent }); return isEnemyByName || hasEnemyComponent; } // 对敌人造成伤害 private damageEnemy(enemyNode: Node) { console.log('⚔️ 开始对敌人造成伤害:', enemyNode.name); // 方法1: 尝试通过EnemyController造成伤害 const enemyController = find('Canvas/GameLevelUI/EnemyController')?.getComponent('EnemyController') as any; if (enemyController && typeof enemyController.damageEnemy === 'function') { try { enemyController.damageEnemy(enemyNode, this.damage); console.log('✅ 通过EnemyController造成伤害:', this.damage); return; } catch (error) { console.error('❌ EnemyController.damageEnemy调用失败:', error); } } // 方法2: 尝试直接调用敌人组件的受伤方法 const enemyInstance = enemyNode.getComponent('EnemyInstance') as any; if (enemyInstance) { if (typeof enemyInstance.takeDamage === 'function') { try { enemyInstance.takeDamage(this.damage); console.log('✅ 通过EnemyInstance.takeDamage造成伤害:', this.damage); return; } catch (error) { console.error('❌ EnemyInstance.takeDamage调用失败:', error); } } if (typeof enemyInstance.damage === 'function') { try { enemyInstance.damage(this.damage); console.log('✅ 通过EnemyInstance.damage造成伤害:', this.damage); return; } catch (error) { console.error('❌ EnemyInstance.damage调用失败:', error); } } } // 方法3: 尝试其他可能的敌人组件 const enemyComponent = enemyNode.getComponent('EnemyComponent') as any; if (enemyComponent && typeof enemyComponent.takeDamage === 'function') { try { enemyComponent.takeDamage(this.damage); console.log('✅ 通过EnemyComponent.takeDamage造成伤害:', this.damage); return; } catch (error) { console.error('❌ EnemyComponent.takeDamage调用失败:', error); } } // 方法4: 简单的生命值减少(如果敌人有health属性) if (enemyInstance && typeof enemyInstance.health === 'number') { enemyInstance.health -= this.damage; console.log('✅ 直接减少敌人生命值:', { 伤害: this.damage, 剩余生命: enemyInstance.health }); // 如果生命值归零,尝试销毁敌人 if (enemyInstance.health <= 0) { console.log('💀 敌人生命值归零,尝试销毁'); if (typeof enemyInstance.die === 'function') { enemyInstance.die(); } else { enemyNode.destroy(); } } return; } console.warn('⚠️ 无法找到合适的方法对敌人造成伤害'); console.log('敌人节点信息:', { name: enemyNode.name, components: enemyNode.components.map(c => c.constructor.name), EnemyInstance: !!enemyNode.getComponent('EnemyInstance'), EnemyComponent: !!enemyNode.getComponent('EnemyComponent') }); } update(dt: number) { // 更新生命周期 this.lifeTimer -= dt; if (this.lifeTimer <= 0) { this.node.destroy(); return; } // 定期检查速度是否正确(每0.1秒检查一次) if (this.rigidBody && this.direction) { const currentVelocity = this.rigidBody.linearVelocity; const currentSpeed = Math.sqrt(currentVelocity.x * currentVelocity.x + currentVelocity.y * currentVelocity.y); // 如果速度过低,重新设置 if (currentSpeed < this.speed * 0.8) { console.log('🔧 检测到子弹速度过低,重新设置...'); this.updateVelocity(); } } // 注意:不再每帧更新速度方向,子弹将沿初始方向直线移动 } // 调试碰撞组信息 private debugCollisionGroups() { const iconNode = this.node.getChildByName('Icon'); if (iconNode) { const collider = iconNode.getComponent(Collider2D); const rigidBody = iconNode.getComponent(RigidBody2D); console.log('🔧 子弹碰撞组调试信息:', { 节点名称: iconNode.name, 碰撞体组: collider?.group, 刚体组: rigidBody?.group, 预期组: 3, // BULLET组 组名: 'BULLET' }); // 检查碰撞矩阵 const bulletGroup = 3; // BULLET const enemyGroup = 4; // ENEMY console.log('🎯 碰撞组配置:', { 子弹组: bulletGroup, 敌人组: enemyGroup, 提示: '子弹组3应该能与敌人组4碰撞' }); } } }