Legend of the Gold Box... A game written for the LOWREZJAM 2018 game jam
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

167 lines
5.9KB

  1. '''
  2. Filename events.py
  3. Author: Bryan "ObsidianBlk" Miller
  4. Date Created: 8/1/2018
  5. Python Version: 3.7
  6. '''
  7. import time
  8. import weakref
  9. import pygame
  10. def _getWeakRef(fn):
  11. if not hasattr(fn, "__call__"):
  12. return None
  13. if hasattr(fn, "__self__"):
  14. return weakref.WeakMethod(fn)
  15. return weakref.ref(fn)
  16. class EventError(Exception):
  17. pass
  18. class _Events:
  19. def __init__(self):
  20. self._signals = {}
  21. def _ClearUnreferenced(self):
  22. for signal in self._signals:
  23. removal = [s for s in self._signals[signal] if s() is None]
  24. for r in removal:
  25. self._signals[signal].remove(r)
  26. def listen(self, signal, fn):
  27. ref = _getWeakRef(fn)
  28. if ref is None or ref() is None:
  29. raise EventError("Expected a function callback.")
  30. if not signal in self._signals:
  31. self._signals[signal] = []
  32. if not ref in self._signals[signal]:
  33. self._signals[signal].append(ref)
  34. def unlisten(self, signal, fn):
  35. ref = _getWeakRef(fn)
  36. if res is None or ref() is None:
  37. return # Not a function. Nothing to do.
  38. if signal in self._signals:
  39. if ref in self._signals[signal]:
  40. self._signals[signal].remove(ref)
  41. def unlisten_all(self, signal):
  42. if signal in self._signals:
  43. del self._signals[signal]
  44. def emit(self, signal, data):
  45. if signal in self._signals:
  46. for r in self._signals[signal]:
  47. fn = r()
  48. if fn is not None:
  49. fn(signal, data)
  50. self._ClearUnreferenced()
  51. # Create the actual Events instance :)
  52. Events = _Events()
  53. _ClickDelayMax=500 # in Milliseconds
  54. _DOWNKEYS=[]
  55. _DOWNMBUTTONS=[]
  56. _DOWNJBUTTONS=[]
  57. def _WatchKey(key):
  58. global _DOWNKEYS
  59. for k in _DOWNKEYS:
  60. if k[0] == key:
  61. return # Already watching. Technically, this should never happen.
  62. _DOWNKEYS.append((key, int(round(time.time()*1000))))
  63. def _ReleaseKey(key):
  64. global _DOWNKEYS, _ClickDelayMax
  65. tick = int(round(time.time()*1000))
  66. for k in _DOWNKEYS:
  67. if k[0] == key:
  68. lastTick = k[1]
  69. _DOWNKEYS.remove(k)
  70. if tick - lastTick <= _ClickDelayMax:
  71. Events.emit("KEYPRESSED", {"key":key, "mod":pygame.key.get_mods()})
  72. return # Done.
  73. # We found nothing, boss.
  74. def _WatchButton(device, button):
  75. global _DOWNMBUTTONS, _DOWNJBUTTONS
  76. tick = int(round(time.time()*1000))
  77. btnsrc = _DOWNMBUTTONS
  78. if device >= 0:
  79. btnsrc = _DOWNJBUTTONS
  80. for b in btnsrc:
  81. if b[0] == device and b[1] == button:
  82. return # Already Watching...
  83. btnsrc.append((device, button, tick))
  84. def _ReleaseButton(device, button):
  85. global _DOWNMBUTTONS, _DOWNJBUTTONS, _ClickDelayMax
  86. tick = int(round(time.time()*1000))
  87. btnsrc = _DOWNMBUTTONS
  88. if device >= 0:
  89. btnsrc = _DOWNJBUTTONS
  90. for b in btnsrc:
  91. if b[0] == device and b[1] == button:
  92. lastTick = b[2]
  93. btnsrc.remove(b)
  94. if tick - lastTick <= _ClickDelayMax:
  95. if device >= 0:
  96. Events.emit("JOYBUTTONPRESSED", {"joy":device, "button":button})
  97. else:
  98. Events.emit("MOUSEBUTTONPRESSED", {"pos":pygame.mouse.get_pos(), "button":button})
  99. return # Done.
  100. # We found nothing, boss.
  101. def pollEmitter():
  102. global Events, _WatchKey, _ReleaseKey, _WatchButton, _ReleaseButton
  103. for event in pygame.event.get():
  104. if event.type == pygame.QUIT:
  105. Events.emit("QUIT", {})
  106. elif event.type == pygame.KEYDOWN:
  107. _WatchKey(event.key)
  108. Events.emit("KEYDOWN", {"unicode":event.unicode, "key":event.key, "mod":event.mod})
  109. elif event.type == pygame.KEYUP:
  110. Events.emit("KEYUP", {"key":event.key, "mod":event.mod})
  111. _ReleaseKey(event.key)
  112. elif event.type == pygame.MOUSEMOTION:
  113. Events.emit("MOUSEMOTION", {"pos":event.pos, "rel":event.rel, "buttons":event.buttons})
  114. elif event.type == pygame.MOUSEBUTTONUP:
  115. Events.emit("MOUSEBUTTONUP", {"pos":event.pos, "button":event.button})
  116. _ReleaseButton(-1, event.button)
  117. elif event.type == pygame.MOUSEBUTTONDOWN:
  118. _WatchButton(-1, event.button)
  119. Events.emit("MOUSEBUTTONDOWN", {"pos":event.pos, "button":event.button})
  120. elif event.type == pygame.VIDEORESIZE:
  121. # NOTE: There is a resize bug in Linux. This will stop working after a short time. Grrr
  122. Events.emit("VIDEORESIZE", {"size":event.size, "w":event.w, "h":event.h})
  123. elif event.type == pygame.VIDEOEXPOSE:
  124. Events.emit("VIDEOEXPOSE", {})
  125. elif event.type == pygame.JOYAXISMOTION:
  126. Events.emit("JOYAXISMOTION", {"joy":event.joy, "axis":event.axis, "value":event.value})
  127. elif event.type == pygame.JOYBALLMOTION:
  128. Events.emit("JOYBALLMOTION", {"joy":event.joy, "ball":event.ball, "res":event.rel})
  129. elif event.type == pygame.JOYHATMOTION:
  130. Events.emit("JOYHATMOTION", {"joy":event.joy, "hat":event.hat, "value":event.value})
  131. elif event.type == pygame.JOYBUTTONUP:
  132. Events.emit("JOYBUTTONUP", {"joy":event.joy, "button":event.button})
  133. _ReleaseButton(event.joy, event.button)
  134. elif event.type == pygame.JOYBUTTONDOWN:
  135. _WatchButton(event.joy, event.button)
  136. Events.emit("JOYBUTTONDOWN", {"joy":event.joy, "button":event.button})
  137. elif event.type == pygame.ACTIVEEVENT:
  138. if event.state == 1:
  139. if event.gain == 0:
  140. Events.emit("FOCUSLOST", {})
  141. elif event.gain == 1:
  142. Events.emit("FOCUSGAINED", {})
  143. else:
  144. if hasattr(event, "code"):
  145. Events.emit("PYGUSER_{}".format(event.code), {})
  146. else:
  147. print("Unkown pygame event type '{}'".format(pygame.event.event_name(event.type)))