Legend of the Gold Box... A game written for the LOWREZJAM 2018 game jam
選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。

167 行
6.1KB

  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 ref 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(), "key_name":pygame.key.name(key)})
  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, "key_name":pygame.key.name(event.key)})
  109. elif event.type == pygame.KEYUP:
  110. Events.emit("KEYUP", {"key":event.key, "mod":event.mod, "key_name":pygame.key.name(event.key)})
  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)))