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)
{