恍然之間已經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和以前做電賽的程序
