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

@@ -1,7 +1,7 @@
[ [
{ {
"__type__": "cc.AnimationClip", "__type__": "cc.AnimationClip",
"_name": "stand_2", "_name": "stand5_2",
"_objFlags": 0, "_objFlags": 0,
"__editorExtras__": { "__editorExtras__": {
"embeddedPlayerGroups": [] "embeddedPlayerGroups": []
@@ -9,7 +9,7 @@
"_native": "", "_native": "",
"sample": 20, "sample": 20,
"speed": 1, "speed": 1,
"wrapMode": 1, "wrapMode": 2,
"enableTrsBlending": false, "enableTrsBlending": false,
"_duration": 1.25, "_duration": 1.25,
"_hash": 500763545, "_hash": 500763545,

View File

@@ -7,11 +7,11 @@
"embeddedPlayerGroups": [] "embeddedPlayerGroups": []
}, },
"_native": "", "_native": "",
"sample": 60, "sample": 8,
"speed": 1, "speed": 1,
"wrapMode": 1, "wrapMode": 2,
"enableTrsBlending": false, "enableTrsBlending": false,
"_duration": 0.6, "_duration": 1,
"_hash": 500763545, "_hash": 500763545,
"_tracks": [ "_tracks": [
{ {
@@ -62,13 +62,13 @@
"__type__": "cc.ObjectCurve", "__type__": "cc.ObjectCurve",
"_times": [ "_times": [
0, 0,
0.08333333333333333, 0.125,
0.16666666666666666,
0.25, 0.25,
0.3333333333333333, 0.375,
0.4166666666666667,
0.5, 0.5,
0.5833333333333334 0.625,
0.75,
0.875
], ],
"_values": [ "_values": [
{ {

View File

@@ -7,11 +7,11 @@
"embeddedPlayerGroups": [] "embeddedPlayerGroups": []
}, },
"_native": "", "_native": "",
"sample": 60, "sample": 20,
"speed": 1, "speed": 0.5,
"wrapMode": 2, "wrapMode": 2,
"enableTrsBlending": false, "enableTrsBlending": false,
"_duration": 0.6, "_duration": 0.4,
"_hash": 500763545, "_hash": 500763545,
"_tracks": [ "_tracks": [
{ {
@@ -61,20 +61,15 @@
{ {
"__type__": "cc.ObjectCurve", "__type__": "cc.ObjectCurve",
"_times": [ "_times": [
0, 0.05,
0.08333333333333333, 0.1,
0.16666666666666666, 0.15,
0.2,
0.25, 0.25,
0.3333333333333333, 0.3,
0.4166666666666667, 0.35
0.5,
0.5833333333333334
], ],
"_values": [ "_values": [
{
"__uuid__": "78ffae32-3bfe-41cb-823f-3b0bca65732a@f9941",
"__expectedType__": "cc.SpriteFrame"
},
{ {
"__uuid__": "8742c745-dcb8-44d8-a276-62e561e81dab@f9941", "__uuid__": "8742c745-dcb8-44d8-a276-62e561e81dab@f9941",
"__expectedType__": "cc.SpriteFrame" "__expectedType__": "cc.SpriteFrame"

View File

@@ -982,46 +982,188 @@ export class PlayerController extends Component {
return; 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'); this.switchAnimation('attack');
// 监听玩家攻击动画结束事件 // 监听玩家攻击动画结束事件
playerAnimation.once(Animation.EventType.FINISHED, async () => { return new Promise<void>((resolve) => {
if (!this.player || !playerLabel.isValid || !monsterLabel.isValid) { playerAnimation.once(Animation.EventType.FINISHED, async () => {
this.isAttacking = false; if (!this.player || !playerLabel.isValid || !monsterLabel.isValid) {
if (this.attackAudio) { resolve();
const audioSource = this.attackAudio.getComponent(AudioSource); return;
if (audioSource) {
audioSource.stop();
}
} }
// 比较生命值,判断输赢
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; return;
} }
// 比较生命值,判断输赢 return new Promise<void>((resolve) => {
console.log('判定攻击结果玩家HP:', playerHp, '怪物HP:', monsterHp); // 添加超时机制,防止动画卡住
const timeout = setTimeout(() => {
console.log('怪物攻击动画超时,强制继续');
// 确保怪物切换回站立状态
this.switchMonsterToStand(otherCollider.node.name, monsterAnimation);
resolve();
}, 3000); // 3秒超时
if (playerHp >= monsterHp) { monsterAnimation.play(`${otherCollider.node.name}_attack`);
// 玩家获胜,直接执行后续流程,不需要播放怪物攻击动画 console.log('开始播放怪物攻击动画');
await this.handlePlayerWin(otherCollider, playerLabel, monsterHp);
} else {
// 玩家输了,需要播放怪物攻击动画
await this.handleMonsterAttack(otherCollider, playerLabel, monsterHp);
}
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) { private switchMonsterToStand(monsterName: string, monsterAnimation: Animation) {
audioSource.stop(); const standAnimName = `${monsterName}_stand`;
console.log('停止攻击音效'); const standAnimState = monsterAnimation.getState(standAnimName);
}
}
});
return true; if (standAnimState) {
monsterAnimation.play(standAnimName);
console.log(`怪物切换到站立动画: ${standAnimName}`);
} else {
console.warn(`怪物站立动画 ${standAnimName} 不存在`);
}
} }
/** /**