Legend of the Gold Box... A game written for the LOWREZJAM 2018 game jam
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

153 lines
5.2KB

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