diff --git a/DungeonShooting_Godot/src/game/activity/role/enemy/AdvancedEnemy.cs b/DungeonShooting_Godot/src/game/activity/role/enemy/AdvancedEnemy.cs index d1313b9..ea5c57b 100644 --- a/DungeonShooting_Godot/src/game/activity/role/enemy/AdvancedEnemy.cs +++ b/DungeonShooting_Godot/src/game/activity/role/enemy/AdvancedEnemy.cs @@ -350,7 +350,7 @@ } /// - /// 调用视野检测, 如果被墙壁和其它物体遮挡, 则返回被挡住视野的物体对象, 视野无阻则返回 null + /// 调用视野检测, 如果被墙壁和其它物体遮挡, 则返回true /// public bool TestViewRayCast(Vector2 target) { diff --git a/DungeonShooting_Godot/src/game/activity/role/enemy/advancedState/AiAttackState.cs b/DungeonShooting_Godot/src/game/activity/role/enemy/advancedState/AiAttackState.cs index fb4e26f..f4f690d 100644 --- a/DungeonShooting_Godot/src/game/activity/role/enemy/advancedState/AiAttackState.cs +++ b/DungeonShooting_Godot/src/game/activity/role/enemy/advancedState/AiAttackState.cs @@ -16,6 +16,21 @@ /// 攻击状态 /// public AiAttackEnum AttackState; + + //是否移动结束 + private bool _isMoveOver; + + //移动停顿计时器 + private float _pauseTimer; + private bool _moveFlag; + + //下一个移动点 + private Vector2 _nextPosition; + + //上一帧位置 + private Vector2 _prevPos; + //卡在一个位置的时间 + private float _lockTimer; public AiAttackState() : base(AIAdvancedStateEnum.AiAttack) { @@ -42,6 +57,10 @@ AttackState = AiAttackEnum.None; Master.LockTargetTime = 0; PrevState = prev; + + _isMoveOver = true; + _pauseTimer = 0; + _moveFlag = false; } public override void Exit(AIAdvancedStateEnum next) @@ -53,18 +72,43 @@ public override void Process(float delta) { + Master.LookTarget = Player.Current; + var weapon = Master.WeaponPack.ActiveItem; - if (weapon == null || (weapon.GetAttackTimer() > 0 && weapon.GetContinuousCount() <= 0)) //攻击完成, 可以切换状态了 + if (weapon == null) { - //这里要做换弹判断, 还有上膛判断 - + //攻击结束 ChangeState(PrevState); } + else if (AttackState == AiAttackEnum.AttackInterval) //攻击完成 + { + if (weapon.GetAttackTimer() <= 0) //攻击冷却完成 + { + //这里要做换弹判断, 还有上膛判断 + if (weapon.CurrAmmo <= 0) //换弹判断 + { + if (!weapon.Reloading) + { + weapon.Reload(); + } + } + else if (weapon.GetBeLoadedStateState() != 2) //上膛 + { + if (weapon.GetBeLoadedStateState() == 0) + { + weapon.BeLoaded(); + } + } + else + { + //攻击结束 + ChangeState(PrevState); + } + } + MoveHandler(delta); + } else //攻击状态 { - //这里还要做是否在视野内的判断 - - Master.LookTarget = Player.Current; //触发扳机 AttackState = Master.WeaponPack.ActiveItem.AiTriggerAttackState(); @@ -99,7 +143,7 @@ } else //正常移动 { - Master.DoMove(); + MoveHandler(delta); } } else @@ -134,9 +178,87 @@ } else //正常移动 { - Master.DoMove(); + MoveHandler(delta); } } } } + + private void MoveHandler(float delta) + { + + if (_pauseTimer >= 0) + { + Master.AnimatedSprite.Play(AnimatorNames.Idle); + _pauseTimer -= delta; + } + else if (_isMoveOver) //移动已经完成 + { + RunOver(Player.Current.Position); + _isMoveOver = false; + } + else + { + var masterPosition = Master.Position; + if (_lockTimer >= 1) //卡在一个点超过一秒 + { + RunOver(Player.Current.Position); + _isMoveOver = false; + _lockTimer = 0; + } + else if (Master.NavigationAgent2D.IsNavigationFinished()) //到达终点 + { + _pauseTimer = Utils.Random.RandomRangeFloat(0f, 0.5f); + _isMoveOver = true; + _moveFlag = false; + //站立 + Master.DoIdle(); + } + else if (!_moveFlag) + { + _moveFlag = true; + //移动 + Master.DoMove(); + } + else + { + var lastSlideCollision = Master.GetLastSlideCollision(); + if (lastSlideCollision != null && lastSlideCollision.GetCollider() is AdvancedRole) //碰到其他角色 + { + _pauseTimer = Utils.Random.RandomRangeFloat(0f, 0.3f); + _isMoveOver = true; + _moveFlag = false; + //站立 + Master.DoIdle(); + } + else + { + //移动 + Master.DoMove(); + } + + if (_prevPos.DistanceSquaredTo(masterPosition) <= 1 * delta) + { + _lockTimer += delta; + } + else + { + _lockTimer = 0; + _prevPos = masterPosition; + } + } + } + } + + private void RunOver(Vector2 targetPos) + { + var weapon = Master.WeaponPack.ActiveItem; + var distance = (int)(weapon == null ? 150 : (Utils.GetConfigRangeStart(weapon.Attribute.Bullet.DistanceRange) * 0.7f)); + _nextPosition = new Vector2( + targetPos.X + Utils.Random.RandomRangeInt(-distance, distance), + targetPos.Y + Utils.Random.RandomRangeInt(-distance, distance) + ); + Master.NavigationAgent2D.TargetPosition = _nextPosition; + } + } \ No newline at end of file diff --git a/DungeonShooting_Godot/src/game/activity/weapon/Weapon.cs b/DungeonShooting_Godot/src/game/activity/weapon/Weapon.cs index 8d9fc25..9a2fd78 100644 --- a/DungeonShooting_Godot/src/game/activity/weapon/Weapon.cs +++ b/DungeonShooting_Godot/src/game/activity/weapon/Weapon.cs @@ -604,7 +604,7 @@ //自动上膛 if (_beLoadedState == -1) { - BeLoadedHandler(); + BeLoaded(); } } } @@ -733,7 +733,7 @@ else if (_attackTimer <= 0) { //触发上膛操作 - BeLoadedHandler(); + BeLoaded(); } } } @@ -1217,7 +1217,7 @@ /// public void Reload() { - if (CurrAmmo < Attribute.AmmoCapacity && ResidueAmmo > 0 && !Reloading && _beLoadedState != 1) + if (!Reloading && CurrAmmo < Attribute.AmmoCapacity && ResidueAmmo > 0 && _beLoadedState != 1) { Reloading = true; _playReloadFinishSoundFlag = false; @@ -1271,6 +1271,59 @@ _reloadTimer = 0; _reloadUseTime = 0; } + + /// + /// 触发上膛 + /// + public void BeLoaded() + { + if (_beLoadedState > 0) + { + return; + } + //上膛抛弹 + if (!Attribute.ReloadThrowShell && !Attribute.ContinuousShoot && Attribute.BeLoadedTime > 0) + { + ThrowShellHandler(0.6f); + } + + //开始上膛 + OnBeginBeLoaded(); + + //上膛时间为0, 直接结束上膛 + if (Attribute.BeLoadedTime <= 0) + { + //直接上膛完成 + _beLoadedState = 2; + OnBeLoadedFinish(); + return; + } + + //上膛中 + _beLoadedState = 1; + _beLoadedStateTimer = Attribute.BeLoadedTime; + + //播放上膛动画 + if (IsAutoPlaySpriteFrames) + { + if (Attribute.BeLoadedSoundDelayTime <= 0) + { + PlaySpriteAnimation(AnimatorNames.BeLoaded); + PlayAnimationPlayer(AnimatorNames.BeLoaded); + } + else + { + this.CallDelay(Attribute.BeLoadedSoundDelayTime, () => + { + PlaySpriteAnimation(AnimatorNames.BeLoaded); + PlayAnimationPlayer(AnimatorNames.BeLoaded); + }); + } + } + + //播放上膛音效 + PlayBeLoadedSound(); + } //播放换弹开始音效 private void PlayBeginReloadSound() @@ -1346,7 +1399,7 @@ if (_attackTimer <= 0) { //执行自动上膛 - BeLoadedHandler(); + BeLoaded(); } else if (CurrAmmo > 0) { @@ -1421,53 +1474,6 @@ OnAloneReloadStateFinish(); } - //上膛处理 - private void BeLoadedHandler() - { - //上膛抛弹 - if (!Attribute.ReloadThrowShell && !Attribute.ContinuousShoot && Attribute.BeLoadedTime > 0) - { - ThrowShellHandler(0.6f); - } - - //开始上膛 - OnBeginBeLoaded(); - - //上膛时间为0, 直接结束上膛 - if (Attribute.BeLoadedTime <= 0) - { - //直接上膛完成 - _beLoadedState = 2; - OnBeLoadedFinish(); - return; - } - - //上膛中 - _beLoadedState = 1; - _beLoadedStateTimer = Attribute.BeLoadedTime; - - //播放上膛动画 - if (IsAutoPlaySpriteFrames) - { - if (Attribute.BeLoadedSoundDelayTime <= 0) - { - PlaySpriteAnimation(AnimatorNames.BeLoaded); - PlayAnimationPlayer(AnimatorNames.BeLoaded); - } - else - { - this.CallDelay(Attribute.BeLoadedSoundDelayTime, () => - { - PlaySpriteAnimation(AnimatorNames.BeLoaded); - PlayAnimationPlayer(AnimatorNames.BeLoaded); - }); - } - } - - //播放上膛音效 - PlayBeLoadedSound(); - } - //抛弹逻辑 private void ThrowShellHandler(float speedScale) { @@ -1945,7 +1951,7 @@ flag = AiAttackEnum.AttackInterval; if (_attackTimer <= 0) { - Master.Attack(); + BeLoaded(); } } else if (_beLoadedState == 1) //上膛中