diff --git a/DungeonShooting_Godot/src/game/GameApplication.cs b/DungeonShooting_Godot/src/game/GameApplication.cs
index 85a1beb..23d0fa6 100644
--- a/DungeonShooting_Godot/src/game/GameApplication.cs
+++ b/DungeonShooting_Godot/src/game/GameApplication.cs
@@ -106,7 +106,7 @@
//固定帧率
//Engine.MaxFps = TargetFps;
//调试绘制开关
- ActivityObject.IsDebug = false;
+ ActivityObject.IsDebug = true;
//Engine.TimeScale = 0.2f;
//调整窗口分辨率
OnWindowSizeChanged();
diff --git a/DungeonShooting_Godot/src/game/activity/role/enemy/AIStateEnum.cs b/DungeonShooting_Godot/src/game/activity/role/enemy/AIStateEnum.cs
deleted file mode 100644
index 05dbbc5..0000000
--- a/DungeonShooting_Godot/src/game/activity/role/enemy/AIStateEnum.cs
+++ /dev/null
@@ -1,36 +0,0 @@
-
-public enum AiStateEnum
-{
- ///
- /// Ai 状态, 正常, 未发现目标
- ///
- AiNormal,
- // ///
- // /// 发现目标, 但不知道在哪
- // ///
- // AiProbe,
- ///
- /// 找到玩家,准备通知其他敌人
- ///
- AiFind,
- ///
- /// 收到其他敌人通知, 前往发现目标的位置
- ///
- AiLeaveFor,
- ///
- /// 发现目标, 目标不在视野内, 但是知道位置
- ///
- AiTailAfter,
- ///
- /// 目标在视野内, 跟进目标, 如果距离在子弹有效射程内, 则开火
- ///
- AiFollowUp,
- ///
- /// 距离足够近, 在目标附近随机移动
- ///
- AiSurround,
- ///
- /// Ai 寻找弹药
- ///
- AiFindAmmo,
-}
\ No newline at end of file
diff --git a/DungeonShooting_Godot/src/game/activity/role/enemy/AdvancedEnemy.cs b/DungeonShooting_Godot/src/game/activity/role/enemy/AdvancedEnemy.cs
index 7166519..cf69f1e 100644
--- a/DungeonShooting_Godot/src/game/activity/role/enemy/AdvancedEnemy.cs
+++ b/DungeonShooting_Godot/src/game/activity/role/enemy/AdvancedEnemy.cs
@@ -29,7 +29,7 @@
///
/// 敌人身上的状态机控制器
///
- public StateController StateController { get; private set; }
+ public StateController StateController { get; private set; }
///
/// 视野半径, 单位像素, 发现玩家后改视野范围可以穿墙
@@ -81,7 +81,7 @@
{
base.OnInit();
IsAi = true;
- StateController = AddComponent>();
+ StateController = AddComponent>();
AttackLayer = PhysicsLayer.Wall | PhysicsLayer.Player;
EnemyLayer = PhysicsLayer.Player;
@@ -104,7 +104,7 @@
StateController.Register(new AiFindAmmoState());
//默认状态
- StateController.ChangeStateInstant(AiStateEnum.AiNormal);
+ StateController.ChangeStateInstant(AIAdvancedStateEnum.AiNormal);
}
public override void EnterTree()
@@ -179,7 +179,7 @@
//目标在视野内的时间
var currState = StateController.CurrState;
- if (currState == AiStateEnum.AiSurround || currState == AiStateEnum.AiFollowUp)
+ if (currState == AIAdvancedStateEnum.AiSurround || currState == AIAdvancedStateEnum.AiFollowUp)
{
var weapon = WeaponPack.ActiveItem;
if (weapon != null)
@@ -262,9 +262,9 @@
{
//受到伤害
var state = StateController.CurrState;
- if (state == AiStateEnum.AiNormal || state == AiStateEnum.AiLeaveFor) //|| state == AiStateEnum.AiProbe
+ if (state == AIAdvancedStateEnum.AiNormal || state == AIAdvancedStateEnum.AiLeaveFor) //|| state == AiStateEnum.AiProbe
{
- StateController.ChangeState(AiStateEnum.AiTailAfter);
+ StateController.ChangeState(AIAdvancedStateEnum.AiTailAfter);
}
}
@@ -370,7 +370,7 @@
}
var currState = StateController.CurrState;
- if (currState == AiStateEnum.AiNormal)// || currState == AiStateEnum.AiProbe)
+ if (currState == AIAdvancedStateEnum.AiNormal)// || currState == AiStateEnum.AiProbe)
{
//判断是否在同一个房间内
return World.Enemy_FindTargetAffiliationSet.Contains(AffiliationArea);
@@ -470,7 +470,7 @@
{
//这几个状态不需要主动拾起武器操作
var state = StateController.CurrState;
- if (state == AiStateEnum.AiNormal)
+ if (state == AIAdvancedStateEnum.AiNormal)
{
return;
}
diff --git a/DungeonShooting_Godot/src/game/activity/role/enemy/Enemy.cs b/DungeonShooting_Godot/src/game/activity/role/enemy/Enemy.cs
index 7265228..4d2e634 100644
--- a/DungeonShooting_Godot/src/game/activity/role/enemy/Enemy.cs
+++ b/DungeonShooting_Godot/src/game/activity/role/enemy/Enemy.cs
@@ -18,7 +18,7 @@
///
/// 敌人身上的状态机控制器
///
- public StateController StateController { get; private set; }
+ public StateController StateController { get; private set; }
///
/// 视野半径, 单位像素, 发现玩家后改视野范围可以穿墙
@@ -36,6 +36,16 @@
public float BackViewRange { get; set; } = 50;
///
+ /// 攻击范围
+ ///
+ public float AttackRange { get; set; } = 200;
+
+ ///
+ /// 开火时是否站立不动
+ ///
+ public bool FiringStand { get; set; } = true;
+
+ ///
/// 视野检测射线, 朝玩家打射线, 检测是否碰到墙
///
[Export, ExportFillNode]
@@ -88,7 +98,7 @@
{
base.OnInit();
IsAi = true;
- StateController = AddComponent>();
+ StateController = AddComponent>();
AttackLayer = PhysicsLayer.Wall | PhysicsLayer.Player;
EnemyLayer = PhysicsLayer.Player;
@@ -102,7 +112,8 @@
StateController.Register(new AiNormalState());
StateController.Register(new AiTailAfterState());
StateController.Register(new AiFollowUpState());
- StateController.ChangeState(AiStateEnum.AiNormal);
+ StateController.Register(new AiSurroundState());
+ StateController.ChangeState(AINormalStateEnum.AiNormal);
}
public override void EnterTree()
@@ -132,14 +143,14 @@
{
AttackState = AiAttackState.Attack;
_attackTimer = AttackInterval;
- EnemyAttack();
+ OnAttack();
}
}
///
/// 敌人发动攻击
///
- public virtual void EnemyAttack()
+ protected virtual void OnAttack()
{
Debug.Log("触发攻击");
var bulletData = FireManager.GetBulletData(this, ConvertRotation(Position.AngleTo(LookPosition)), ExcelConfig.BulletBase_Map["0006"]);
@@ -177,7 +188,7 @@
}
//目标在视野内的时间
var currState = StateController.CurrState;
- if (currState == AiStateEnum.AiSurround || currState == AiStateEnum.AiFollowUp)
+ if (currState == AINormalStateEnum.AiSurround || currState == AINormalStateEnum.AiFollowUp)
{
if (_attackTimer <= 0) //必须在可以开火时记录时间
{
@@ -198,9 +209,9 @@
{
//受到伤害
var state = StateController.CurrState;
- if (state == AiStateEnum.AiNormal || state == AiStateEnum.AiLeaveFor) //|| state == AiStateEnum.AiProbe
+ if (state == AINormalStateEnum.AiNormal || state == AINormalStateEnum.AiLeaveFor) //|| state == AiStateEnum.AiProbe
{
- StateController.ChangeState(AiStateEnum.AiTailAfter);
+ StateController.ChangeState(AINormalStateEnum.AiTailAfter);
}
}
@@ -238,7 +249,7 @@
}
var currState = StateController.CurrState;
- if (currState == AiStateEnum.AiNormal)// || currState == AiStateEnum.AiProbe)
+ if (currState == AINormalStateEnum.AiNormal)// || currState == AiStateEnum.AiProbe)
{
//判断是否在同一个房间内
return World.Enemy_FindTargetAffiliationSet.Contains(AffiliationArea);
@@ -327,10 +338,9 @@
///
/// 获取攻击范围
///
- /// 从最小到最大距离的过渡量, 0 - 1, 默认 0.5
- public float GetAttackRange(float weight = 0.5f)
+ public float GetAttackRange()
{
- return 200;
+ return AttackRange;
}
public override float GetFirePointAltitude()
diff --git a/DungeonShooting_Godot/src/game/activity/role/enemy/advancedState/AIAdvancedStateEnum.cs b/DungeonShooting_Godot/src/game/activity/role/enemy/advancedState/AIAdvancedStateEnum.cs
new file mode 100644
index 0000000..117b3c1
--- /dev/null
+++ b/DungeonShooting_Godot/src/game/activity/role/enemy/advancedState/AIAdvancedStateEnum.cs
@@ -0,0 +1,36 @@
+
+public enum AIAdvancedStateEnum
+{
+ ///
+ /// Ai 状态, 正常, 未发现目标
+ ///
+ AiNormal,
+ // ///
+ // /// 发现目标, 但不知道在哪
+ // ///
+ // AiProbe,
+ ///
+ /// 找到玩家,准备通知其他敌人
+ ///
+ AiFind,
+ ///
+ /// 收到其他敌人通知, 前往发现目标的位置
+ ///
+ AiLeaveFor,
+ ///
+ /// 发现目标, 目标不在视野内, 但是知道位置
+ ///
+ AiTailAfter,
+ ///
+ /// 目标在视野内, 跟进目标, 如果距离在子弹有效射程内, 则开火
+ ///
+ AiFollowUp,
+ ///
+ /// 距离足够近, 在目标附近随机移动
+ ///
+ AiSurround,
+ ///
+ /// Ai 寻找弹药
+ ///
+ AiFindAmmo,
+}
\ 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 ab9ef33..c650113 100644
--- a/DungeonShooting_Godot/src/game/activity/role/enemy/advancedState/AiFindAmmoState.cs
+++ b/DungeonShooting_Godot/src/game/activity/role/enemy/advancedState/AiFindAmmoState.cs
@@ -6,7 +6,7 @@
///
/// Ai 寻找弹药, 进入该状态需要在参数中传入目标武器对象
///
-public class AiFindAmmoState : StateBase
+public class AiFindAmmoState : StateBase
{
private Weapon _target;
@@ -18,11 +18,11 @@
private bool _isInTailAfterRange = false;
private float _tailAfterTimer = 0;
- public AiFindAmmoState() : base(AiStateEnum.AiFindAmmo)
+ public AiFindAmmoState() : base(AIAdvancedStateEnum.AiFindAmmo)
{
}
- public override void Enter(AiStateEnum prev, params object[] args)
+ public override void Enter(AIAdvancedStateEnum prev, params object[] args)
{
if (args.Length == 0)
{
@@ -119,9 +119,9 @@
}
}
- private AiStateEnum GetNextState()
+ private AIAdvancedStateEnum GetNextState()
{
- return _tailAfterTimer > 10 ? AiStateEnum.AiNormal : AiStateEnum.AiTailAfter;
+ return _tailAfterTimer > 10 ? AIAdvancedStateEnum.AiNormal : AIAdvancedStateEnum.AiTailAfter;
}
private void SetTargetWeapon(Weapon weapon)
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 f635a9d..86bbe98 100644
--- a/DungeonShooting_Godot/src/game/activity/role/enemy/advancedState/AiFollowUpState.cs
+++ b/DungeonShooting_Godot/src/game/activity/role/enemy/advancedState/AiFollowUpState.cs
@@ -6,17 +6,17 @@
///
/// 目标在视野内, 跟进目标, 如果距离在子弹有效射程内, 则开火
///
-public class AiFollowUpState : StateBase
+public class AiFollowUpState : StateBase
{
//导航目标点刷新计时器
private float _navigationUpdateTimer = 0;
private float _navigationInterval = 0.3f;
- public AiFollowUpState() : base(AiStateEnum.AiFollowUp)
+ public AiFollowUpState() : base(AIAdvancedStateEnum.AiFollowUp)
{
}
- public override void Enter(AiStateEnum prev, params object[] args)
+ public override void Enter(AIAdvancedStateEnum prev, params object[] args)
{
_navigationUpdateTimer = 0;
Master.TargetInView = true;
@@ -31,13 +31,13 @@
var targetWeapon = Master.FindTargetWeapon();
if (targetWeapon != null)
{
- ChangeState(AiStateEnum.AiFindAmmo, targetWeapon);
+ ChangeState(AIAdvancedStateEnum.AiFindAmmo, targetWeapon);
return;
}
else
{
//切换到随机移动状态
- ChangeState(AiStateEnum.AiSurround);
+ ChangeState(AIAdvancedStateEnum.AiSurround);
}
}
@@ -61,9 +61,10 @@
var inAttackRange = false;
var weapon = Master.WeaponPack.ActiveItem;
+ var distanceSquared = masterPosition.DistanceSquaredTo(playerPos);
if (weapon != null)
{
- inAttackRange = masterPosition.DistanceSquaredTo(playerPos) <= Mathf.Pow(Master.GetWeaponRange(0.7f), 2);
+ inAttackRange = distanceSquared <= Mathf.Pow(Master.GetWeaponRange(0.7f), 2);
}
//枪口指向玩家
@@ -112,15 +113,15 @@
Master.EnemyAttack();
//距离够近, 可以切换到环绕模式
- if (Master.GlobalPosition.DistanceSquaredTo(playerPos) <= Mathf.Pow(Utils.GetConfigRangeStart(weapon.Attribute.Bullet.DistanceRange), 2) * 0.7f)
+ if (distanceSquared <= Mathf.Pow(Utils.GetConfigRangeStart(weapon.Attribute.Bullet.DistanceRange), 2) * 0.7f)
{
- ChangeState(AiStateEnum.AiSurround);
+ ChangeState(AIAdvancedStateEnum.AiSurround);
}
}
}
else //不在视野中
{
- ChangeState(AiStateEnum.AiTailAfter);
+ ChangeState(AIAdvancedStateEnum.AiTailAfter);
}
}
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 73e339b..4c56fb2 100644
--- a/DungeonShooting_Godot/src/game/activity/role/enemy/advancedState/AiLeaveForState.cs
+++ b/DungeonShooting_Godot/src/game/activity/role/enemy/advancedState/AiLeaveForState.cs
@@ -6,17 +6,17 @@
///
/// 收到其他敌人通知, 前往发现目标的位置
///
-public class AiLeaveForState : StateBase
+public class AiLeaveForState : StateBase
{
//导航目标点刷新计时器
private float _navigationUpdateTimer = 0;
private float _navigationInterval = 0.3f;
- public AiLeaveForState() : base(AiStateEnum.AiLeaveFor)
+ public AiLeaveForState() : base(AIAdvancedStateEnum.AiLeaveFor)
{
}
- public override void Enter(AiStateEnum prev, params object[] args)
+ public override void Enter(AIAdvancedStateEnum prev, params object[] args)
{
if (Master.World.Enemy_IsFindTarget)
{
@@ -35,7 +35,7 @@
var targetWeapon = Master.FindTargetWeapon();
if (targetWeapon != null)
{
- ChangeState(AiStateEnum.AiFindAmmo, targetWeapon);
+ ChangeState(AIAdvancedStateEnum.AiFindAmmo, targetWeapon);
}
}
}
@@ -79,7 +79,7 @@
//关闭射线检测
Master.TestViewRayCastOver();
//切换成发现目标状态
- ChangeState(AiStateEnum.AiFollowUp);
+ ChangeState(AIAdvancedStateEnum.AiFollowUp);
return;
}
else
@@ -92,7 +92,7 @@
//移动到目标掉了, 还没发现目标
if (Master.NavigationAgent2D.IsNavigationFinished())
{
- ChangeState(AiStateEnum.AiNormal);
+ ChangeState(AIAdvancedStateEnum.AiNormal);
}
}
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 5f469d1..13362bc 100644
--- a/DungeonShooting_Godot/src/game/activity/role/enemy/advancedState/AiNormalState.cs
+++ b/DungeonShooting_Godot/src/game/activity/role/enemy/advancedState/AiNormalState.cs
@@ -6,7 +6,7 @@
///
/// AI 正常状态
///
-public class AiNormalState : StateBase
+public class AiNormalState : StateBase
{
//是否发现玩家
private bool _isFindPlayer;
@@ -32,11 +32,11 @@
//卡在一个位置的时间
private float _lockTimer;
- public AiNormalState() : base(AiStateEnum.AiNormal)
+ public AiNormalState() : base(AIAdvancedStateEnum.AiNormal)
{
}
- public override void Enter(AiStateEnum prev, params object[] args)
+ public override void Enter(AIAdvancedStateEnum prev, params object[] args)
{
_isFindPlayer = false;
_isMoveOver = true;
@@ -51,14 +51,14 @@
//其他敌人发现玩家
if (Master.CanChangeLeaveFor())
{
- ChangeState(AiStateEnum.AiLeaveFor);
+ ChangeState(AIAdvancedStateEnum.AiLeaveFor);
return;
}
if (_isFindPlayer) //已经找到玩家了
{
//现临时处理, 直接切换状态
- ChangeState(AiStateEnum.AiTailAfter);
+ ChangeState(AIAdvancedStateEnum.AiTailAfter);
}
else //没有找到玩家
{
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 a7b2fe4..07dc504 100644
--- a/DungeonShooting_Godot/src/game/activity/role/enemy/advancedState/AiSurroundState.cs
+++ b/DungeonShooting_Godot/src/game/activity/role/enemy/advancedState/AiSurroundState.cs
@@ -6,7 +6,7 @@
///
/// 距离目标足够近, 在目标附近随机移动, 并开火
///
-public class AiSurroundState : StateBase
+public class AiSurroundState : StateBase
{
//是否移动结束
private bool _isMoveOver;
@@ -23,11 +23,11 @@
//卡在一个位置的时间
private float _lockTimer;
- public AiSurroundState() : base(AiStateEnum.AiSurround)
+ public AiSurroundState() : base(AIAdvancedStateEnum.AiSurround)
{
}
- public override void Enter(AiStateEnum prev, params object[] args)
+ public override void Enter(AIAdvancedStateEnum prev, params object[] args)
{
Master.TargetInView = true;
_isMoveOver = true;
@@ -44,7 +44,7 @@
var targetWeapon = Master.FindTargetWeapon();
if (targetWeapon != null)
{
- ChangeState(AiStateEnum.AiFindAmmo, targetWeapon);
+ ChangeState(AIAdvancedStateEnum.AiFindAmmo, targetWeapon);
return;
}
}
@@ -85,6 +85,7 @@
}
else
{
+ var masterPosition = Master.GlobalPosition;
if (_lockTimer >= 1) //卡在一个点超过一秒
{
RunOver(playerPos);
@@ -105,12 +106,12 @@
var nextPos = Master.NavigationAgent2D.GetNextPathPosition();
Master.AnimatedSprite.Play(AnimatorNames.Run);
Master.BasisVelocity =
- (nextPos - Master.GlobalPosition - Master.NavigationPoint.Position).Normalized() *
+ (nextPos - masterPosition - Master.NavigationPoint.Position).Normalized() *
Master.RoleState.MoveSpeed;
}
else
{
- var pos = Master.GlobalPosition;
+ var pos = masterPosition;
var lastSlideCollision = Master.GetLastSlideCollision();
if (lastSlideCollision != null && lastSlideCollision.GetCollider() is AdvancedRole) //碰到其他角色
{
@@ -138,7 +139,7 @@
}
}
- if (_prevPos.DistanceSquaredTo(pos) <= 0.01f)
+ if (_prevPos.DistanceSquaredTo(pos) <= 1 * delta)
{
_lockTimer += delta;
}
@@ -150,10 +151,9 @@
if (weapon != null)
{
- var position = Master.GlobalPosition;
- if (position.DistanceSquaredTo(playerPos) > Mathf.Pow(Master.GetWeaponRange(0.7f), 2)) //玩家离开正常射击范围
+ if (masterPosition.DistanceSquaredTo(playerPos) > Mathf.Pow(Master.GetWeaponRange(0.7f), 2)) //玩家离开正常射击范围
{
- ChangeState(AiStateEnum.AiFollowUp);
+ ChangeState(AIAdvancedStateEnum.AiFollowUp);
}
else
{
@@ -165,7 +165,7 @@
}
else //目标离开视野
{
- ChangeState(AiStateEnum.AiTailAfter);
+ ChangeState(AIAdvancedStateEnum.AiTailAfter);
}
}
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 569690e..96fc91c 100644
--- a/DungeonShooting_Godot/src/game/activity/role/enemy/advancedState/AiTailAfterState.cs
+++ b/DungeonShooting_Godot/src/game/activity/role/enemy/advancedState/AiTailAfterState.cs
@@ -6,7 +6,7 @@
///
/// AI 发现玩家, 跟随玩家
///
-public class AiTailAfterState : StateBase
+public class AiTailAfterState : StateBase
{
///
/// 目标是否在视野半径内
@@ -20,11 +20,11 @@
//目标从视野消失时已经过去的时间
private float _viewTimer;
- public AiTailAfterState() : base(AiStateEnum.AiTailAfter)
+ public AiTailAfterState() : base(AIAdvancedStateEnum.AiTailAfter)
{
}
- public override void Enter(AiStateEnum prev, params object[] args)
+ public override void Enter(AIAdvancedStateEnum prev, params object[] args)
{
_isInViewRange = true;
_navigationUpdateTimer = 0;
@@ -37,7 +37,7 @@
var targetWeapon = Master.FindTargetWeapon();
if (targetWeapon != null)
{
- ChangeState(AiStateEnum.AiFindAmmo, targetWeapon);
+ ChangeState(AIAdvancedStateEnum.AiFindAmmo, targetWeapon);
}
}
}
@@ -93,7 +93,7 @@
//关闭射线检测
Master.TestViewRayCastOver();
//切换成发现目标状态
- ChangeState(AiStateEnum.AiFollowUp);
+ ChangeState(AIAdvancedStateEnum.AiFollowUp);
return;
}
else
@@ -113,7 +113,7 @@
{
if (_viewTimer > 10) //10秒
{
- ChangeState(AiStateEnum.AiNormal);
+ ChangeState(AIAdvancedStateEnum.AiNormal);
}
else
{
diff --git a/DungeonShooting_Godot/src/game/activity/role/enemy/normalState/AINormalStateEnum.cs b/DungeonShooting_Godot/src/game/activity/role/enemy/normalState/AINormalStateEnum.cs
new file mode 100644
index 0000000..447e4e6
--- /dev/null
+++ b/DungeonShooting_Godot/src/game/activity/role/enemy/normalState/AINormalStateEnum.cs
@@ -0,0 +1,33 @@
+namespace NnormalState;
+
+public enum AINormalStateEnum
+{
+ ///
+ /// Ai 状态, 正常, 未发现目标
+ ///
+ AiNormal,
+ // ///
+ // /// 发现目标, 但不知道在哪
+ // ///
+ // AiProbe,
+ ///
+ /// 找到玩家,准备通知其他敌人
+ ///
+ AiFind,
+ ///
+ /// 收到其他敌人通知, 前往发现目标的位置
+ ///
+ AiLeaveFor,
+ ///
+ /// 发现目标, 目标不在视野内, 但是知道位置
+ ///
+ AiTailAfter,
+ ///
+ /// 目标在视野内, 跟进目标, 如果距离在子弹有效射程内, 则开火
+ ///
+ AiFollowUp,
+ ///
+ /// 距离足够近, 在目标附近随机移动
+ ///
+ AiSurround,
+}
\ No newline at end of file
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 c4ec235..b0185de 100644
--- a/DungeonShooting_Godot/src/game/activity/role/enemy/normalState/AiFollowUpState.cs
+++ b/DungeonShooting_Godot/src/game/activity/role/enemy/normalState/AiFollowUpState.cs
@@ -6,17 +6,17 @@
///
/// 目标在视野内, 跟进目标, 如果距离在子弹有效射程内, 则开火
///
-public class AiFollowUpState : StateBase
+public class AiFollowUpState : StateBase
{
//导航目标点刷新计时器
private float _navigationUpdateTimer = 0;
private float _navigationInterval = 0.3f;
- public AiFollowUpState() : base(AiStateEnum.AiFollowUp)
+ public AiFollowUpState() : base(AINormalStateEnum.AiFollowUp)
{
}
- public override void Enter(AiStateEnum prev, params object[] args)
+ public override void Enter(AINormalStateEnum prev, params object[] args)
{
_navigationUpdateTimer = 0;
Master.TargetInView = true;
@@ -39,9 +39,9 @@
}
var masterPosition = Master.GlobalPosition;
-
+ var distanceSquared = masterPosition.DistanceSquaredTo(playerPos);
//是否在攻击范围内
- var inAttackRange = masterPosition.DistanceSquaredTo(playerPos) <= Mathf.Pow(Master.GetAttackRange(0.7f), 2);
+ var inAttackRange = distanceSquared <= Mathf.Pow(Master.GetAttackRange(), 2);
//枪口指向玩家
Master.LookTargetPosition(playerPos);
@@ -89,15 +89,15 @@
Master.Attack();
//距离够近, 可以切换到环绕模式
- // if (Master.GlobalPosition.DistanceSquaredTo(playerPos) <= Mathf.Pow(Utils.GetConfigRangeStart(weapon.Attribute.Bullet.DistanceRange), 2) * 0.7f)
- // {
- // ChangeState(AiStateEnum.AiSurround);
- // }
+ if (distanceSquared <= Mathf.Pow(Master.GetAttackRange() * 0.7f, 2) * 0.7f)
+ {
+ ChangeState(AINormalStateEnum.AiSurround);
+ }
}
}
else //不在视野中
{
- ChangeState(AiStateEnum.AiTailAfter);
+ ChangeState(AINormalStateEnum.AiTailAfter);
}
}
diff --git a/DungeonShooting_Godot/src/game/activity/role/enemy/normalState/AiNormalState.cs b/DungeonShooting_Godot/src/game/activity/role/enemy/normalState/AiNormalState.cs
index 9cf340a..e991e00 100644
--- a/DungeonShooting_Godot/src/game/activity/role/enemy/normalState/AiNormalState.cs
+++ b/DungeonShooting_Godot/src/game/activity/role/enemy/normalState/AiNormalState.cs
@@ -5,7 +5,7 @@
///
/// AI 正常状态
///
-public class AiNormalState : StateBase
+public class AiNormalState : StateBase
{
//是否发现玩家
private bool _isFindPlayer;
@@ -31,11 +31,11 @@
//卡在一个位置的时间
private float _lockTimer;
- public AiNormalState() : base(AiStateEnum.AiNormal)
+ public AiNormalState() : base(AINormalStateEnum.AiNormal)
{
}
- public override void Enter(AiStateEnum prev, params object[] args)
+ public override void Enter(AINormalStateEnum prev, params object[] args)
{
_isFindPlayer = false;
_isMoveOver = true;
@@ -50,14 +50,14 @@
//其他敌人发现玩家
if (Master.CanChangeLeaveFor())
{
- ChangeState(AiStateEnum.AiLeaveFor);
+ ChangeState(AINormalStateEnum.AiLeaveFor);
return;
}
if (_isFindPlayer) //已经找到玩家了
{
//现临时处理, 直接切换状态
- ChangeState(AiStateEnum.AiTailAfter);
+ ChangeState(AINormalStateEnum.AiTailAfter);
}
else //没有找到玩家
{
diff --git a/DungeonShooting_Godot/src/game/activity/role/enemy/normalState/AiSurroundState.cs b/DungeonShooting_Godot/src/game/activity/role/enemy/normalState/AiSurroundState.cs
new file mode 100644
index 0000000..b66e1fb
--- /dev/null
+++ b/DungeonShooting_Godot/src/game/activity/role/enemy/normalState/AiSurroundState.cs
@@ -0,0 +1,170 @@
+
+using Godot;
+
+namespace NnormalState;
+
+///
+/// 距离目标足够近, 在目标附近随机移动, 并开火
+///
+public class AiSurroundState : StateBase
+{
+ //是否移动结束
+ private bool _isMoveOver;
+
+ //移动停顿计时器
+ private float _pauseTimer;
+ private bool _moveFlag;
+
+ //下一个移动点
+ private Vector2 _nextPosition;
+
+ //上一帧位置
+ private Vector2 _prevPos;
+ //卡在一个位置的时间
+ private float _lockTimer;
+
+ public AiSurroundState() : base(AINormalStateEnum.AiSurround)
+ {
+ }
+
+ public override void Enter(AINormalStateEnum prev, params object[] args)
+ {
+ Master.TargetInView = true;
+ _isMoveOver = true;
+ _pauseTimer = 0;
+ _moveFlag = false;
+ }
+
+ public override void Process(float delta)
+ {
+ var playerPos = Player.Current.GetCenterPosition();
+
+ //枪口指向玩家
+ Master.LookTargetPosition(playerPos);
+
+ //检测玩家是否在视野内
+ if (Master.IsInTailAfterViewRange(playerPos))
+ {
+ Master.TargetInView = !Master.TestViewRayCast(playerPos);
+ //关闭射线检测
+ Master.TestViewRayCastOver();
+ }
+ else
+ {
+ Master.TargetInView = false;
+ }
+
+ //在视野中, 或者锁敌状态下, 或者攻击状态下, 继续保持原本逻辑
+ if (Master.TargetInView ||
+ (Master.FiringStand &&
+ (Master.AttackState == AiAttackState.LockingTime || Master.AttackState == AiAttackState.Attack)
+ ))
+ {
+ if (_pauseTimer >= 0)
+ {
+ Master.AnimatedSprite.Play(AnimatorNames.Idle);
+ _pauseTimer -= delta;
+ }
+ else if (_isMoveOver) //移动已经完成
+ {
+ RunOver(playerPos);
+ _isMoveOver = false;
+ }
+ else
+ {
+ var masterPosition = Master.GlobalPosition;
+ if (_lockTimer >= 1) //卡在一个点超过一秒
+ {
+ RunOver(playerPos);
+ _isMoveOver = false;
+ _lockTimer = 0;
+ }
+ else if (Master.NavigationAgent2D.IsNavigationFinished()) //到达终点
+ {
+ _pauseTimer = Utils.Random.RandomRangeFloat(0f, 0.5f);
+ _isMoveOver = true;
+ _moveFlag = false;
+ Master.BasisVelocity = Vector2.Zero;
+ }
+ 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;
+ }
+ else
+ {
+ var pos = masterPosition;
+ var lastSlideCollision = Master.GetLastSlideCollision();
+ if (lastSlideCollision != null && lastSlideCollision.GetCollider() is AdvancedRole) //碰到其他角色
+ {
+ _pauseTimer = Utils.Random.RandomRangeFloat(0f, 0.3f);
+ _isMoveOver = true;
+ _moveFlag = false;
+ Master.BasisVelocity = Vector2.Zero;
+ }
+ else
+ {
+ //判断开火状态, 进行移动
+ if (!Master.FiringStand ||
+ (Master.AttackState != AiAttackState.LockingTime && Master.AttackState != AiAttackState.Attack))
+ { //正常移动
+ //计算移动
+ var nextPos = Master.NavigationAgent2D.GetNextPathPosition();
+ Master.AnimatedSprite.Play(AnimatorNames.Run);
+ Master.BasisVelocity = (nextPos - pos - Master.NavigationPoint.Position).Normalized() *
+ Master.RoleState.MoveSpeed;
+ }
+ else //站立不动
+ {
+ Master.AnimatedSprite.Play(AnimatorNames.Idle);
+ Master.BasisVelocity = Vector2.Zero;
+ }
+ }
+
+ if (_prevPos.DistanceSquaredTo(pos) <= 1 * delta)
+ {
+ _lockTimer += delta;
+ }
+ else
+ {
+ _prevPos = pos;
+ }
+ }
+
+ if (masterPosition.DistanceSquaredTo(playerPos) > Mathf.Pow(Master.GetAttackRange() * 0.7f, 2)) //玩家离开正常射击范围
+ {
+ ChangeState(AINormalStateEnum.AiFollowUp);
+ }
+ else
+ {
+ //发起攻击
+ Master.Attack();
+ }
+ }
+ }
+ else //目标离开视野
+ {
+ ChangeState(AINormalStateEnum.AiTailAfter);
+ }
+ }
+
+ private void RunOver(Vector2 targetPos)
+ {
+ var distance = (int)(Master.GetAttackRange() * 0.7f);
+ _nextPosition = new Vector2(
+ targetPos.X + Utils.Random.RandomRangeInt(-distance, distance),
+ targetPos.Y + Utils.Random.RandomRangeInt(-distance, distance)
+ );
+ Master.NavigationAgent2D.TargetPosition = _nextPosition;
+ }
+
+ public override void DebugDraw()
+ {
+ Master.DrawLine(new Vector2(0, -8), Master.ToLocal(_nextPosition), Colors.White);
+ }
+}
\ No newline at end of file
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 3d29972..fe894e2 100644
--- a/DungeonShooting_Godot/src/game/activity/role/enemy/normalState/AiTailAfterState.cs
+++ b/DungeonShooting_Godot/src/game/activity/role/enemy/normalState/AiTailAfterState.cs
@@ -6,7 +6,7 @@
///
/// AI 发现玩家, 跟随玩家
///
-public class AiTailAfterState : StateBase
+public class AiTailAfterState : StateBase
{
///
/// 目标是否在视野半径内
@@ -20,11 +20,11 @@
//目标从视野消失时已经过去的时间
private float _viewTimer;
- public AiTailAfterState() : base(AiStateEnum.AiTailAfter)
+ public AiTailAfterState() : base(AINormalStateEnum.AiTailAfter)
{
}
- public override void Enter(AiStateEnum prev, params object[] args)
+ public override void Enter(AINormalStateEnum prev, params object[] args)
{
_isInViewRange = true;
_navigationUpdateTimer = 0;
@@ -80,7 +80,7 @@
//关闭射线检测
Master.TestViewRayCastOver();
//切换成发现目标状态
- ChangeState(AiStateEnum.AiFollowUp);
+ ChangeState(AINormalStateEnum.AiFollowUp);
return;
}
else
@@ -100,7 +100,7 @@
{
if (_viewTimer > 10) //10秒
{
- ChangeState(AiStateEnum.AiNormal);
+ ChangeState(AINormalStateEnum.AiNormal);
}
else
{
diff --git a/DungeonShooting_Godot/src/game/room/DungeonManager.cs b/DungeonShooting_Godot/src/game/room/DungeonManager.cs
index 09a0576..e53840c 100644
--- a/DungeonShooting_Godot/src/game/room/DungeonManager.cs
+++ b/DungeonShooting_Godot/src/game/room/DungeonManager.cs
@@ -3,6 +3,7 @@
using System.Collections;
using System.Collections.Generic;
using Godot;
+using NnormalState;
///
/// 地牢管理器
@@ -569,16 +570,16 @@
{
if (enemy is Enemy e)
{
- if (e.StateController.CurrState != AiStateEnum.AiNormal)
+ if (e.StateController.CurrState != AINormalStateEnum.AiNormal)
{
- e.StateController.ChangeState(AiStateEnum.AiNormal);
+ e.StateController.ChangeState(AINormalStateEnum.AiNormal);
}
}
else if (enemy is AdvancedEnemy ae)
{
- if (ae.StateController.CurrState != AiStateEnum.AiNormal)
+ if (ae.StateController.CurrState != AIAdvancedStateEnum.AiNormal)
{
- ae.StateController.ChangeState(AiStateEnum.AiNormal);
+ ae.StateController.ChangeState(AIAdvancedStateEnum.AiNormal);
}
}
else
@@ -644,29 +645,39 @@
for (var i = 0; i < World.Enemy_InstanceList.Count; i++)
{
var enemy = World.Enemy_InstanceList[i];
- AiStateEnum state;
if (enemy is Enemy e)
{
- state = e.StateController.CurrState;
+ var state = e.StateController.CurrState;
+ if (state == AINormalStateEnum.AiFollowUp || state == AINormalStateEnum.AiSurround) //目标在视野内
+ {
+ if (!World.Enemy_IsFindTarget)
+ {
+ World.Enemy_IsFindTarget = true;
+ World.Enemy_FindTargetPosition = Player.Current.GetCenterPosition();
+ World.Enemy_FindTargetAffiliationSet.Add(Player.Current.AffiliationArea);
+ }
+ World.Enemy_FindTargetAffiliationSet.Add(enemy.AffiliationArea);
+ }
}
else if (enemy is AdvancedEnemy ae)
{
- state = ae.StateController.CurrState;
+ var state = ae.StateController.CurrState;
+ if (state == AIAdvancedStateEnum.AiFollowUp || state == AIAdvancedStateEnum.AiSurround) //目标在视野内
+ {
+ if (!World.Enemy_IsFindTarget)
+ {
+ World.Enemy_IsFindTarget = true;
+ World.Enemy_FindTargetPosition = Player.Current.GetCenterPosition();
+ World.Enemy_FindTargetAffiliationSet.Add(Player.Current.AffiliationArea);
+ }
+ World.Enemy_FindTargetAffiliationSet.Add(enemy.AffiliationArea);
+ }
}
else
{
throw new Exception("World.Enemy_InstanceList 混入了非 Enemy 和 AdvancedEnemy 类型的对象!");
}
- if (state == AiStateEnum.AiFollowUp || state == AiStateEnum.AiSurround) //目标在视野内
- {
- if (!World.Enemy_IsFindTarget)
- {
- World.Enemy_IsFindTarget = true;
- World.Enemy_FindTargetPosition = Player.Current.GetCenterPosition();
- World.Enemy_FindTargetAffiliationSet.Add(Player.Current.AffiliationArea);
- }
- World.Enemy_FindTargetAffiliationSet.Add(enemy.AffiliationArea);
- }
+
}
}