Newer
Older
DungeonShooting / DungeonShooting_Godot / src / game / role / enemy / Enemy.cs
@小李xl 小李xl on 24 Nov 2022 4 KB 生成NavigationPolygon功能完成
  1. #region 基础敌人设计思路
  2. /*
  3. 敌人有三种状态:
  4. 状态1: 未发现玩家, 视野不可穿墙, 该状态下敌人移动比较规律, 移动速度较慢, 一旦玩家进入视野或者听到玩家枪声, 立刻切换至状态3, 该房间的敌人不能再回到状态1
  5. 状态2: 发现有玩家, 但不知道在哪, 视野不可穿墙, 该情况下敌人移动速度明显加快, 移动不规律, 一旦玩家进入视野或者听到玩家枪声, 立刻切换至状态3
  6. 状态3: 明确知道玩家的位置, 视野允许穿墙, 移动速度与状态2一致, 进入该状态时, 敌人之间会相互告知玩家所在位置, 并朝着玩家位置开火,
  7. 如果有墙格挡, 则有一定概率继续开火, 一旦玩家立刻敌人视野超哥一段时间, 敌人自动切换为状态2
  8.  
  9. 敌人状态1只存在于少数房间内, 比如特殊房间, 大部分情况下敌人应该是状态2, 或者玩家进入房间时就被敌人发现
  10. */
  11. #endregion
  12.  
  13.  
  14. using Godot;
  15.  
  16. /// <summary>
  17. /// 基础敌人
  18. /// </summary>
  19. public class Enemy : Role
  20. {
  21.  
  22. /// <summary>
  23. /// 敌人身上的状态机控制器
  24. /// </summary>
  25. public StateController<Enemy, AIStateEnum> StateController { get; }
  26. /// <summary>
  27. /// 视野半径, 单位像素
  28. /// </summary>
  29. public float ViewRange { get; set; } = 200;
  30.  
  31. /// <summary>
  32. /// 背后的视野半径, 单位像素
  33. /// </summary>
  34. public float BackViewRange { get; set; } = 50;
  35. /// <summary>
  36. /// 视野检测射线, 朝玩家打射线, 检测是否碰到墙
  37. /// </summary>
  38. public RayCast2D ViewRay { get; }
  39. //------------------- 寻路相关 ---------------------------
  40.  
  41. /// <summary>
  42. /// 移动目标标记
  43. /// </summary>
  44. public PathSign PathSign { get; }
  45.  
  46. /// <summary>
  47. /// 寻路标记线段总长度
  48. /// </summary>
  49. public float PathSignLength { get; set; } = 500;
  50.  
  51. //-------------------------------------------------------
  52.  
  53. private Node2D _navigationPoint;
  54. private NavigationAgent2D _navigationAgent2D;
  55. private float _navigationUpdateTimer = 0;
  56. public Enemy() : base(ResourcePath.prefab_role_Enemy_tscn)
  57. {
  58. StateController = new StateController<Enemy, AIStateEnum>();
  59. AddComponent(StateController);
  60. AttackLayer = PhysicsLayer.Wall | PhysicsLayer.Props | PhysicsLayer.Player;
  61. Camp = CampEnum.Camp2;
  62.  
  63. MoveSpeed = 20;
  64. //视野射线
  65. ViewRay = GetNode<RayCast2D>("ViewRay");
  66. _navigationPoint = GetNode<Node2D>("NavigationPoint");
  67. _navigationAgent2D = _navigationPoint.GetNode<NavigationAgent2D>("NavigationAgent2D");
  68. PathSign = new PathSign(this, PathSignLength, GameApplication.Instance.Room.Player);
  69. //注册Ai状态机
  70. StateController.Register(new AINormalState());
  71. StateController.Register(new AIProbeState());
  72. StateController.Register(new AITailAfterState());
  73. }
  74.  
  75. public override void _Ready()
  76. {
  77. base._Ready();
  78. //默认状态
  79. StateController.ChangeState(AIStateEnum.AINormal);
  80. _navigationAgent2D.SetTargetLocation(GameApplication.Instance.Room.Player.GlobalPosition);
  81. }
  82. public override void _Process(float delta)
  83. {
  84. base._Process(delta);
  85. if (GameApplication.Instance.Debug)
  86. {
  87. PathSign.Scale = new Vector2((int)Face, 1);
  88. Update();
  89. }
  90. }
  91.  
  92. public override void _PhysicsProcess(float delta)
  93. {
  94. base._PhysicsProcess(delta);
  95.  
  96. if (_navigationAgent2D.IsNavigationFinished())
  97. {
  98. return;
  99. }
  100. var playerGlobalPosition = GameApplication.Instance.Room.Player.GlobalPosition;
  101. //临时处理, 让敌人跟随玩家
  102. if (_navigationUpdateTimer <= 0)
  103. {
  104. _navigationUpdateTimer = 0.2f;
  105. if (_navigationAgent2D.GetTargetLocation() != playerGlobalPosition)
  106. {
  107. _navigationAgent2D.SetTargetLocation(playerGlobalPosition);
  108. }
  109. }
  110. else
  111. {
  112. _navigationUpdateTimer -= delta;
  113. }
  114. var nextPos = _navigationAgent2D.GetNextLocation();
  115. LookTargetPosition(playerGlobalPosition);
  116. AnimatedSprite.Animation = AnimatorNames.Run;
  117. Velocity = (nextPos - GlobalPosition - _navigationPoint.Position).Normalized() * MoveSpeed;
  118. CalcMove(delta);
  119. }
  120.  
  121. public override void _Draw()
  122. {
  123. if (GameApplication.Instance.Debug)
  124. {
  125. if (PathSign != null)
  126. {
  127. DrawLine(Vector2.Zero,ToLocal(PathSign.GlobalPosition), Colors.Red);
  128. }
  129. }
  130. }
  131. }