feat: 优化打斗逻辑
This commit is contained in:
@@ -982,46 +982,188 @@ export class PlayerController extends Component {
|
||||
return;
|
||||
}
|
||||
|
||||
// 检查是否是 guai_10,如果是则使用特殊战斗逻辑
|
||||
if (otherCollider.node.name === 'guai_10') {
|
||||
await this.handleGuai10SpecialAttack(selfCollider, otherCollider, playerLabel, monsterLabel, playerHp, monsterHp, playerAnimation);
|
||||
} else {
|
||||
// 原有的普通战斗逻辑
|
||||
await this.handleNormalAttack(otherCollider, playerLabel, monsterLabel, playerHp, monsterHp, playerAnimation);
|
||||
}
|
||||
|
||||
this.isAttacking = false;
|
||||
|
||||
// 停止攻击音效
|
||||
if (this.attackAudio) {
|
||||
const audioSource = this.attackAudio.getComponent(AudioSource);
|
||||
if (audioSource) {
|
||||
audioSource.stop();
|
||||
console.log('停止攻击音效');
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理普通怪物的攻击逻辑
|
||||
*/
|
||||
private async handleNormalAttack(otherCollider: Collider2D, playerLabel: Label, monsterLabel: Label, playerHp: number, monsterHp: number, playerAnimation: Animation) {
|
||||
// 播放玩家攻击动画(只传递基础动画名称)
|
||||
this.switchAnimation('attack');
|
||||
|
||||
// 监听玩家攻击动画结束事件
|
||||
playerAnimation.once(Animation.EventType.FINISHED, async () => {
|
||||
if (!this.player || !playerLabel.isValid || !monsterLabel.isValid) {
|
||||
this.isAttacking = false;
|
||||
if (this.attackAudio) {
|
||||
const audioSource = this.attackAudio.getComponent(AudioSource);
|
||||
if (audioSource) {
|
||||
audioSource.stop();
|
||||
}
|
||||
return new Promise<void>((resolve) => {
|
||||
playerAnimation.once(Animation.EventType.FINISHED, async () => {
|
||||
if (!this.player || !playerLabel.isValid || !monsterLabel.isValid) {
|
||||
resolve();
|
||||
return;
|
||||
}
|
||||
|
||||
// 比较生命值,判断输赢
|
||||
console.log('判定攻击结果,玩家HP:', playerHp, '怪物HP:', monsterHp);
|
||||
|
||||
if (playerHp >= monsterHp) {
|
||||
// 玩家获胜,直接执行后续流程,不需要播放怪物攻击动画
|
||||
await this.handlePlayerWin(otherCollider, playerLabel, monsterHp);
|
||||
} else {
|
||||
// 玩家输了,需要播放怪物攻击动画
|
||||
await this.handleMonsterAttack(otherCollider, playerLabel, monsterHp);
|
||||
}
|
||||
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理 guai_10 的特殊攻击逻辑:玩家攻击 → 怪物还击 → 玩家再攻击 → 最终判定
|
||||
*/
|
||||
private async handleGuai10SpecialAttack(selfCollider: Collider2D, otherCollider: Collider2D, playerLabel: Label, monsterLabel: Label, playerHp: number, monsterHp: number, playerAnimation: Animation) {
|
||||
console.log('开始 guai_10 特殊战斗逻辑');
|
||||
|
||||
// 第一轮:玩家攻击
|
||||
console.log('第一轮:玩家攻击');
|
||||
this.switchAnimation('attack');
|
||||
|
||||
// 等待玩家攻击动画结束
|
||||
await new Promise<void>((resolve) => {
|
||||
playerAnimation.once(Animation.EventType.FINISHED, () => {
|
||||
console.log('玩家第一轮攻击完成');
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
|
||||
// 检查节点是否仍然有效
|
||||
if (!this.player || !otherCollider.node || !otherCollider.node.isValid || !playerLabel.isValid || !monsterLabel.isValid) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 第二轮:怪物还击
|
||||
console.log('第二轮:怪物还击');
|
||||
await this.playMonsterAttackAnimation(otherCollider);
|
||||
|
||||
// 检查节点是否仍然有效
|
||||
if (!this.player || !otherCollider.node || !otherCollider.node.isValid || !playerLabel.isValid || !monsterLabel.isValid) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 确保玩家在怪物攻击后回到站立状态,然后再进行第三轮攻击
|
||||
this.switchAnimation('stand');
|
||||
|
||||
// 添加短暂延迟,让玩家站立动画播放一下
|
||||
await new Promise<void>((resolve) => {
|
||||
this.scheduleOnce(() => {
|
||||
resolve();
|
||||
}, 0.2);
|
||||
});
|
||||
|
||||
// 第三轮:玩家再次攻击
|
||||
console.log('第三轮:玩家再次攻击');
|
||||
this.switchAnimation('attack');
|
||||
|
||||
// 等待玩家攻击动画结束
|
||||
await new Promise<void>((resolve) => {
|
||||
playerAnimation.once(Animation.EventType.FINISHED, () => {
|
||||
console.log('玩家第三轮攻击完成');
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
|
||||
// 检查节点是否仍然有效
|
||||
if (!this.player || !otherCollider.node || !otherCollider.node.isValid || !playerLabel.isValid || !monsterLabel.isValid) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 最终判定:比较生命值
|
||||
console.log('最终判定,玩家HP:', playerHp, '怪物HP:', monsterHp);
|
||||
|
||||
if (playerHp >= monsterHp) {
|
||||
// 玩家获胜
|
||||
await this.handlePlayerWin(otherCollider, playerLabel, monsterHp);
|
||||
} else {
|
||||
// 玩家失败
|
||||
this.executePlayerDefeat(otherCollider, playerLabel);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 播放怪物攻击动画
|
||||
*/
|
||||
private async playMonsterAttackAnimation(otherCollider: Collider2D): Promise<void> {
|
||||
const animNode = otherCollider.node.getChildByName('Anim');
|
||||
const monsterAnimation = animNode ? animNode.getComponent(Animation) : null;
|
||||
|
||||
if (monsterAnimation) {
|
||||
console.log(`尝试播放怪物攻击动画: ${otherCollider.node.name}_attack`);
|
||||
|
||||
// 检查动画是否存在
|
||||
const attackAnimState = monsterAnimation.getState(`${otherCollider.node.name}_attack`);
|
||||
if (!attackAnimState) {
|
||||
console.warn(`怪物攻击动画 ${otherCollider.node.name}_attack 不存在,跳过怪物攻击动画`);
|
||||
return;
|
||||
}
|
||||
|
||||
// 比较生命值,判断输赢
|
||||
console.log('判定攻击结果,玩家HP:', playerHp, '怪物HP:', monsterHp);
|
||||
return new Promise<void>((resolve) => {
|
||||
// 添加超时机制,防止动画卡住
|
||||
const timeout = setTimeout(() => {
|
||||
console.log('怪物攻击动画超时,强制继续');
|
||||
// 确保怪物切换回站立状态
|
||||
this.switchMonsterToStand(otherCollider.node.name, monsterAnimation);
|
||||
resolve();
|
||||
}, 3000); // 3秒超时
|
||||
|
||||
if (playerHp >= monsterHp) {
|
||||
// 玩家获胜,直接执行后续流程,不需要播放怪物攻击动画
|
||||
await this.handlePlayerWin(otherCollider, playerLabel, monsterHp);
|
||||
} else {
|
||||
// 玩家输了,需要播放怪物攻击动画
|
||||
await this.handleMonsterAttack(otherCollider, playerLabel, monsterHp);
|
||||
}
|
||||
monsterAnimation.play(`${otherCollider.node.name}_attack`);
|
||||
console.log('开始播放怪物攻击动画');
|
||||
|
||||
this.isAttacking = false;
|
||||
// 监听怪物攻击动画结束
|
||||
monsterAnimation.once(Animation.EventType.FINISHED, () => {
|
||||
clearTimeout(timeout);
|
||||
console.log('怪物攻击动画完成,切换回站立状态');
|
||||
// 怪物攻击完成后切换回站立动画
|
||||
this.switchMonsterToStand(otherCollider.node.name, monsterAnimation);
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
} else {
|
||||
console.warn('未找到怪物动画组件,跳过怪物攻击动画');
|
||||
// 如果没有怪物动画组件,直接返回
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// 停止攻击音效
|
||||
if (this.attackAudio) {
|
||||
const audioSource = this.attackAudio.getComponent(AudioSource);
|
||||
if (audioSource) {
|
||||
audioSource.stop();
|
||||
console.log('停止攻击音效');
|
||||
}
|
||||
}
|
||||
});
|
||||
/**
|
||||
* 将怪物切换到站立动画
|
||||
*/
|
||||
private switchMonsterToStand(monsterName: string, monsterAnimation: Animation) {
|
||||
const standAnimName = `${monsterName}_stand`;
|
||||
const standAnimState = monsterAnimation.getState(standAnimName);
|
||||
|
||||
return true;
|
||||
if (standAnimState) {
|
||||
monsterAnimation.play(standAnimName);
|
||||
console.log(`怪物切换到站立动画: ${standAnimName}`);
|
||||
} else {
|
||||
console.warn(`怪物站立动画 ${standAnimName} 不存在`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user