python庫tkinter、pygame中幾點需要注意的問題


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

https://github.com/nishilv2


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM