diff --git a/DungeonShooting_Godot/excel/excelFile/AiAttackAttr.xlsx b/DungeonShooting_Godot/excel/excelFile/AiAttackAttr.xlsx index 7491120..2aefd57 100644 --- a/DungeonShooting_Godot/excel/excelFile/AiAttackAttr.xlsx +++ b/DungeonShooting_Godot/excel/excelFile/AiAttackAttr.xlsx Binary files differ diff --git a/DungeonShooting_Godot/resource/map/tileMaps/TestGroup1/inlet/Start1/Preinstall.json b/DungeonShooting_Godot/resource/map/tileMaps/TestGroup1/inlet/Start1/Preinstall.json index 09e0c14..cb5ad6b 100644 --- a/DungeonShooting_Godot/resource/map/tileMaps/TestGroup1/inlet/Start1/Preinstall.json +++ b/DungeonShooting_Godot/resource/map/tileMaps/TestGroup1/inlet/Start1/Preinstall.json @@ -1 +1 @@ -[{"Name":"test1","Weight":100,"Remark":"","WaveList":[[{"Position":{"X":19,"Y":2},"Size":{"X":0,"Y":0},"SpecialMarkType":1,"DelayTime":0,"MarkList":[]},{"Position":{"X":24,"Y":-14},"Size":{"X":0,"Y":0},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"weapon0001","Weight":100,"Attr":{"CurrAmmon":"30","ResidueAmmo":"210"},"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":6,"Y":34},"Size":{"X":16,"Y":16},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"weapon0002","Weight":100,"Attr":{"CurrAmmon":"7","ResidueAmmo":"70"},"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":-42,"Y":9},"Size":{"X":16,"Y":16},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"weapon0004","Weight":100,"Attr":{"CurrAmmon":"180","ResidueAmmo":"90"},"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":-63,"Y":-18},"Size":{"X":16,"Y":16},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"weapon0005","Weight":100,"Attr":{"CurrAmmon":"10","ResidueAmmo":"40"},"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":-31,"Y":-16},"Size":{"X":16,"Y":16},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"weapon0003","Weight":100,"Attr":{"CurrAmmon":"12","ResidueAmmo":"90"},"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":-47,"Y":32},"Size":{"X":16,"Y":16},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"weapon0006","Weight":100,"Attr":{"CurrAmmon":"20","ResidueAmmo":"300"},"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":2,"Y":-25},"Size":{"X":16,"Y":16},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"weapon0007","Weight":100,"Attr":{"CurrAmmon":"60","ResidueAmmo":"300"},"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":-80,"Y":14},"Size":{"X":16,"Y":16},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"weapon0008","Weight":100,"Attr":{"CurrAmmon":"10","ResidueAmmo":"120"},"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":-75,"Y":47},"Size":{"X":16,"Y":16},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"weapon0009","Weight":100,"Attr":{"CurrAmmon":"1","ResidueAmmo":"25"},"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":46,"Y":1},"Size":{"X":16,"Y":16},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"prop0011","Weight":100,"Attr":null,"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":36,"Y":49},"Size":{"X":16,"Y":16},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"prop0012","Weight":100,"Attr":null,"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":-90,"Y":-23},"Size":{"X":3,"Y":6},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"prop0013","Weight":100,"Attr":null,"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":-91,"Y":-6},"Size":{"X":0,"Y":0},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"prop0014","Weight":100,"Attr":null,"Altitude":8,"VerticalSpeed":0}]}],[{"Position":{"X":57,"Y":56},"Size":{"X":16,"Y":16},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"prop0003","Weight":100,"Attr":null,"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":67,"Y":28},"Size":{"X":16,"Y":16},"SpecialMarkType":0,"DelayTime":0.5,"MarkList":[{"Id":"prop5000","Weight":100,"Attr":null,"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":60,"Y":-19},"Size":{"X":16,"Y":16},"SpecialMarkType":0,"DelayTime":1,"MarkList":[{"Id":"prop5001","Weight":100,"Attr":null,"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":34,"Y":23},"Size":{"X":16,"Y":16},"SpecialMarkType":0,"DelayTime":1.5,"MarkList":[{"Id":"prop0002","Weight":100,"Attr":null,"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":-11,"Y":8},"Size":{"X":16,"Y":16},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"prop0010","Weight":100,"Attr":null,"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":-20,"Y":33},"Size":{"X":16,"Y":16},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"prop0010","Weight":100,"Attr":null,"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":8,"Y":12},"Size":{"X":16,"Y":16},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"enemy0002","Weight":100,"Attr":{"Face":"0","Weapon":null},"Altitude":0,"VerticalSpeed":0}]}]]}] \ No newline at end of file +[{"Name":"test1","Weight":100,"Remark":"","WaveList":[[{"Position":{"X":19,"Y":2},"Size":{"X":0,"Y":0},"SpecialMarkType":1,"DelayTime":0,"MarkList":[]},{"Position":{"X":24,"Y":-14},"Size":{"X":0,"Y":0},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"weapon0001","Weight":100,"Attr":{"CurrAmmon":"30","ResidueAmmo":"210"},"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":6,"Y":34},"Size":{"X":16,"Y":16},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"weapon0002","Weight":100,"Attr":{"CurrAmmon":"7","ResidueAmmo":"70"},"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":-42,"Y":9},"Size":{"X":16,"Y":16},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"weapon0004","Weight":100,"Attr":{"CurrAmmon":"180","ResidueAmmo":"90"},"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":-63,"Y":-18},"Size":{"X":16,"Y":16},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"weapon0005","Weight":100,"Attr":{"CurrAmmon":"10","ResidueAmmo":"40"},"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":-31,"Y":-16},"Size":{"X":16,"Y":16},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"weapon0003","Weight":100,"Attr":{"CurrAmmon":"12","ResidueAmmo":"90"},"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":-47,"Y":32},"Size":{"X":16,"Y":16},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"weapon0006","Weight":100,"Attr":{"CurrAmmon":"20","ResidueAmmo":"300"},"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":2,"Y":-25},"Size":{"X":16,"Y":16},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"weapon0007","Weight":100,"Attr":{"CurrAmmon":"60","ResidueAmmo":"300"},"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":-80,"Y":14},"Size":{"X":16,"Y":16},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"weapon0008","Weight":100,"Attr":{"CurrAmmon":"10","ResidueAmmo":"120"},"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":-75,"Y":47},"Size":{"X":16,"Y":16},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"weapon0009","Weight":100,"Attr":{"CurrAmmon":"1","ResidueAmmo":"25"},"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":46,"Y":1},"Size":{"X":16,"Y":16},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"prop0011","Weight":100,"Attr":null,"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":36,"Y":49},"Size":{"X":16,"Y":16},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"prop0012","Weight":100,"Attr":null,"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":-90,"Y":-23},"Size":{"X":3,"Y":6},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"prop0013","Weight":100,"Attr":null,"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":-91,"Y":-6},"Size":{"X":0,"Y":0},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"prop0014","Weight":100,"Attr":null,"Altitude":8,"VerticalSpeed":0}]}],[{"Position":{"X":57,"Y":56},"Size":{"X":16,"Y":16},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"prop0003","Weight":100,"Attr":null,"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":67,"Y":28},"Size":{"X":16,"Y":16},"SpecialMarkType":0,"DelayTime":0.5,"MarkList":[{"Id":"prop5000","Weight":100,"Attr":null,"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":60,"Y":-19},"Size":{"X":16,"Y":16},"SpecialMarkType":0,"DelayTime":1,"MarkList":[{"Id":"prop5001","Weight":100,"Attr":null,"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":34,"Y":23},"Size":{"X":16,"Y":16},"SpecialMarkType":0,"DelayTime":1.5,"MarkList":[{"Id":"prop0002","Weight":100,"Attr":null,"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":-11,"Y":8},"Size":{"X":16,"Y":16},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"prop0010","Weight":100,"Attr":null,"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":-20,"Y":33},"Size":{"X":16,"Y":16},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"prop0010","Weight":100,"Attr":null,"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":-90,"Y":34},"Size":{"X":16,"Y":16},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"enemy0001","Weight":100,"Attr":{"Face":"0","Weapon":"weapon0005","CurrAmmon":"10","ResidueAmmo":"10"},"Altitude":0,"VerticalSpeed":0}]}]]}] \ No newline at end of file diff --git a/DungeonShooting_Godot/src/game/GameApplication.cs b/DungeonShooting_Godot/src/game/GameApplication.cs index 4496067..0786aea 100644 --- a/DungeonShooting_Godot/src/game/GameApplication.cs +++ b/DungeonShooting_Godot/src/game/GameApplication.cs @@ -106,7 +106,7 @@ //固定帧率 Engine.MaxFps = TargetFps; //调试绘制开关 - ActivityObject.IsDebug = true; + ActivityObject.IsDebug = false; //Engine.TimeScale = 0.2f; //调整窗口分辨率 OnWindowSizeChanged(); diff --git a/DungeonShooting_Godot/src/game/activity/role/enemy/AdvancedEnemy.cs b/DungeonShooting_Godot/src/game/activity/role/enemy/AdvancedEnemy.cs index 22ae399..d1313b9 100644 --- a/DungeonShooting_Godot/src/game/activity/role/enemy/AdvancedEnemy.cs +++ b/DungeonShooting_Godot/src/game/activity/role/enemy/AdvancedEnemy.cs @@ -63,19 +63,16 @@ /// [Export, ExportFillNode] public Marker2D NavigationPoint { get; private set; } - - /// - /// Ai攻击状态, 调用 Attack() 函数后会刷新 - /// - public AiAttackEnum AttackState { get; private set; } /// /// 当前敌人所看向的对象, 也就是枪口指向的对象 /// public ActivityObject LookTarget { get; set; } - //锁定目标时间 - private float _lockTargetTime = 0; + /// + /// 锁定目标已经走过的时间 + /// + public float LockTargetTime { get; set; } = 0; public override void OnInit() { @@ -102,6 +99,7 @@ StateController.Register(new AiLeaveForState()); StateController.Register(new AiSurroundState()); StateController.Register(new AiFindAmmoState()); + StateController.Register(new AiAttackState()); //默认状态 StateController.ChangeStateInstant(AIAdvancedStateEnum.AiNormal); @@ -176,83 +174,6 @@ //枪口跟随目标 MountPoint.SetLookAt(pos); } - - //目标在视野内的时间 - var currState = StateController.CurrState; - if (currState == AIAdvancedStateEnum.AiSurround || currState == AIAdvancedStateEnum.AiFollowUp) - { - var weapon = WeaponPack.ActiveItem; - if (weapon != null) - { - if (weapon.GetBeLoadedStateState() >= 2 && !weapon.IsAttackIntervalTime()) //必须在可以开火时记录时间 - { - _lockTargetTime += delta; - } - else - { - _lockTargetTime = 0; - } - - if (AttackState == AiAttackEnum.LockingTime) //锁定玩家状态 - { - var aiLockRemainderTime = GetLockRemainderTime(); - MountLookTarget = aiLockRemainderTime >= weapon.Attribute.AiAttackAttr.LockAngleTime; - //更新瞄准辅助线 - if (weapon.Attribute.AiAttackAttr.ShowSubline) - { - if (SubLine == null) - { - InitSubLine(); - } - else - { - SubLine.Enable = true; - } - - //播放警告删掉动画 - if (!SubLine.IsPlayWarnAnimation && aiLockRemainderTime <= 0.5f) - { - SubLine.PlayWarnAnimation(0.5f); - } - } - } - else - { - //关闭辅助线 - if (SubLine != null) - { - SubLine.Enable = false; - } - - if (AttackState == AiAttackEnum.Attack || AttackState == AiAttackEnum.AttackInterval) - { - if (weapon.Attribute.AiAttackAttr.AttackLockAngle) //开火时锁定枪口角度 - { - //连发状态锁定角度 - MountLookTarget = !(weapon.GetContinuousCount() > 0 || weapon.GetAttackTimer() > 0); - } - else - { - MountLookTarget = true; - } - } - else - { - MountLookTarget = true; - } - } - } - else - { - MountLookTarget = true; - _lockTargetTime = 0; - } - } - else - { - MountLookTarget = true; - _lockTargetTime = 0; - } //拾起武器操作 EnemyPickUpWeapon(); @@ -378,22 +299,6 @@ return false; } - - /// - /// 敌人发动攻击 - /// - public virtual void EnemyAttack() - { - var weapon = WeaponPack.ActiveItem; - if (weapon != null) - { - AttackState = weapon.AiTriggerAttackState(); - } - else //没有武器 - { - AttackState = AiAttackEnum.NoWeapon; - } - } /// /// 获取武器攻击范围 (最大距离值与最小距离的中间值) @@ -518,14 +423,6 @@ // } } } - - /// - /// 获取锁定目标的时间 - /// - public float GetLockTime() - { - return _lockTargetTime; - } /// /// 获取锁定目标的剩余时间 @@ -537,7 +434,7 @@ { return 0; } - return weapon.Attribute.AiAttackAttr.LockingTime - _lockTargetTime; + return weapon.Attribute.AiAttackAttr.LockingTime - LockTargetTime; } /// @@ -545,7 +442,7 @@ /// public void SetLockTargetTime(float time) { - _lockTargetTime = time; + LockTargetTime = time; } public override void LookTargetPosition(Vector2 pos) @@ -553,4 +450,24 @@ LookTarget = null; base.LookTargetPosition(pos); } + + /// + /// 执行移动操作 + /// + public void DoMove() + { + AnimatedSprite.Play(AnimatorNames.Run); + //计算移动 + var nextPos = NavigationAgent2D.GetNextPathPosition(); + BasisVelocity = (nextPos - Position - NavigationPoint.Position).Normalized() * RoleState.MoveSpeed; + } + + /// + /// 执行站立操作 + /// + public void DoIdle() + { + AnimatedSprite.Play(AnimatorNames.Idle); + BasisVelocity = Vector2.Zero; + } } diff --git a/DungeonShooting_Godot/src/game/activity/role/enemy/AiAttackEnum.cs b/DungeonShooting_Godot/src/game/activity/role/enemy/AiAttackEnum.cs deleted file mode 100644 index f8e8b89..0000000 --- a/DungeonShooting_Godot/src/game/activity/role/enemy/AiAttackEnum.cs +++ /dev/null @@ -1,43 +0,0 @@ - -/// -/// 调用 Enemy.EnemyAttack() 函数返回的结果 -/// -public enum AiAttackEnum -{ - /// - /// 未触发 EnemyAttack() - /// - None, - /// - /// 触发切换武器 - /// - ExchangeWeapon, - /// - /// 没有弹药了 - /// - NoAmmo, - /// - /// 换弹中 - /// - Reloading, - /// - /// 触发换弹 - /// - TriggerReload, - /// - /// 没有武器 - /// - NoWeapon, - /// - /// 正在锁定目标中 - /// - LockingTime, - /// - /// 攻击间隙时间 - /// - AttackInterval, - /// - /// 成功触发攻击 - /// - Attack, -} \ No newline at end of file diff --git a/DungeonShooting_Godot/src/game/activity/role/enemy/advancedState/AIAdvancedStateEnum.cs b/DungeonShooting_Godot/src/game/activity/role/enemy/advancedState/AIAdvancedStateEnum.cs index 117b3c1..a04b743 100644 --- a/DungeonShooting_Godot/src/game/activity/role/enemy/advancedState/AIAdvancedStateEnum.cs +++ b/DungeonShooting_Godot/src/game/activity/role/enemy/advancedState/AIAdvancedStateEnum.cs @@ -33,4 +33,8 @@ /// Ai 寻找弹药 /// AiFindAmmo, + /// + /// Ai攻击 + /// + AiAttack, } \ No newline at end of file diff --git a/DungeonShooting_Godot/src/game/activity/role/enemy/advancedState/AiAttackState.cs b/DungeonShooting_Godot/src/game/activity/role/enemy/advancedState/AiAttackState.cs new file mode 100644 index 0000000..fb4e26f --- /dev/null +++ b/DungeonShooting_Godot/src/game/activity/role/enemy/advancedState/AiAttackState.cs @@ -0,0 +1,142 @@ +using Godot; + +namespace AdvancedState; + +/// +/// ai 攻击状态 +/// +public class AiAttackState : StateBase +{ + /// + /// 上一个状态 + /// + public AIAdvancedStateEnum PrevState; + + /// + /// 攻击状态 + /// + public AiAttackEnum AttackState; + + public AiAttackState() : base(AIAdvancedStateEnum.AiAttack) + { + } + + public override void Enter(AIAdvancedStateEnum prev, params object[] args) + { + var weapon = Master.WeaponPack.ActiveItem; + if (weapon == null) + { + Debug.LogError("进入 AIAdvancedStateEnum.AiAttack 状态时角色没有武器!"); + ChangeState(prev); + return; + } + + if (!weapon.TriggerIsReady()) + { + Debug.LogError("进入 AIAdvancedStateEnum.AiAttack 状态时角色武器还玩法触动扳机!"); + ChangeState(prev); + return; + } + + Master.BasisVelocity = Vector2.Zero; + AttackState = AiAttackEnum.None; + Master.LockTargetTime = 0; + PrevState = prev; + } + + public override void Exit(AIAdvancedStateEnum next) + { + Master.MountLookTarget = true; + Master.LockTargetTime = 0; + Master.LookTarget = null; + } + + public override void Process(float delta) + { + var weapon = Master.WeaponPack.ActiveItem; + if (weapon == null || (weapon.GetAttackTimer() > 0 && weapon.GetContinuousCount() <= 0)) //攻击完成, 可以切换状态了 + { + //这里要做换弹判断, 还有上膛判断 + + ChangeState(PrevState); + } + else //攻击状态 + { + //这里还要做是否在视野内的判断 + + Master.LookTarget = Player.Current; + //触发扳机 + AttackState = Master.WeaponPack.ActiveItem.AiTriggerAttackState(); + + if (AttackState == AiAttackEnum.LockingTime) //锁定玩家状态 + { + Master.LockTargetTime += delta; + + var aiLockRemainderTime = Master.GetLockRemainderTime(); + Master.MountLookTarget = aiLockRemainderTime >= weapon.Attribute.AiAttackAttr.LockAngleTime; + //更新瞄准辅助线 + if (weapon.Attribute.AiAttackAttr.ShowSubline) + { + if (Master.SubLine == null) + { + Master.InitSubLine(); + } + else + { + Master.SubLine.Enable = true; + } + + //播放警告删掉动画 + if (!Master.SubLine.IsPlayWarnAnimation && aiLockRemainderTime <= 0.5f) + { + Master.SubLine.PlayWarnAnimation(0.5f); + } + } + + if (weapon.Attribute.AiAttackAttr.LockingStand) //锁定目标时站立不动 + { + Master.DoIdle(); + } + else //正常移动 + { + Master.DoMove(); + } + } + else + { + Master.LockTargetTime = 0; + //关闭辅助线 + if (Master.SubLine != null) + { + Master.SubLine.Enable = false; + } + + if (AttackState == AiAttackEnum.Attack || AttackState == AiAttackEnum.AttackInterval) + { + if (weapon.Attribute.AiAttackAttr.AttackLockAngle) //开火时锁定枪口角度 + { + //连发状态锁定角度 + Master.MountLookTarget = !(weapon.GetContinuousCount() > 0 || weapon.GetAttackTimer() > 0); + } + else + { + Master.MountLookTarget = true; + } + } + else + { + Master.MountLookTarget = true; + } + + if (AttackState == AiAttackEnum.Attack && weapon.Attribute.AiAttackAttr.FiringStand) //开火时站立不动 + { + Master.DoIdle(); + } + else //正常移动 + { + Master.DoMove(); + } + } + } + } +} \ No newline at end of file diff --git a/DungeonShooting_Godot/src/game/activity/role/enemy/advancedState/AiFindAmmoState.cs b/DungeonShooting_Godot/src/game/activity/role/enemy/advancedState/AiFindAmmoState.cs index c650113..0019e00 100644 --- a/DungeonShooting_Godot/src/game/activity/role/enemy/advancedState/AiFindAmmoState.cs +++ b/DungeonShooting_Godot/src/game/activity/role/enemy/advancedState/AiFindAmmoState.cs @@ -40,6 +40,11 @@ _target.SetSign(SignNames.AiFindWeaponSign, Master); } + public override void Exit(AIAdvancedStateEnum next) + { + Master.LookTarget = null; + } + public override void Process(float delta) { if (!Master.IsAllWeaponTotalAmmoEmpty()) //已经有弹药了 @@ -60,10 +65,9 @@ { _navigationUpdateTimer -= delta; } - - var playerPos = Player.Current.GetCenterPosition(); + //枪口指向玩家 - Master.LookTargetPosition(playerPos); + Master.LookTarget = Player.Current; if (_target.IsDestroyed || _target.IsTotalAmmoEmpty()) //已经被销毁, 或者弹药已经被其他角色捡走 { @@ -92,7 +96,7 @@ else { //检测目标没有超出跟随视野距离 - _isInTailAfterRange = Master.IsInTailAfterViewRange(playerPos); + _isInTailAfterRange = Master.IsInTailAfterViewRange(Player.Current.GetCenterPosition()); if (_isInTailAfterRange) { _tailAfterTimer = 0; @@ -105,16 +109,13 @@ //向武器移动 if (!Master.NavigationAgent2D.IsNavigationFinished()) { - //计算移动 - var nextPos = Master.NavigationAgent2D.GetNextPathPosition(); - Master.AnimatedSprite.Play(AnimatorNames.Run); - Master.BasisVelocity = - (nextPos - Master.GlobalPosition - Master.NavigationPoint.Position).Normalized() * - Master.RoleState.MoveSpeed; + //移动 + Master.DoMove(); } else { - Master.BasisVelocity = Vector2.Zero; + //站立 + Master.DoIdle(); } } } diff --git a/DungeonShooting_Godot/src/game/activity/role/enemy/advancedState/AiFollowUpState.cs b/DungeonShooting_Godot/src/game/activity/role/enemy/advancedState/AiFollowUpState.cs index ae6ee0d..30b04ff 100644 --- a/DungeonShooting_Godot/src/game/activity/role/enemy/advancedState/AiFollowUpState.cs +++ b/DungeonShooting_Godot/src/game/activity/role/enemy/advancedState/AiFollowUpState.cs @@ -22,6 +22,11 @@ Master.TargetInView = true; } + public override void Exit(AIAdvancedStateEnum next) + { + Master.LookTarget = null; + } + public override void Process(float delta) { //先检查弹药是否打光 @@ -55,41 +60,28 @@ _navigationUpdateTimer -= delta; } - var masterPosition = Master.GlobalPosition; - //是否在攻击范围内 var inAttackRange = false; var weapon = Master.WeaponPack.ActiveItem; - var distanceSquared = masterPosition.DistanceSquaredTo(playerPos); + var distanceSquared = Master.Position.DistanceSquaredTo(playerPos); if (weapon != null) { inAttackRange = distanceSquared <= Mathf.Pow(Master.GetWeaponRange(0.7f), 2); } //枪口指向玩家 - Master.LookTargetPosition(playerPos); + Master.LookTarget = Player.Current; if (!Master.NavigationAgent2D.IsNavigationFinished()) { - if (weapon == null || !weapon.Attribute.AiAttackAttr.FiringStand || - (Master.AttackState != AiAttackEnum.LockingTime && Master.AttackState != AiAttackEnum.Attack)) - { - //计算移动 - var nextPos = Master.NavigationAgent2D.GetNextPathPosition(); - Master.AnimatedSprite.Play(AnimatorNames.Run); - Master.BasisVelocity = (nextPos - masterPosition - Master.NavigationPoint.Position).Normalized() * - Master.RoleState.MoveSpeed; - } - else - { - Master.AnimatedSprite.Play(AnimatorNames.Idle); - Master.BasisVelocity = Vector2.Zero; - } + //移动 + Master.DoMove(); } else { - Master.BasisVelocity = Vector2.Zero; + //站立 + Master.DoIdle(); } //检测玩家是否在视野内 @@ -104,19 +96,21 @@ Master.TargetInView = false; } - //在视野中, 或者锁敌状态下, 或者攻击状态下, 继续保持原本逻辑 - if (Master.TargetInView || Master.AttackState == AiAttackEnum.LockingTime || Master.AttackState == AiAttackEnum.Attack) + //在视野中 + if (Master.TargetInView) { if (inAttackRange) //在攻击范围内 { - //发起攻击 - Master.EnemyAttack(); - //距离够近, 可以切换到环绕模式 if (distanceSquared <= Mathf.Pow(Utils.GetConfigRangeStart(weapon.Attribute.Bullet.DistanceRange), 2) * 0.7f) { ChangeState(AIAdvancedStateEnum.AiSurround); } + else if (weapon.TriggerIsReady()) //可以攻击 + { + //攻击状态 + ChangeState(AIAdvancedStateEnum.AiAttack); + } } } else //不在视野中 diff --git a/DungeonShooting_Godot/src/game/activity/role/enemy/advancedState/AiLeaveForState.cs b/DungeonShooting_Godot/src/game/activity/role/enemy/advancedState/AiLeaveForState.cs index 4c56fb2..9bdea9c 100644 --- a/DungeonShooting_Godot/src/game/activity/role/enemy/advancedState/AiLeaveForState.cs +++ b/DungeonShooting_Godot/src/game/activity/role/enemy/advancedState/AiLeaveForState.cs @@ -58,16 +58,14 @@ if (!Master.NavigationAgent2D.IsNavigationFinished()) { - //计算移动 - var nextPos = Master.NavigationAgent2D.GetNextPathPosition(); Master.LookTargetPosition(Master.World.Enemy_FindTargetPosition); - Master.AnimatedSprite.Play(AnimatorNames.Run); - Master.BasisVelocity = (nextPos - Master.GlobalPosition - Master.NavigationPoint.Position).Normalized() * - Master.RoleState.MoveSpeed; + //移动 + Master.DoMove(); } else { - Master.BasisVelocity = Vector2.Zero; + //站立 + Master.DoIdle(); } var playerPos = Player.Current.GetCenterPosition(); diff --git a/DungeonShooting_Godot/src/game/activity/role/enemy/advancedState/AiNormalState.cs b/DungeonShooting_Godot/src/game/activity/role/enemy/advancedState/AiNormalState.cs index 13362bc..bc57b33 100644 --- a/DungeonShooting_Godot/src/game/activity/role/enemy/advancedState/AiNormalState.cs +++ b/DungeonShooting_Godot/src/game/activity/role/enemy/advancedState/AiNormalState.cs @@ -95,37 +95,33 @@ _pauseTimer = Utils.Random.RandomRangeFloat(0.3f, 2f); _isMoveOver = true; _moveFlag = false; - Master.BasisVelocity = Vector2.Zero; + //站立 + Master.DoIdle(); } else if (!_moveFlag) { _moveFlag = true; - var pos = Master.GlobalPosition; - //计算移动 - var nextPos = Master.NavigationAgent2D.GetNextPathPosition(); - Master.AnimatedSprite.Play(AnimatorNames.Run); - Master.BasisVelocity = (nextPos - pos - Master.NavigationPoint.Position).Normalized() * - Master.RoleState.MoveSpeed; + var pos = Master.Position; + //移动 + Master.DoMove(); _prevPos = pos; } else { - var pos = Master.GlobalPosition; + var pos = Master.Position; var lastSlideCollision = Master.GetLastSlideCollision(); if (lastSlideCollision != null && lastSlideCollision.GetCollider() is AdvancedRole) //碰到其他角色 { _pauseTimer = Utils.Random.RandomRangeFloat(0.1f, 0.5f); _isMoveOver = true; _moveFlag = false; - Master.BasisVelocity = Vector2.Zero; + //站立 + Master.DoIdle(); } else { - //计算移动 - var nextPos = Master.NavigationAgent2D.GetNextPathPosition(); - Master.AnimatedSprite.Play(AnimatorNames.Run); - Master.BasisVelocity = (nextPos - pos - Master.NavigationPoint.Position).Normalized() * - Master.RoleState.MoveSpeed; + //移动 + Master.DoMove(); } if (_prevPos.DistanceSquaredTo(pos) <= 0.01f) diff --git a/DungeonShooting_Godot/src/game/activity/role/enemy/advancedState/AiSurroundState.cs b/DungeonShooting_Godot/src/game/activity/role/enemy/advancedState/AiSurroundState.cs index fc5578a..2b063e8 100644 --- a/DungeonShooting_Godot/src/game/activity/role/enemy/advancedState/AiSurroundState.cs +++ b/DungeonShooting_Godot/src/game/activity/role/enemy/advancedState/AiSurroundState.cs @@ -35,6 +35,11 @@ _moveFlag = false; } + public override void Exit(AIAdvancedStateEnum next) + { + Master.LookTarget = null; + } + public override void Process(float delta) { //先检查弹药是否打光 @@ -53,7 +58,7 @@ var weapon = Master.WeaponPack.ActiveItem; //枪口指向玩家 - Master.LookTargetPosition(playerPos); + Master.LookTarget = Player.Current; //检测玩家是否在视野内 if (Master.IsInTailAfterViewRange(playerPos)) @@ -67,11 +72,8 @@ Master.TargetInView = false; } - //在视野中, 或者锁敌状态下, 或者攻击状态下, 继续保持原本逻辑 - if (Master.TargetInView || - (weapon != null && weapon.Attribute.AiAttackAttr.FiringStand && - (Master.AttackState == AiAttackEnum.LockingTime || Master.AttackState == AiAttackEnum.Attack) - )) + //在视野中 + if (Master.TargetInView) { if (_pauseTimer >= 0) { @@ -85,7 +87,7 @@ } else { - var masterPosition = Master.GlobalPosition; + var masterPosition = Master.Position; if (_lockTimer >= 1) //卡在一个点超过一秒 { RunOver(playerPos); @@ -97,17 +99,14 @@ _pauseTimer = Utils.Random.RandomRangeFloat(0f, 0.5f); _isMoveOver = true; _moveFlag = false; - Master.BasisVelocity = Vector2.Zero; + //站立 + Master.DoIdle(); } else if (!_moveFlag) { _moveFlag = true; - //计算移动 - var nextPos = Master.NavigationAgent2D.GetNextPathPosition(); - Master.AnimatedSprite.Play(AnimatorNames.Run); - Master.BasisVelocity = - (nextPos - masterPosition - Master.NavigationPoint.Position).Normalized() * - Master.RoleState.MoveSpeed; + //移动 + Master.DoMove(); } else { @@ -117,25 +116,13 @@ _pauseTimer = Utils.Random.RandomRangeFloat(0f, 0.3f); _isMoveOver = true; _moveFlag = false; - Master.BasisVelocity = Vector2.Zero; + //站立 + Master.DoIdle(); } else { - //判断开火状态, 进行移动 - if (weapon == null || !weapon.Attribute.AiAttackAttr.FiringStand || - (Master.AttackState != AiAttackEnum.LockingTime && Master.AttackState != AiAttackEnum.Attack)) - { //正常移动 - //计算移动 - var nextPos = Master.NavigationAgent2D.GetNextPathPosition(); - Master.AnimatedSprite.Play(AnimatorNames.Run); - Master.BasisVelocity = (nextPos - masterPosition - Master.NavigationPoint.Position).Normalized() * - Master.RoleState.MoveSpeed; - } - else //站立不动 - { - Master.AnimatedSprite.Play(AnimatorNames.Idle); - Master.BasisVelocity = Vector2.Zero; - } + //移动 + Master.DoMove(); } if (_prevPos.DistanceSquaredTo(masterPosition) <= 1 * delta) @@ -155,10 +142,10 @@ { ChangeState(AIAdvancedStateEnum.AiFollowUp); } - else + else if (weapon.TriggerIsReady()) //可以攻击 { //发起攻击 - Master.EnemyAttack(); + ChangeState(AIAdvancedStateEnum.AiAttack); } } } diff --git a/DungeonShooting_Godot/src/game/activity/role/enemy/advancedState/AiTailAfterState.cs b/DungeonShooting_Godot/src/game/activity/role/enemy/advancedState/AiTailAfterState.cs index b24319a..1146b13 100644 --- a/DungeonShooting_Godot/src/game/activity/role/enemy/advancedState/AiTailAfterState.cs +++ b/DungeonShooting_Godot/src/game/activity/role/enemy/advancedState/AiTailAfterState.cs @@ -41,7 +41,12 @@ } } } - + + public override void Exit(AIAdvancedStateEnum next) + { + Master.LookTarget = null; + } + public override void Process(float delta) { //这个状态下不会有攻击事件, 所以没必要每一帧检查是否弹药耗尽 @@ -61,29 +66,17 @@ } //枪口指向玩家 - Master.LookTargetPosition(playerPos); + Master.LookTarget = Player.Current; if (!Master.NavigationAgent2D.IsNavigationFinished()) { - var weapon = Master.WeaponPack.ActiveItem; - if (weapon == null || !weapon.Attribute.AiAttackAttr.FiringStand || - (Master.AttackState != AiAttackEnum.LockingTime && Master.AttackState != AiAttackEnum.Attack)) - { - //计算移动 - var nextPos = Master.NavigationAgent2D.GetNextPathPosition(); - Master.AnimatedSprite.Play(AnimatorNames.Run); - Master.BasisVelocity = (nextPos - Master.GlobalPosition - Master.NavigationPoint.Position).Normalized() * - Master.RoleState.MoveSpeed; - } - else - { - Master.AnimatedSprite.Play(AnimatorNames.Idle); - Master.BasisVelocity = Vector2.Zero; - } + //移动 + Master.DoMove(); } else { - Master.BasisVelocity = Vector2.Zero; + //站立 + Master.DoIdle(); } //检测玩家是否在视野内, 如果在, 则切换到 AiTargetInView 状态 if (Master.IsInTailAfterViewRange(playerPos)) diff --git a/DungeonShooting_Godot/src/game/activity/role/enemy/normalState/AiAttackState.cs b/DungeonShooting_Godot/src/game/activity/role/enemy/normalState/AiAttackState.cs index b6f9f92..4fc5e3e 100644 --- a/DungeonShooting_Godot/src/game/activity/role/enemy/normalState/AiAttackState.cs +++ b/DungeonShooting_Godot/src/game/activity/role/enemy/normalState/AiAttackState.cs @@ -19,6 +19,7 @@ { Debug.LogError("攻击冷却还未完成就进入了 AINormalStateEnum.AiAttack 状态!"); ChangeState(prev); + return; } _attackStep = 0; PrevState = prev; diff --git a/DungeonShooting_Godot/src/game/activity/role/enemy/normalState/AiFollowUpState.cs b/DungeonShooting_Godot/src/game/activity/role/enemy/normalState/AiFollowUpState.cs index 5fe2add..9ce25d8 100644 --- a/DungeonShooting_Godot/src/game/activity/role/enemy/normalState/AiFollowUpState.cs +++ b/DungeonShooting_Godot/src/game/activity/role/enemy/normalState/AiFollowUpState.cs @@ -22,6 +22,11 @@ Master.TargetInView = true; } + public override void Exit(AINormalStateEnum next) + { + Master.LookTarget = null; + } + public override void Process(float delta) { var playerPos = Player.Current.GetCenterPosition(); @@ -43,7 +48,7 @@ var inAttackRange = distanceSquared <= Mathf.Pow(Master.GetAttackRange(), 2); //枪口指向玩家 - Master.LookTargetPosition(playerPos); + Master.LookTarget = Player.Current; if (!Master.NavigationAgent2D.IsNavigationFinished()) { diff --git a/DungeonShooting_Godot/src/game/activity/role/enemy/normalState/AiSurroundState.cs b/DungeonShooting_Godot/src/game/activity/role/enemy/normalState/AiSurroundState.cs index f2705bd..9e145c5 100644 --- a/DungeonShooting_Godot/src/game/activity/role/enemy/normalState/AiSurroundState.cs +++ b/DungeonShooting_Godot/src/game/activity/role/enemy/normalState/AiSurroundState.cs @@ -35,12 +35,17 @@ _moveFlag = false; } + public override void Exit(AINormalStateEnum next) + { + Master.LookTarget = null; + } + public override void Process(float delta) { var playerPos = Player.Current.GetCenterPosition(); //枪口指向玩家 - Master.LookTargetPosition(playerPos); + Master.LookTarget = Player.Current; //检测玩家是否在视野内 if (Master.IsInTailAfterViewRange(playerPos)) diff --git a/DungeonShooting_Godot/src/game/activity/role/enemy/normalState/AiTailAfterState.cs b/DungeonShooting_Godot/src/game/activity/role/enemy/normalState/AiTailAfterState.cs index f1a2646..864d094 100644 --- a/DungeonShooting_Godot/src/game/activity/role/enemy/normalState/AiTailAfterState.cs +++ b/DungeonShooting_Godot/src/game/activity/role/enemy/normalState/AiTailAfterState.cs @@ -30,7 +30,12 @@ _navigationUpdateTimer = 0; _viewTimer = 0; } - + + public override void Exit(AINormalStateEnum next) + { + Master.LookTarget = null; + } + public override void Process(float delta) { //这个状态下不会有攻击事件, 所以没必要每一帧检查是否弹药耗尽 @@ -50,7 +55,7 @@ } //枪口指向玩家 - Master.LookTargetPosition(playerPos); + Master.LookTarget = Player.Current; if (!Master.NavigationAgent2D.IsNavigationFinished()) { diff --git a/DungeonShooting_Godot/src/game/activity/weapon/AiAttackEnum.cs b/DungeonShooting_Godot/src/game/activity/weapon/AiAttackEnum.cs new file mode 100644 index 0000000..9ee4dc5 --- /dev/null +++ b/DungeonShooting_Godot/src/game/activity/weapon/AiAttackEnum.cs @@ -0,0 +1,43 @@ + +/// +/// 调用 Weapon.AiTriggerAttackState() 函数返回的结果 +/// +public enum AiAttackEnum +{ + /// + /// 未触发 AiTriggerAttackState() + /// + None, + /// + /// 触发切换武器 + /// + ExchangeWeapon, + /// + /// 没有弹药了 + /// + NoAmmo, + /// + /// 换弹中 + /// + Reloading, + /// + /// 触发换弹 + /// + TriggerReload, + /// + /// 没有武器 + /// + NoWeapon, + /// + /// 正在锁定目标中 + /// + LockingTime, + /// + /// 攻击间隙时间 + /// + AttackInterval, + /// + /// 成功触发攻击 + /// + Attack, +} \ 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 69fc6e7..8d9fc25 100644 --- a/DungeonShooting_Godot/src/game/activity/weapon/Weapon.cs +++ b/DungeonShooting_Godot/src/game/activity/weapon/Weapon.cs @@ -910,6 +910,14 @@ } /// + /// 是否可以按下扳机并发射了 + /// + public bool TriggerIsReady() + { + return GetBeLoadedStateState() >= 2 && !IsAttackIntervalTime(); + } + + /// /// 获取上膛状态,-1: 等待执行自动上膛 , 0: 未上膛, 1: 上膛中, 2: 已经完成上膛 /// public sbyte GetBeLoadedStateState() @@ -1904,79 +1912,6 @@ //-------------------------------- Ai相关 ----------------------------- /// - /// Ai 调用, 刷新 Ai 攻击状态并返回, 并不会调用相应的函数 - /// - public AiAttackEnum AiRefreshAttackState() - { - AiAttackEnum flag; - if (IsTotalAmmoEmpty()) //当前武器弹药打空 - { - //切换到有子弹的武器 - var index = Master.WeaponPack.FindIndex((we, i) => !we.IsTotalAmmoEmpty()); - if (index != -1) - { - flag = AiAttackEnum.ExchangeWeapon; - } - else //所有子弹打光 - { - flag = AiAttackEnum.NoAmmo; - } - } - else if (Reloading) //换弹中 - { - flag = AiAttackEnum.TriggerReload; - } - else if (IsAmmoEmpty()) //弹夹已经打空 - { - flag = AiAttackEnum.Reloading; - } - else if (_beLoadedState == 0 || _beLoadedState == -1) //需要上膛 - { - flag = AiAttackEnum.AttackInterval; - } - else if (_beLoadedState == 1) //上膛中 - { - flag = AiAttackEnum.AttackInterval; - } - else if (_continuousCount >= 1) //连发中 - { - flag = AiAttackEnum.Attack; - } - else if (IsAttackIntervalTime()) //开火间隙 - { - flag = AiAttackEnum.AttackInterval; - } - else - { - var enemy = (AdvancedEnemy)Master; - if (enemy.GetLockTime() >= Attribute.AiAttackAttr.LockingTime) //正常射击 - { - if (GetDelayedAttackTime() > 0) - { - flag = AiAttackEnum.Attack; - } - else - { - if (Attribute.ContinuousShoot) //连发 - { - flag = AiAttackEnum.Attack; - } - else //单发 - { - flag = AiAttackEnum.Attack; - } - } - } - else //锁定时间没到 - { - flag = AiAttackEnum.LockingTime; - } - } - - return flag; - } - - /// /// Ai调用, 触发扣动扳机, 并返回攻击状态 /// public AiAttackEnum AiTriggerAttackState() @@ -2028,7 +1963,7 @@ else { var enemy = (AdvancedEnemy)Master; - if (enemy.GetLockTime() >= Attribute.AiAttackAttr.LockingTime) //正常射击 + if (enemy.LockTargetTime >= Attribute.AiAttackAttr.LockingTime) //正常射击 { if (GetDelayedAttackTime() > 0) {