Guest User

Untitled

a guest
Jan 18th, 2019
87
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 7.68 KB | None | 0 0
  1. import tkinter as tk
  2.  
  3.  
  4. class Shape:
  5.  
  6. def __init__(self, x, y, width, height, center=False):
  7. if center:
  8. x -= width // 2
  9. y -= height // 2
  10. self.x1 = x
  11. self.y1 = y
  12. self.x2 = x + width
  13. self.y2 = y + height
  14.  
  15.  
  16. class Paddle(Shape):
  17.  
  18. def __init__(self, x, y, width=45, height=8, speed=6, color="blue"):
  19. super().__init__(x, y, width, height, center=True)
  20. self.speed = speed
  21. self.color = color
  22. self.name = "paddle"
  23.  
  24. def right(self, event):
  25. self.x1 += self.speed
  26. self.x2 += self.speed
  27.  
  28. def left(self, event):
  29. self.x1 -= self.speed
  30. self.x2 -= self.speed
  31.  
  32. def move(self):
  33. pass
  34.  
  35. def limit(self, area):
  36. adjust = (max(self.x1, area.x1) - self.x1 or
  37. min(self.x2, area.x2) - self.x2)
  38. self.x1 += adjust
  39. self.x2 += adjust
  40.  
  41.  
  42. class Ball(Shape):
  43.  
  44. def __init__(self, x, y, size=10, dx=2, dy=2, color="red"):
  45. super().__init__(x, y, size, size, center=True)
  46. self.dx = dx
  47. self.dy = dy
  48. self.color = color
  49. self.name = "ball"
  50.  
  51. def move(self):
  52. self.x1 += self.dx
  53. self.y1 += self.dy
  54. self.x2 += self.dx
  55. self.y2 += self.dy
  56.  
  57. def limit(self, area):
  58. if self.x1 <= area.x1 or area.x2 <= self.x2:
  59. self.dx *= -1
  60. if self.y1 <= area.y1 or area.y2 <= self.y2:
  61. self.dy *= -1
  62.  
  63. def bound(self, target):
  64. hit_x = max(self.x1, target.x1) <= min(self.x2, target.x2)
  65. hit_y = max(self.y1, target.y1) <= min(self.y2, target.y2)
  66. if not (hit_x and hit_y):
  67. return False
  68. center_x = (self.x1 + self.x2) // 2
  69. center_y = (self.y1 + self.y2) // 2
  70. if (self.dx > 0 and center_x <= target.x1 or
  71. self.dx < 0 and target.x2 <= center_x):
  72. self.dx *= -1
  73. if (self.dy > 0 and center_y <= target.y1 or
  74. self.dy < 0 and target.y2 <= center_y):
  75. self.dy *= -1
  76. return True
  77.  
  78.  
  79. class Block(Shape):
  80.  
  81. def __init__(self, x, y, width, height, gap_x=0, gap_y=0, center=False,
  82. color="orange", point=1):
  83. super().__init__(x + gap_x, y + gap_y,
  84. width - gap_x * 2, height - gap_y * 2, center=center)
  85. self.point = point
  86. self.color = color
  87. self.name = f"block{x}.{y}"
  88. self.exists = True
  89.  
  90. def break_and_bound(self, target):
  91. if self.exists and target.bound(self):
  92. self.exists = False
  93. return self.point
  94. else:
  95. return 0
  96.  
  97. def is_broken(self):
  98. return not self.exists
  99.  
  100.  
  101. class BlockRow:
  102. def __init__(self, color, point):
  103. self.color = color
  104. self.point = point
  105.  
  106.  
  107. class Blocks:
  108. #ROWS = [BlockRow("orange", 1)] * 3
  109. ROWS = BlockRow("cyan", 10), BlockRow("yellow", 20), BlockRow("orange", 30)
  110.  
  111. def __init__(self, x, y, width, height, columns=12, rows=None):
  112. rows = (rows or self.ROWS)[::-1]
  113. w = width // columns
  114. h = height // len(rows)
  115. self.blocks = [Block(x + dx, y + dy, w, h, gap_x=6, gap_y=12,
  116. color=row.color, point=row.point)
  117. for dy, row in zip(range(0, h * len(rows) + 1, h), rows)
  118. for dx in range(0, w * columns + 1, w)]
  119.  
  120. def __iter__(self):
  121. return iter(self.blocks)
  122.  
  123. def break_and_bound(self, target):
  124. return sum(block.break_and_bound(target) for block in self.blocks)
  125.  
  126. def are_wiped(self):
  127. return all(block.is_broken() for block in self.blocks)
  128.  
  129.  
  130. class Wall(Shape):
  131. CATCH_LINES = 3
  132.  
  133. def __init__(self, x, y, width, height):
  134. super().__init__(x, y, width, height)
  135. self.catch_line = self.y2 - self.CATCH_LINES
  136.  
  137. def catch(self, target):
  138. return target.y2 >= self.catch_line
  139.  
  140.  
  141. class Score:
  142.  
  143. def __init__(self, x, y):
  144. self.x = x
  145. self.y = y
  146. self.score = 0
  147. self.name = "score"
  148.  
  149. def __str__(self):
  150. return str(self.score)
  151.  
  152. def add(self, point):
  153. self.score += point
  154.  
  155.  
  156. class BreakoutModel:
  157.  
  158. def __init__(self, width, height):
  159. self.paddle = Paddle(width // 2, height - 30)
  160. self.ball = Ball(width // 3, height * 2 // 3)
  161. self.blocks = Blocks(0, 40, width, 120)
  162. self.wall = Wall(0, 0, width, height)
  163. self.score = Score(width - 70, 20)
  164. self.message = None
  165.  
  166. def update(self):
  167. self.paddle.move()
  168. self.paddle.limit(self.wall)
  169. self.ball.move()
  170. self.ball.limit(self.wall)
  171. self.ball.bound(self.paddle)
  172. point = self.blocks.break_and_bound(self.ball)
  173. self.score.add(point)
  174. self.over()
  175. self.clear()
  176.  
  177. def over(self):
  178. self.message = self.wall.catch(self.ball) and "GAME OVER(T_T)"
  179.  
  180. def clear(self):
  181. self.message = self.blocks.are_wiped() and "GAME CLEAR(^0^)"
  182.  
  183.  
  184. class BreakoutView:
  185. SCORE_FONT = ('FixedSys', 16)
  186. MESSAGE_FONT = ('FixedSys', 40)
  187.  
  188. def __init__(self, window, width, height):
  189. self.canvas = tk.Canvas(window, width=width, height=height)
  190. self.center = (width // 2, height // 2)
  191. window.title("ブロック崩し")
  192. window.minsize(width, height)
  193. window.maxsize(width, height)
  194. self.draw_rectangle = self.canvas.create_rectangle
  195. self.draw_oval = self.canvas.create_oval
  196. self.draw_text = self.canvas.create_text
  197.  
  198. def update(self, model):
  199. self.ball(model.ball)
  200. self.paddle(model.paddle)
  201. self.blocks(model.blocks)
  202. self.score(model.score)
  203. self.message(model.message)
  204. self.canvas.pack()
  205.  
  206. def delete(self, model):
  207. self.canvas.delete(model.name)
  208.  
  209. def paddle(self, paddle):
  210. self.delete(paddle)
  211. self.draw_rectangle(paddle.x1, paddle.y1, paddle.x2, paddle.y2,
  212. fill=paddle.color, tag=paddle.name)
  213.  
  214. def ball(self, ball):
  215. self.delete(ball)
  216. self.draw_oval(ball.x1, ball.y1, ball.x2, ball.y2,
  217. fill=ball.color, tag=ball.name)
  218.  
  219. def blocks(self, blocks):
  220. for block in blocks:
  221. self.delete(block)
  222. if block.exists:
  223. self.draw_rectangle(block.x1, block.y1, block.x2, block.y2,
  224. fill=block.color, tag=block.name)
  225.  
  226. def score(self, score):
  227. self.delete(score)
  228. self.draw_text(score.x, score.y, text=f"Score = {score}",
  229. font=self.SCORE_FONT, tag=score.name)
  230.  
  231. def message(self, message):
  232. if message:
  233. self.draw_text(*self.center, text=message, font=self.MESSAGE_FONT)
  234.  
  235.  
  236. class Breakout:
  237. TICK = 20 # 更新間隔
  238.  
  239. def __init__(self, width, height):
  240. self.controller = window = tk.Tk()
  241. self.model = BreakoutModel(width, height)
  242. self.view = BreakoutView(window, width, height)
  243. self.view.update(self.model)
  244. self.keybind()
  245.  
  246. def keybind(self):
  247. self.controller.bind("q", self.controller.quit)
  248. self.controller.bind("<Right>", self.model.paddle.right)
  249. self.controller.bind("<Left>", self.model.paddle.left)
  250.  
  251. def start(self):
  252. self.update()
  253. try:
  254. self.controller.mainloop()
  255. except KeyboardInterrupt:
  256. self.controller.quit()
  257.  
  258. def update(self):
  259. try:
  260. if self.model.message:
  261. input("Hit return key to end")
  262. self.controller.quit()
  263. else:
  264. self.model.update()
  265. self.view.update(self.model)
  266. self.controller.after(self.TICK, self.update)
  267. except KeyboardInterrupt:
  268. self.controller.quit()
  269.  
  270.  
  271. if __name__ == '__main__':
  272. Breakout(width=600, height=480).start()
Add Comment
Please, Sign In to add comment