Python tkinter Canvas绘制动画桌面弹球游戏

其实前面程序中的高亮显示已经是动画效果了。程序会用红色、黄色交替显示几何图形的边框,这样看上去就是动画效果了。实现其他动画效果也是这个原理,程序只要增加一个定时器,周期性地改变界面上图形项的颜色、大小、位置等选项,用户看上去就是所谓的“动画”了。

下面以一个简单的桌面弹球游戏来介绍使用 Canvas 绘制动画。在游戏界面上会有一个小球,该小球会在界面上滚动,遇到边界或用户挡板就会反弹。该程序涉及两个动画:

  • 小球转动:小球转动是一个“逐帧动画”,程序会循环显示多张转动的小球图片,这样用户就会看到小球转动的效果。
  • 小球移动:只要改变小球的坐标程序就可以控制小球移动。


为了让用户控制挡板移动,程序还为 Canvas 的向左箭头、向右箭头绑定了事件处理函数。下面是桌面弹球游戏的程序:

 
  1. from tkinter import *
  2. from tkinter import messagebox
  3. import threading
  4. import random
  5. GAME_WIDTH = 500
  6. GAME_HEIGHT = 680
  7. BOARD_X = 230
  8. BOARD_Y = 600
  9. BOARD_WIDTH = 80
  10. BALL_RADIUS = 9
  11. class App:
  12. def __init__(self, master):
  13. self.master = master
  14. # 记录小球动画的第几帧
  15. self.ball_index = 0
  16. # 记录游戏是否失败的旗标
  17. self.is_lose = False
  18. # 初始化记录小球位置的变量
  19. self.curx = 260
  20. self.cury = 30
  21. self.boardx = BOARD_X
  22. self.init_widgets()
  23. self.vx = random.randint(3, 6) # x方向的速度
  24. self.vy = random.randint(5, 10) # y方向的速度
  25. # 通过定时器指定0.1秒之后执行moveball函数
  26. self.t = threading.Timer(0.1, self.moveball)
  27. self.t.start()
  28. # 创建界面组件
  29. def init_widgets(self):
  30. self.cv = Canvas(root, background='white',
  31. width=GAME_WIDTH, height=GAME_HEIGHT)
  32. self.cv.pack()
  33. # 让画布得到焦点,从而可以响应按键事件
  34. self.cv.focus_set()
  35. self.cv.bms = []
  36. # 初始化小球的动画帧
  37. for i in range(8):
  38. self.cv.bms.append(PhotoImage(file='images/ball_' + str(i+1) + '.gif'))
  39. # 绘制小球
  40. self.ball = self.cv.create_image(self.curx, self.cury,
  41. image=self.cv.bms[self.ball_index])
  42. self.board = self.cv.create_rectangle(BOARD_X, BOARD_Y,
  43. BOARD_X + BOARD_WIDTH, BOARD_Y + 20, width=0, fill='lightblue')
  44. # 为向左箭头按键绑定事件,挡板左移
  45. self.cv.bind('', self.move_left)
  46. # 为向右箭头按键绑定事件,挡板右移
  47. self.cv.bind('', self.move_right)
  48. def move_left(self, event):
  49. if self.boardx <= 0:
  50. return
  51. self.boardx -= 5
  52. self.cv.coords(self.board, self.boardx, BOARD_Y,
  53. self.boardx + BOARD_WIDTH, BOARD_Y + 20)
  54. def move_right(self, event):
  55. if self.boardx + BOARD_WIDTH >= GAME_WIDTH:
  56. return
  57. self.boardx += 5
  58. self.cv.coords(self.board, self.boardx, BOARD_Y,
  59. self.boardx + BOARD_WIDTH, BOARD_Y + 20)
  60. def moveball(self):
  61. self.curx += self.vx
  62. self.cury += self.vy
  63. # 小球到了右边墙壁,转向
  64. if self.curx + BALL_RADIUS >= GAME_WIDTH:
  65. self.vx = -self.vx
  66. # 小球到了左边墙壁,转向
  67. if self.curx - BALL_RADIUS <= 0:
  68. self.vx = -self.vx
  69. # 小球到了上边墙壁,转向
  70. if self.cury - BALL_RADIUS <= 0:
  71. self.vy = -self.vy
  72. # 小球到了挡板处
  73. if self.cury + BALL_RADIUS >= BOARD_Y:
  74. # 如果在挡板范围内
  75. if self.boardx <= self.curx <= (self.boardx + BOARD_WIDTH):
  76. self.vy = -self.vy
  77. else:
  78. messagebox.showinfo(title='失败', message='您已经输了')
  79. self.is_lose = True
  80. self.cv.coords(self.ball, self.curx, self.cury)
  81. self.ball_index += 1
  82. self.cv.itemconfig(self.ball, image=self.cv.bms[self.ball_index % 8])
  83. # 如果游戏还未失败,让定时器继续执行
  84. if not self.is_lose:
  85. # 通过定时器指定0.1秒之后执行moveball函数
  86. self.t = threading.Timer(0.1, self.moveball)
  87. self.t.start()
  88. root = Tk()
  89. root.title("弹球游戏")
  90. root.iconbitmap('images/fklogo.ico')
  91. root.geometry('%dx%d' % (GAME_WIDTH, GAME_HEIGHT))
  92. # 禁止改变窗口大小
  93. root.resizable(width=False, height=False)
  94. App(root)
  95. root.mainloop()

上面程序中第 26、27 行代码通过线程启动了一个定时器,该定时器控制 moveball() 方法每隔 0.1 秒执行一次,而 moveball() 方法中通过改变小球的坐标可以实现小球移动的效果;通过改变小球的图片,可以实现小球滚动的效果。

运行上面程序,可以看到如图 1 所示的游戏效果:


Python tkinter Canvas绘制动画桌面弹球游戏_第1张图片
图 1 桌面弹球游戏

你可能感兴趣的:(python)