Python RGB Matrix games and animations https://www.xythobuz.de/ledmatrix_v2.html
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.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. #!/usr/bin/env python3
  2. # ----------------------------------------------------------------------------
  3. # "THE BEER-WARE LICENSE" (Revision 42):
  4. # <xythobuz@xythobuz.de> wrote this file. As long as you retain this notice
  5. # you can do whatever you want with this stuff. If we meet some day, and you
  6. # think this stuff is worth it, you can buy me a beer in return. Thomas Buck
  7. # ----------------------------------------------------------------------------
  8. from scroll import ScrollText
  9. import time
  10. import random
  11. import math
  12. class Breakout:
  13. def __init__(self, g, i, ts = 0.1, to = 60.0):
  14. self.gui = g
  15. self.input = i
  16. self.timestep = ts
  17. self.timeout = to
  18. self.paddle_width = 9
  19. self.winText = ScrollText(self.gui, "You Won!", "uushi",
  20. 2, 50, (0, 255, 0))
  21. self.loseText = ScrollText(self.gui, "Game Over!", "uushi",
  22. 2, 50, (255, 0, 0))
  23. self.scoreText = ScrollText(self.gui, "Score:", "uushi",
  24. 2, 50, (255, 255, 255))
  25. random.seed()
  26. self.restart()
  27. def place(self):
  28. self.player = int(self.gui.width / 2)
  29. self.ball = [
  30. self.player, # x
  31. self.gui.height - 2, # y
  32. 1, # v x
  33. -1, # v y
  34. ]
  35. def restart(self):
  36. self.start = time.time()
  37. self.last = time.time()
  38. self.lives = 3
  39. self.score = 0
  40. self.direction = ""
  41. self.data = [[(0, 0, 0) for y in range(self.gui.height)] for x in range(self.gui.width)]
  42. for x in range(self.gui.width - 2):
  43. for y in range(5):
  44. self.data[x + 1][y] = (0, 255, 0)
  45. self.place()
  46. self.old_keys = {
  47. "left": False,
  48. "right": False,
  49. "up": False,
  50. "down": False,
  51. "a": False,
  52. "b": False,
  53. "x": False,
  54. "y": False,
  55. "l": False,
  56. "r": False,
  57. "start": False,
  58. "select": False,
  59. }
  60. def finished(self):
  61. if self.input == None:
  62. # backup timeout for "AI"
  63. if (time.time() - self.start) >= self.timeout:
  64. return True
  65. if self.lives < 0:
  66. # game over screen
  67. return self.scoreText.finished()
  68. return False
  69. def buttons(self):
  70. keys = self.input.get()
  71. if keys["left"] and (not self.old_keys["left"]) and (not self.old_keys["select"]):
  72. self.direction = "l"
  73. elif keys["right"] and (not self.old_keys["right"]) and (not self.old_keys["select"]):
  74. self.direction = "r"
  75. elif (keys["select"] and keys["start"] and (not self.old_keys["start"])) or (keys["start"] and keys["select"] and (not self.old_keys["select"])):
  76. self.restart()
  77. self.old_keys = keys.copy()
  78. def step(self):
  79. # TODO check for collisions with pieces
  80. # move ball
  81. self.ball[0] += self.ball[2]
  82. self.ball[1] += self.ball[3]
  83. # check for collision with left wall
  84. if self.ball[0] <= 0:
  85. self.ball[2] = -self.ball[2]
  86. # check for collision with right wall
  87. if self.ball[0] >= self.gui.width - 1:
  88. self.ball[2] = -self.ball[2]
  89. # check for collision with ceiling
  90. if self.ball[1] <= 0:
  91. self.ball[3] = -self.ball[3]
  92. # check for collision with paddle
  93. if (self.ball[1] == self.gui.height - 2) and (self.ball[0] >= (self.player - int(self.paddle_width / 2))) and (self.ball[0] <= (self.player + int(self.paddle_width / 2))):
  94. # TODO angle
  95. self.ball[3] = -self.ball[3]
  96. # check for collision with floor
  97. if self.ball[1] >= self.gui.height - 1:
  98. self.place()
  99. self.lives -= 1
  100. def finishedEndScreen(self):
  101. if self.score >= self.gui.width * self.gui.height:
  102. return self.winText.finished()
  103. else:
  104. return self.loseText.finished()
  105. def drawEndScreen(self):
  106. if self.score >= self.gui.width * self.gui.height:
  107. self.winText.draw()
  108. else:
  109. self.loseText.draw()
  110. def drawScoreScreen(self):
  111. self.scoreText.draw()
  112. def draw(self):
  113. if self.input != None:
  114. self.buttons()
  115. else:
  116. # TODO "AI"
  117. pass
  118. if self.lives < 0:
  119. if self.finishedEndScreen():
  120. self.drawScoreScreen()
  121. else:
  122. self.drawEndScreen()
  123. self.scoreText.restart()
  124. return
  125. if self.direction == "l":
  126. self.player = max(self.player - 1, 0)
  127. elif self.direction == "r":
  128. self.player = min(self.player + 1, self.gui.width - 1)
  129. self.direction = ""
  130. now = time.time()
  131. if (now - self.last) >= self.timestep:
  132. self.last = now
  133. self.step()
  134. if self.lives < 0:
  135. self.scoreText.setText("Score: " + str(self.score), "uushi")
  136. self.winText.restart()
  137. self.loseText.restart()
  138. self.scoreText.restart()
  139. for x in range(0, self.gui.width):
  140. for y in range(0, self.gui.height):
  141. self.gui.set_pixel(x, y, self.data[x][y])
  142. for x in range(0, self.paddle_width):
  143. self.gui.set_pixel(x + self.player - int(self.paddle_width / 2), self.gui.height - 1, (255, 255, 255))
  144. self.gui.set_pixel(self.ball[0], self.ball[1], (255, 0, 0))
  145. if __name__ == "__main__":
  146. import util
  147. # Need to import InputWrapper before initializing RGB Matrix on Pi
  148. i = util.getInput()
  149. t = util.getTarget(i)
  150. d = Breakout(t, i)
  151. util.loop(t, d.draw)