PageRenderTime 45ms CodeModel.GetById 19ms RepoModel.GetById 1ms app.codeStats 0ms

/MonocleEngine/Components/Logic/StateMachine.cs

https://bitbucket.org/gamblore/monocleengine-monogame
C# | 96 lines | 79 code | 13 blank | 4 comment | 12 complexity | 561b5b18261542e7c4d51229d6b129c5 MD5 | raw file
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. namespace Monocle
  6. {
  7. public class StateMachine<Indexer> : Component where Indexer : struct
  8. {
  9. public delegate Indexer StateCallback();
  10. private Indexer state;
  11. private Dictionary<Indexer, Action> enterStates;
  12. private Dictionary<Indexer, StateCallback> updates;
  13. private Dictionary<Indexer, Action> leaveStates;
  14. private Indexer switchTo;
  15. private int switchCounter;
  16. public StateMachine(Indexer initialState)
  17. : base(true, false)
  18. {
  19. state = initialState;
  20. enterStates = new Dictionary<Indexer, Action>();
  21. updates = new Dictionary<Indexer, StateCallback>();
  22. leaveStates = new Dictionary<Indexer, Action>();
  23. }
  24. public StateMachine()
  25. : this(default(Indexer))
  26. {
  27. }
  28. public Indexer State
  29. {
  30. get { return state; }
  31. set
  32. {
  33. #if DEBUG
  34. if (!updates.ContainsKey(value))
  35. throw new Exception("StateMachine has entered a state for which callbacks have not been set (you can set them to null for no actions)");
  36. #endif
  37. if (!state.Equals(value))
  38. {
  39. switchCounter = 0;
  40. if (leaveStates[state] != null)
  41. leaveStates[state]();
  42. state = value;
  43. if (enterStates[state] != null)
  44. enterStates[state]();
  45. }
  46. }
  47. }
  48. public void SetCallbacks(Indexer state, StateCallback onUpdate, Action onEnterState = null, Action onLeaveState = null)
  49. {
  50. updates[state] = onUpdate;
  51. enterStates[state] = onEnterState;
  52. leaveStates[state] = onLeaveState;
  53. }
  54. public override void Update()
  55. {
  56. if (switchCounter > 0)
  57. {
  58. switchCounter--;
  59. if (switchCounter == 0)
  60. State = switchTo;
  61. }
  62. if (updates[state] != null)
  63. State = updates[state]();
  64. }
  65. static public implicit operator Indexer(StateMachine<Indexer> s)
  66. {
  67. return s.state;
  68. }
  69. /*
  70. * Switch to the specified state in the specified amount of frames.
  71. * This switch is cancelled if the state is otherwise changed before it is finished.
  72. */
  73. public void DelayedStateChange(Indexer changeTo, int frameDelay)
  74. {
  75. #if DEBUG
  76. if (frameDelay <= 0)
  77. throw new Exception("Frame delay must be larger than zero");
  78. #endif
  79. switchTo = changeTo;
  80. switchCounter = frameDelay;
  81. }
  82. }
  83. }