其實前面程序中的高亮顯示已經是動畫效果了。程序會用紅色、黃色交替顯示幾何圖形的邊框,這樣看上去就是動畫效果了。實現其他動畫效果也是這個原理,程序只要增加一個定時器,周期性地改變界面上圖形項的顏色、大小、位置等選項,用戶看上去就是所謂的“動畫”了。
下面以一個簡單的桌面彈球游戲來介紹使用 Canvas 繪制動畫。在游戲界面上會有一個小球,該小球會在界面上滾動,遇到邊界或用戶擋板就會反彈。該程序涉及兩個動畫:
- 小球轉動:小球轉動是一個“逐幀動畫”,程序會循環顯示多張轉動的小球圖片,這樣用戶就會看到小球轉動的效果。
- 小球移動:只要改變小球的坐標程序就可以控制小球移動。
為了讓用戶控制擋板移動,程序還為 Canvas 的向左箭頭、向右箭頭綁定了事件處理函數。下面是桌面彈球游戲的程序:
?
- from tkinter import *
- from tkinter import messagebox
- import threading
- import random
- GAME_WIDTH = 500
- GAME_HEIGHT = 680
- BOARD_X = 230
- BOARD_Y = 600
- BOARD_WIDTH = 80
- BALL_RADIUS = 9
- class App:
- def __init__(self, master):
- self.master = master
- # 記錄小球動畫的第幾幀
- self.ball_index = 0
- # 記錄游戲是否失敗的旗標
- self.is_lose = False
- # 初始化記錄小球位置的變量
- self.curx = 260
- self.cury = 30
- self.boardx = BOARD_X
- self.init_widgets()
- self.vx = random.randint(3, 6) # x方向的速度
- self.vy = random.randint(5, 10) # y方向的速度
- # 通過定時器指定0.1秒之后執行moveball函數
- self.t = threading.Timer(0.1, self.moveball)
- self.t.start()
- # 創建界面組件
- def init_widgets(self):
- self.cv = Canvas(root, background='white',
- width=GAME_WIDTH, height=GAME_HEIGHT)
- self.cv.pack()
- # 讓畫布得到焦點,從而可以響應按鍵事件
- self.cv.focus_set()
- self.cv.bms = []
- # 初始化小球的動畫幀
- for i in range(8):
- self.cv.bms.append(PhotoImage(file='images/ball_' + str(i+1) + '.gif'))
- # 繪制小球
- self.ball = self.cv.create_image(self.curx, self.cury,
- image=self.cv.bms[self.ball_index])
- self.board = self.cv.create_rectangle(BOARD_X, BOARD_Y,
- BOARD_X + BOARD_WIDTH, BOARD_Y + 20, width=0, fill='lightblue')
- # 為向左箭頭按鍵綁定事件,擋板左移
-
self.cv.bind('
', self.move_left) - # 為向右箭頭按鍵綁定事件,擋板右移
-
self.cv.bind('
', self.move_right) - def move_left(self, event):
- if self.boardx <= 0:
- return
- self.boardx -= 5
- self.cv.coords(self.board, self.boardx, BOARD_Y,
- self.boardx + BOARD_WIDTH, BOARD_Y + 20)
- def move_right(self, event):
- if self.boardx + BOARD_WIDTH >= GAME_WIDTH:
- return
- self.boardx += 5
- self.cv.coords(self.board, self.boardx, BOARD_Y,
- self.boardx + BOARD_WIDTH, BOARD_Y + 20)
- def moveball(self):
- self.curx += self.vx
- self.cury += self.vy
- # 小球到了右邊墻壁,轉向
- if self.curx + BALL_RADIUS >= GAME_WIDTH:
- self.vx = -self.vx
- # 小球到了左邊墻壁,轉向
- if self.curx - BALL_RADIUS <= 0:
- self.vx = -self.vx
- # 小球到了上邊墻壁,轉向
- if self.cury - BALL_RADIUS <= 0:
- self.vy = -self.vy
- # 小球到了擋板處
- if self.cury + BALL_RADIUS >= BOARD_Y:
- # 如果在擋板范圍內
- if self.boardx <= self.curx <= (self.boardx + BOARD_WIDTH):
- self.vy = -self.vy
- else:
- messagebox.showinfo(title='失敗', message='您已經輸了')
- self.is_lose = True
- self.cv.coords(self.ball, self.curx, self.cury)
- self.ball_index += 1
- self.cv.itemconfig(self.ball, image=self.cv.bms[self.ball_index % 8])
- # 如果游戲還未失敗,讓定時器繼續執行
- if not self.is_lose:
- # 通過定時器指定0.1秒之后執行moveball函數
- self.t = threading.Timer(0.1, self.moveball)
- self.t.start()
- root = Tk()
- root.title("彈球游戲")
- root.iconbitmap('images/fklogo.ico')
- root.geometry('%dx%d' % (GAME_WIDTH, GAME_HEIGHT))
- # 禁止改變窗口大小
- root.resizable(width=False, height=False)
- App(root)
- root.mainloop()
上面程序中第 26、27 行代碼通過線程啟動了一個定時器,該定時器控制 moveball() 方法每隔 0.1 秒執行一次,而 moveball() 方法中通過改變小球的坐標可以實現小球移動的效果;通過改變小球的圖片,可以實現小球滾動的效果。
運行上面程序,可以看到如圖 1 所示的游戲效果:
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
