feat: 优化打斗逻辑
This commit is contained in:
@@ -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,
|
||||||
|
|||||||
@@ -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": [
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -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"
|
||||||
|
|||||||
@@ -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} 不存在`);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user