移動矩形代碼和一個非常重要的windows消息隊列機制的坑

今天跟着S.Harbour的書寫了第一個例程,一開始沒打算一章章認真碼,沒想到卻遇上了不少問題,收穫不菲,這對接下來也是一個非常好的提醒,要腳踏實地


,不能“感覺”自己會了就不看
import pygame  
from pygame.locals import * 
import sys 
pygame.init()  #導入模塊並初始化  
screen=pygame.display.set_mode((600, 500))  #創建並設置一個叫圖像窗口的surface對象。名叫screen 
pygame.display.set_caption("Drawing Rectangles") 

position_x=0
position_y=0
velocity_x=1
velocity_y=2

while True:  
    for event in pygame.event.get():
        if event.type in (QUIT,KEYDOWN):
            quit()  
            sys.exit()  
            #退出的消息處理   
    screen.fill((0,0,200))        
    position_x=position_x+velocity_x
    position_y=position_y+velocity_y
 
    if position_x>500 or position_x<0:
            velocity_x=-velocity_x
    if position_y>400 or position_y<0:
            velocity_y=-velocity_y
    color=255,255,0
    position=position_x,position_y,100,100           
            
    pygame.draw.rect(screen,color,position,0)
    pygame.display.update()  
#    #刷新一下畫面  

以上是結果代碼。
出現在的問題主要有以下幾點:
1.sys模塊應該是一個內置模塊,所以不import直接使用sys.exit()也不會報錯。而且沒有quit()只會在調試的時候崩潰,直接運行不會
2.from XXX import * 可以直接導入命名空間,但是編譯器會一直warn你說某一些變量可能未定義或者定義在這個XXX裏,意思是讓你自己注意,自己檢查檢查
。這個只要無視就好。而pygame的locals官網的描述是裏面定義了大量的常量。我們這裏使用的QUIT和KEYDOWN就是鍵值常量。我嘗試過用pygame.locals.QUIT
但最後會報錯,所以我只能無視這個warning
3.spder編譯器通過點操作有時候是看不到一個對象完整的,所有的屬性和方法的。這個就很無語。只能自己翻翻手冊和書才能知道,這裏的display和screen裏
的屬性和方法就看不到。之前也出現很多這類情況
4.也是今天最重要的一點。一開始我寫的程序。矩形只有在我給消息的情況下,比如移動鼠標,點擊鼠標等情況下才會移動。而例程運行後卻可以自動移動。後
來我發現這是因爲我把繪圖的程序放在了和if event.type in (QUIT,KEYDOWN):對齊的地方。當我把下面的繪圖程序和for event in pygame.event.get():放對
齊的時候就可以自動運動了。這是一個很致命的錯誤。因爲涉及到了windows處理消息的機制。windows不是實時處理消息的,一次性處理掉之前堆積起來的消息
隊列,然後繼續順序執行下面的繪圖和邏輯判斷。在運行下面程序的同時,硬件卻在實時的檢測鼠標和鍵盤的動向,然後把這些消息放進內存的一個隊列中形成
消息隊列。這是一種典型的用緩衝區的方法去解決不同步的問題。等到程序運行到底部,重新再一次進入while循環後,就會又進入到處理消息隊列的那個for循
環裏處理消息(不然怎麼會有專門的函數刪除消息隊列裏的某個消息呢,這樣就徹底理解了消息處理的機制)。所以當我把他寫在for循環對齊的時候,那麼當有消息時,先進入for循環,用if處理完消息後,就會跳出到下面的繪圖程序。當沒消息時,直接for循環就跳出了,也出來執行繪圖程序。但是!當寫在和if event.type in (QUIT,KEYDOWN):對齊的時候,當有消息的時候還好,他會進入for循環,判斷完是不是QUIT和KEYDOWN,然後執行你的一遍繪圖。但是沒消息的時候。for裏的event in pygame.event.get():是沒有的,於是乎,程序直接跳到外面了,根本不會進去執行if event.type in (QUIT,KEYDOWN):和繪圖的代碼塊。所以結論就是。對於有沒有消息都要處理的代碼,要放在for循環裏面。對於有消息才執行的代碼,纔要放在for裏面自己消息if語句對應的下面。對於有消息就執行,不在乎你是什麼消息的代碼,就放在for裏面,if外面。因爲python是沒有括號只有靠對齊來區分代碼的  所以要尤爲注意這個問題
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章