Newer
Older
DungeonShooting / DungeonShooting_Godot / src / framework / activity / components / StateController.cs
  1. using System;
  2. using Godot;
  3. using System.Collections.Generic;
  4.  
  5. /// <summary>
  6. /// 对象状态机控制器
  7. /// </summary>
  8. public class StateController<T, S> : Component where T : ActivityObject where S : Enum
  9. {
  10. /// <summary>
  11. /// 获取当前状态
  12. /// </summary>
  13. public S CurrState => CurrStateBase != null ? CurrStateBase.State : default;
  14. /// <summary>
  15. /// 当前活跃的状态对象实例
  16. /// </summary>
  17. public StateBase<T, S> CurrStateBase { get; private set; }
  18.  
  19. /// <summary>
  20. /// 负责存放状态实例对象
  21. /// </summary>
  22. private readonly Dictionary<S, StateBase<T, S>> _states = new Dictionary<S, StateBase<T, S>>();
  23.  
  24. /// <summary>
  25. /// 记录下当前帧是否有改变的状态
  26. /// </summary>
  27. private bool _isChangeState;
  28.  
  29. public override void Process(float delta)
  30. {
  31. _isChangeState = false;
  32. if (CurrStateBase != null)
  33. {
  34. CurrStateBase.Process(delta);
  35. //判断当前帧是否有改变的状态, 如果有, 则重新调用 Process() 方法
  36. if (_isChangeState)
  37. {
  38. Process(delta);
  39. }
  40. }
  41. }
  42.  
  43. public override void DebugDraw()
  44. {
  45. if (CurrStateBase != null)
  46. {
  47. CurrStateBase.DebugDraw();
  48. }
  49. }
  50.  
  51. /// <summary>
  52. /// 往状态机里注册一个新的状态实例
  53. /// </summary>
  54. public void Register(StateBase<T, S> stateBase)
  55. {
  56. if (GetStateInstance(stateBase.State) != null)
  57. {
  58. GD.PrintErr("当前状态已经在状态机中注册:", stateBase);
  59. return;
  60. }
  61.  
  62. stateBase.Master = ActivityInstance as T;
  63. stateBase.StateController = this;
  64. _states.Add(stateBase.State, stateBase);
  65. }
  66.  
  67. /// <summary>
  68. /// 返回该状态机控制器中是否存在指定的状态实例
  69. /// </summary>
  70. public bool HasState(S state)
  71. {
  72. return _states.ContainsKey(state);
  73. }
  74. /// <summary>
  75. /// 获取指定状态对应的实例对象
  76. /// </summary>
  77. public StateBase<T, S> GetState(S state)
  78. {
  79. if (_states.TryGetValue(state, out var temp))
  80. {
  81. return temp;
  82. }
  83.  
  84. return null;
  85. }
  86.  
  87. /// <summary>
  88. /// 立即切换到下一个指定状态, 并且这一帧会被调用 Process
  89. /// </summary>
  90. public void ChangeStateInstant(S next, params object[] arg)
  91. {
  92. _changeState(false, next, arg);
  93. }
  94.  
  95. /// <summary>
  96. /// 切换到下一个指定状态, 下一帧才会调用 Process
  97. /// </summary>
  98. public void ChangeState(S next, params object[] arg)
  99. {
  100. _changeState(true, next, arg);
  101. }
  102.  
  103. /// <summary>
  104. /// 根据状态类型获取相应的状态对象
  105. /// </summary>
  106. private StateBase<T, S> GetStateInstance(S stateType)
  107. {
  108. _states.TryGetValue(stateType, out var v);
  109. return v;
  110. }
  111.  
  112. /// <summary>
  113. /// 切换状态
  114. /// </summary>
  115. private void _changeState(bool late, S next, params object[] arg)
  116. {
  117. if (CurrStateBase != null && CurrStateBase.State.Equals(next))
  118. {
  119. return;
  120. }
  121.  
  122. var newState = GetStateInstance(next);
  123. if (newState == null)
  124. {
  125. GD.PrintErr("当前状态机未找到相应状态:" + next);
  126. return;
  127. }
  128.  
  129. if (CurrStateBase == null)
  130. {
  131. CurrStateBase = newState;
  132. newState.Enter(default, arg);
  133. }
  134. else if (CurrStateBase.CanChangeState(next))
  135. {
  136. _isChangeState = !late;
  137. var prev = CurrStateBase.State;
  138. CurrStateBase.Exit(next);
  139. CurrStateBase = newState;
  140. CurrStateBase.Enter(prev, arg);
  141. }
  142. }
  143. }