恍然之間已經16年快四月份了,已經好久都沒有寫過東西了。。
最近在用python做一些小的游戲,在網上找了一些Python庫,Python中游戲編程最常用的還是pygame了,其次是Tkinter
pygame的話是專門用來寫一些小的游戲的庫,非常好用。
這里想說的主要是關於他的事件處理,在pygame中他的事件處理主要通過一個事件隊列進行處理。
while True: screen.blit(image_board, (0, 0)) for event in pygame.event.get(): if event.type == QUIT: exit() if event.type == MOUSEBUTTONDOWN: mouse_position = pygame.mouse.get_pos() world.answer_mouse(mouse_position) world.render() pygame.display.update()
這里是一個小的demo中主程序中的一部分,整體通過一個while死循環,在死循環中通過update函數進行不斷的畫面更新,並且在獲取事件時,通過for循環遍歷事件隊列,這里用的是get函數,另外還有wait函數,這其中的區別可以從字面上去理解,wait是要通過等待一個事件產生后進行處理,可能會有卡頓的感覺
這里我是要處理鼠標的點擊事件,很明顯get函數的效果要更好,wait函數的適用范圍,我也不是很了解
這里可以看到,如果使用pygame的話是要通過自己聲明的while死循環,顯示的進行事件的處理與畫面的更新
另外,關於Tkinter庫,他主要用來進行GUI的繪制,但其實也不是非常好用,但功能上還是挺全面的。前兩天看到網上有人寫關於貪食蛇的小的demo,但切入的角度主要的算法,自己對算法還是不怎么在行,主要就說下關於Tkinter中進行游戲編寫的一些問題
tk = Tk() def start(): snake_game = SnakeGame(tk, 500) tk.mainloop() class SnakeGame(object): def __init__(self, tk, speed): self.food = (randint(0, 20), randint(0, 20)) self.speed = speed self.snake = Snake() self.tk = tk self.button = Button(tk, text="start game!", command=self.run) self.canvas = Canvas(tk, width=410, height=410, bg="black") self.button.pack() self.canvas.pack() self.tk.bind("<KeyPress-Up>", self.up_event) self.tk.bind("<KeyPress-Down>", self.down_event) self.tk.bind("<KeyPress-Right>", self.right_event) self.tk.bind("<KeyPress-Left>", self.left_event) def run(self): if self.snake.eat(self.food): eat_flag = 1 self.food = None else: eat_flag = 0 self.snake.move(eat_flag) if self.not_over(): self.canvas.delete("all") self.draw_food() self.draw_snake() self.tk.after(self.speed, self.run) else: r = tkMessageBox.showinfo("Oh,game over!") if r == "ok": sys.exit()
這里是自己前兩天寫貪食蛇小的demo的部分程序,用的是Tkinter,其中並沒有發現有顯示的while主循環,但在主程序中出現了一個mainloop的函數,同時在Snake類的run方法里有tk.after的函數
在Tkinter中如果要進行畫面的繪制要通過Tk.canvas進行繪制,但如果要進行畫面的時刻更新則要通過tk.after()函數
這個函數接受兩個參數,第一個是經過多少毫秒執行,第二個是想要執行的函數名
這里一定要注意一個問題,第二個參數最好不要加括號,就是寫成self.run,而不是self.run(),開始時筆者是加括號的,但是程序一直無法運行,顯示遞歸超出范圍,在網上查了下,Python的遞歸是有深度限制的,大概900多。但如果去掉(),就沒有這樣的問題,是不是類似於javascript中的函數立即執行的方式
第二點要注意的是,要在你要執行的函數底部加上tk.after()函數,不能只在主函數中調用after函數,這樣只會執行一次。
另外,在Tkinter中對於事件的處理是要通過綁定到界面來進行的,類似於SnakeGame.__init__(),將KeyPress事件通過bind函數綁定到tk上,再通過mainloop主循環進行事件的處理,但同時mainloop循環也控制着Tkinter整個窗口的生命周期,即如果不執行mainloop循環,Tkinter窗口會關閉,即使有tk.after()函數的執行。
即mainloop函數中有着事件處理的循環和Tkinter窗口生命周期的控制
總體來看編寫游戲上,還是pygame的條理更為清晰一些,更好用一些
下面是筆者的github地址,有一些小的demo和以前做電賽的程序