|
|
@@ -25,6 +25,7 @@ interface EnemyControllerType {
|
|
|
enum EnemyState {
|
|
|
DRIFTING, // 漂移中(从生成位置移动到线上)
|
|
|
MOVING, // 移动中
|
|
|
+ IDLE, // 待机中(碰到墙体后停止移动但可以攻击)
|
|
|
ATTACKING, // 攻击中
|
|
|
DEAD // 死亡
|
|
|
}
|
|
|
@@ -438,17 +439,17 @@ export class EnemyInstance extends Component {
|
|
|
// 检查是否碰到墙体(更严格的墙体识别)
|
|
|
const isWall = this.isWallNode(otherCollider.node);
|
|
|
if (isWall) {
|
|
|
- console.log(`[EnemyInstance] 敌人 ${this.getEnemyName()} 碰撞到墙体 ${nodeName},切换到攻击状态`);
|
|
|
+ console.log(`[EnemyInstance] 敌人 ${this.getEnemyName()} 碰撞到墙体 ${nodeName},切换到待机状态`);
|
|
|
|
|
|
- this.state = EnemyState.ATTACKING;
|
|
|
+ this.state = EnemyState.IDLE;
|
|
|
this.attackTimer = 0; // 立即开始攻击
|
|
|
this.collidedWall = otherCollider.node; // 记录碰撞的墙体
|
|
|
|
|
|
// 停止移动
|
|
|
this.stopRigidBodyMovement();
|
|
|
|
|
|
- // 切换攻击动画
|
|
|
- this.playAttackAnimation();
|
|
|
+ // 切换到待机动画
|
|
|
+ this.playIdleAnimation();
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -653,6 +654,8 @@ export class EnemyInstance extends Component {
|
|
|
this.updateMovement(deltaTime);
|
|
|
// 在移动状态检查墙体碰撞
|
|
|
this.checkWallCollisionByDistance();
|
|
|
+ } else if (this.state === EnemyState.IDLE) {
|
|
|
+ this.updateIdle(deltaTime);
|
|
|
} else if (this.state === EnemyState.ATTACKING) {
|
|
|
this.updateAttack(deltaTime);
|
|
|
}
|
|
|
@@ -858,6 +861,29 @@ export class EnemyInstance extends Component {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ // 待机状态更新(停止移动但可以攻击)
|
|
|
+ private updateIdle(deltaTime: number) {
|
|
|
+ // 在待机状态下停止移动
|
|
|
+ const enemySprite = this.node.getChildByName('EnemySprite');
|
|
|
+ if (enemySprite) {
|
|
|
+ const rigidBody = enemySprite.getComponent(RigidBody2D);
|
|
|
+ if (rigidBody) {
|
|
|
+ // 停止物理移动
|
|
|
+ rigidBody.linearVelocity = new Vec2(0, 0);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ this.attackTimer -= deltaTime;
|
|
|
+
|
|
|
+ if (this.attackTimer <= 0) {
|
|
|
+ // 执行攻击
|
|
|
+ this.performAttack();
|
|
|
+
|
|
|
+ // 重置攻击计时器
|
|
|
+ this.attackTimer = this.attackInterval;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
// 执行攻击
|
|
|
private performAttack() {
|
|
|
if (!this.controller) {
|
|
|
@@ -939,6 +965,23 @@ export class EnemyInstance extends Component {
|
|
|
}, 0.1);
|
|
|
}
|
|
|
|
|
|
+ // 播放待机动画
|
|
|
+ private playIdleAnimation() {
|
|
|
+ if (!this.skeleton) return;
|
|
|
+ const enemyComp = this.getComponent('EnemyComponent') as any;
|
|
|
+ const anims = enemyComp?.getAnimations ? enemyComp.getAnimations() : {};
|
|
|
+ const idleName = anims.idle ?? 'idle';
|
|
|
+
|
|
|
+ if (this.skeleton.findAnimation(idleName)) {
|
|
|
+ this.skeleton.setAnimation(0, idleName, true);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 动画切换后延迟更新血条位置,确保动画尺寸已生效
|
|
|
+ this.scheduleOnce(() => {
|
|
|
+ this.updateHPBarPosition();
|
|
|
+ }, 0.1);
|
|
|
+ }
|
|
|
+
|
|
|
// 播放攻击动画并在动画结束时造成伤害
|
|
|
private playAttackAnimationWithDamage() {
|
|
|
if (!this.skeleton) {
|
|
|
@@ -968,8 +1011,14 @@ export class EnemyInstance extends Component {
|
|
|
// 使用定时器在动画结束时造成伤害
|
|
|
this.scheduleOnce(() => {
|
|
|
this.dealDamageToWall();
|
|
|
- // 动画完成后切换回行走动画
|
|
|
- this.playWalkAnimation();
|
|
|
+ // 动画完成后根据当前状态切换动画
|
|
|
+ if (this.state === EnemyState.IDLE) {
|
|
|
+ // 如果是待机状态,切换回待机动画
|
|
|
+ this.playIdleAnimation();
|
|
|
+ } else {
|
|
|
+ // 其他状态切换回行走动画
|
|
|
+ this.playWalkAnimation();
|
|
|
+ }
|
|
|
}, animationDuration);
|
|
|
} else {
|
|
|
// 如果找不到攻击动画,直接造成伤害
|
|
|
@@ -1136,8 +1185,8 @@ export class EnemyInstance extends Component {
|
|
|
* 基于距离检查墙体碰撞
|
|
|
*/
|
|
|
private checkWallCollisionByDistance(): void {
|
|
|
- if (this.state === EnemyState.ATTACKING) {
|
|
|
- return; // 已经在攻击状态,不需要再检查
|
|
|
+ if (this.state === EnemyState.ATTACKING || this.state === EnemyState.IDLE) {
|
|
|
+ return; // 已经在攻击状态或待机状态,不需要再检查
|
|
|
}
|
|
|
|
|
|
const enemySprite = this.node.getChildByName('EnemySprite');
|
|
|
@@ -1154,17 +1203,17 @@ export class EnemyInstance extends Component {
|
|
|
const distance = Vec3.distance(currentPos, wallPos);
|
|
|
|
|
|
if (distance <= collisionDistance) {
|
|
|
- console.log(`[EnemyInstance] 敌人 ${this.getEnemyName()} 距离检测到墙体 ${wallNode.name},距离: ${distance.toFixed(2)},切换到攻击状态`);
|
|
|
+ console.log(`[EnemyInstance] 敌人 ${this.getEnemyName()} 距离检测到墙体 ${wallNode.name},距离: ${distance.toFixed(2)},切换到待机状态`);
|
|
|
|
|
|
- this.state = EnemyState.ATTACKING;
|
|
|
+ this.state = EnemyState.IDLE;
|
|
|
this.attackTimer = 0; // 立即开始攻击
|
|
|
this.collidedWall = wallNode; // 记录碰撞的墙体
|
|
|
|
|
|
// 停止移动
|
|
|
this.stopRigidBodyMovement();
|
|
|
|
|
|
- // 切换攻击动画
|
|
|
- this.playAttackAnimation();
|
|
|
+ // 切换到待机动画
|
|
|
+ this.playIdleAnimation();
|
|
|
|
|
|
return; // 找到一个墙体就停止检查
|
|
|
}
|