Legend of the Gold Box... A game written for the LOWREZJAM 2018 game jam
Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

134 lines
3.7KB

  1. from .events import Events
  2. from .nodes import Node
  3. from .time import Time
  4. from .display import Display
  5. class StateMachineError(Exception):
  6. pass
  7. # This is the main, active state (Node).
  8. _ACTIVE_STATE = None
  9. # In some cases, the previous state isn't totally shut down, but temporarily put on hold.
  10. # Only the _render() call will be made on hold states.
  11. _HOLD_STATE = None
  12. # List of all states registered into the State Manager.
  13. _STATE_LIST = []
  14. _TIME = Time()
  15. class StateMachine:
  16. def __init__(self):
  17. pass
  18. def has_node(self, name):
  19. """
  20. Returns true if a Node with the given name has been registered in the State List.
  21. NOTE: This is only going to check the root Node's name, not any other node in the node tree.
  22. """
  23. global _STATE_LIST
  24. for n in _STATE_LIST:
  25. if n.name == name:
  26. return True
  27. return False
  28. def register_node(self, node):
  29. """
  30. """
  31. if not isinstance(node, Node):
  32. raise TypeError("Expected a Node instance.")
  33. # Check if given the root Node. If not, get the root Node.
  34. if node.parent != None:
  35. node = node.root
  36. if self.has_node(node.name):
  37. raise StateMachineError("State machine already registered node named '{}'. Names must be unique.".format(node.name))
  38. global _STATE_LIST
  39. _STATE_LIST.append(node)
  40. def activate_node(self, name, hold_previous=False):
  41. """
  42. """
  43. global _ACTIVE_STATE, _TIME
  44. if self.has_node(name):
  45. if _ACTIVE_STATE is not None:
  46. if _ACTIVE_STATE.name == name:
  47. return
  48. self._releaseActive(hold_previous)
  49. self._setActive(name)
  50. if _ACTIVE_STATE is not None:
  51. _TIME.reset()
  52. def _relaseActive(self, hold_previous):
  53. global _ACTIVE_STATE, _HOLD_STATE
  54. a = _ACTIVE_STATE
  55. a._pause()
  56. if _HOLD_STATE is not None:
  57. _ACTIVE_STATE = _HOLD_STATE
  58. _HOLD_STATE = None
  59. _ACTIVE_STATE._start()
  60. else:
  61. _ACTIVE_STATE = None
  62. if hold_previous == True:
  63. _HOLD_STATE = a
  64. else:
  65. a._close()
  66. def _setActive(self, name):
  67. global _ACTIVE_STATE, _STATE_LIST
  68. for n in _STATE_LIST:
  69. if n.name == name:
  70. _ACTIVE_STATE = n
  71. break
  72. if _ACTIVE_STATE is not None:
  73. _ACTIVE_STATE._init()
  74. _ACTIVE_STATE._start()
  75. elif _HOLD_STATE is not None:
  76. # If we failed to find an Active state, then we need to drop any hold state as well...
  77. # Keep things as clean as possible
  78. _HOLD_STATE._close()
  79. _HOLD_STATE = None
  80. def close(self):
  81. global _ACTIVE_STATE, _HOLD_STATE, _STATE_LIST
  82. if _HOLD_STATE is not None:
  83. _HOLD_STATE._close()
  84. _HOLD_STATE = None
  85. if _ACTIVE_STATE is not None:
  86. _ACTIVE_STATE._pause()
  87. _ACTIVE_STATE._close()
  88. _ACTIVE_STATE = None
  89. _STATE_LIST = []
  90. def update(self):
  91. global _ACTIVE_STATE, _TIME
  92. if _ACTIVE_STATE is not None:
  93. _ACTIVE_STATE._update(_TIME.delta)
  94. def render(self):
  95. global _ACTIVE_STATE, _HOLD_STATE
  96. dsurf = Display.surface
  97. if dsurf is not None:
  98. Display.clear()
  99. # If there's a hold state, render that first.
  100. if _HOLD_STATE is not None:
  101. _HOLD_STATE._render(dsurf)
  102. # Render the active state next so it overdraws the hold state.
  103. if _ACTIVE_STATE is not None:
  104. _ACTIVE_STATE._render(dsurf)
  105. Display.flip()