| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532 |
- 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碰撞'
- });
- }
- }
- }
|