feat: 优化打斗逻辑

This commit is contained in:
richarjiang
2025-10-20 15:38:20 +08:00
parent 77ced55142
commit f70bf7ba14
4 changed files with 189 additions and 52 deletions

View File

@@ -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} 不存在`);
}
}
/**