本系列博客介紹以python+pygame庫進行小游戲的開發。有寫的不對之處還望各位海涵。
在上一篇博客中,我們學習了pygame中的IO、數據http://www.cnblogs.com/msxh/p/4973003.html。
這次我們來一起了解一下pygame事件與設備輪詢。
一、pygame事件
1.簡介
pygame事件可以處理游戲中的各種事情。其實在前兩節的博客中,我們已經使用過他們了。如下是pygame的完整事件列表:
QUIT,ACTIVEEVENT,KEYDOWN,KEYDOWN,MOUSEMOTION,MOUSEBUTTONUP,MOUSEBUTTONDOWN,JOYAXISMOTION,
JOYBALLMOTION,JOYHATMOTION........
更多的事件可以去查pygame的文檔。http://www.pygame.org/docs/index.html
查看pygame的文檔是一種非常好的學習方式。
2.實時事件循環
pygame中的事件處理是放在一個實時的循環中來完成的。將代碼都放在一個while True的循環中,但是這樣會造成死循環,所以在里面加一句sys.exit()來退出。
for event in pygame.event.get()
上面的代碼將會創建當前等待處理的事件的一個列表,然后使用for循環來遍歷里面的事件。這樣,我們將會根據事件產生的順序依次地進行不同的操作。常見的事件是按鍵按下,按鍵釋放以及鼠標移動。通常需要最先處理QUIT事件(在用戶關閉窗口的時候會產生該事件。)
while True: for event in pygame.event.get(): if event.type == QUIT: pygame.quit() sys.exit()
3.鍵盤事件
鍵盤事件包括最典型的keyup 和 keydown 當按鍵按下的時候響應KEYDOWN事件,按鍵彈起的時候響應KEYDOWN事件。通常可以設置一個事件變量,然后根據keyup或者keydown給它賦不同的值。
while True: for event in pygame.event.get(): if event.type == QUIT: sys.exit() elif event.type == KEYDOWN: key_flag = True elif event.type == KEYUP: key_flag = False
默認的話pygame不會重復地去響應一個被一直按住的鍵,只是在按鍵第一次被按下的時候響應一次,如果需要重復響應一個按鍵的話下面的操作:
pygame.key.set_repeat(10) #參數是一個以毫秒為單位的值
4.鼠標事件
pygame支持一些鼠標事件,他們包括MOUSEMOTION,MOUSEBUTTONUP,MOUSEBUTTONDOWN.
在MOUSEMOTION中包含了一些屬性:event.pos,event.rel,event.buttons
for event in pygame.event.get(): if event.type == MOUSEMOTION: mouse_x,mouse_y = event.pos move_x,move_y = event.rel
MOUSEBUTTONDOWN里面的屬性:
event.type == MOUSEBUTTONDOWN: mouse_down = event.button mouse_down_x,mouse_down_y = event.pos
MOUSEBUTTONUP里面的屬性:
event.type == MOUSEBUTTONUP: mouse_up = event.button mouse_up_x,mouse_up_y = event.pos
二、設備輪詢
在pygame中除了pygame事件,還可以使用設備輪詢的方法來檢測是否有事件發生。而且在python里面是沒有switch語句的,因此當需要處理的事件過多時,我們肯定不會去一條一條的去寫if...elif....else來匹配,而設備輪詢正好解決了這個棘手的問題。
1.輪詢鍵盤
在pygame中,使用pygame.key.get_pressed()來輪詢鍵盤接口。這個方法會返回布爾值的一個列表,其中每個鍵一個標志。使用鍵常量值來匹配按鍵,這樣的好處就是不必遍歷事件系統就可以檢測多個鍵的按下。例如:
keys = pygame.key.get_pressed() if keys[K_ESCAPE]: pygame.quit() sys.exit()
我們可以設計一個打字測速小游戲來綜合練習一下鍵盤的輪詢:
1 import sys, random, time, pygame 2 from pygame.locals import * 3 4 def print_text(font, x, y, text, color=(255,255,255)): 5 imgText = font.render(text, True, color) 6 screen.blit(imgText, (x,y)) 7 8 9 #主程序 10 pygame.init() 11 screen = pygame.display.set_mode((600,500)) 12 pygame.display.set_caption("Keyboard Demo") 13 font1 = pygame.font.Font(None, 24) 14 font2 = pygame.font.Font(None, 200) 15 white = 255,255,255 16 yellow = 255,255,0 17 color = 125,100,210 18 19 key_flag = False 20 correct_answer = 97 21 seconds = 10 22 score = 0 23 clock_start = 0 24 game_over = True 25 26 while True: 27 for event in pygame.event.get(): 28 if event.type == QUIT: 29 pygame.quit() 30 sys.exit() 31 elif event.type == KEYDOWN: 32 key_flag = True 33 elif event.type == KEYUP: 34 key_flag = False 35 36 keys = pygame.key.get_pressed() 37 if keys[K_ESCAPE]: 38 sys.exit() 39 40 if keys[K_RETURN]: 41 if game_over: 42 game_over = False 43 score = 0 44 seconds = 11 45 clock_start = time.clock() 46 47 current = time.clock() - clock_start 48 speed = score * 6 49 if seconds-current < 0: 50 game_over = True 51 elif current <= 10: 52 if keys[correct_answer]: 53 correct_answer = random.randint(97,122) 54 score += 1 55 56 57 #清屏 58 screen.fill(color) 59 60 print_text(font1, 0, 20, "Try to keep up for 10 seconds...") 61 62 if key_flag: 63 print_text(font1, 450, 0, "you are keying...") 64 65 if not game_over: 66 print_text(font1, 0, 80, "Time: " + str(int(seconds-current))) 67 68 print_text(font1, 0, 100, "Speed: " + str(speed) + " letters/min") 69 70 if game_over: 71 print_text(font1, 0, 160, "Press Enter to start...") 72 73 print_text(font2, 0, 240, chr(correct_answer-32), yellow) 74 75 76 #更新 77 pygame.display.update() 78 79
在這個程序中,我們使用到了一些新的模塊和函數,讓我們來了解一下。
Random.randint(x,y);看名字知道這個函數的作用了,它可以返回一個x~y之間的隨機數。
另外一個模塊是time。time.clock()函數會返回從程序啟動到現在為止的時間。
2.輪詢鼠標
同樣,我們可以使用類似的方法去輪詢鼠標事件。
這里有3個相關的函數:
(1)pygame.mouse.get_pos(),這個函數會返回鼠標當前的坐標x,y;
(2)pygame.mouse.get_rel();
rel_x ,rel_y = pygame.mouse.get_rel().利用這個函數可以讀取鼠標的相對移動。
(3)btn_one,btn_two,btn_three = pygame.mouse.get_pressed();
利用這個函數,可以獲取鼠標按鈕的狀態。比如當左鍵按下的時候btn_one 的值會被賦值為1,鼠標按鍵彈起是會被賦值為0。
同樣我們可以設計一個小案例來熟悉一下鼠標輪詢,比如當鼠標按下的時候 打印鼠標按的是左鍵還是右鍵,鼠標點擊的位置,鼠標當前的坐標等等。這里就不給出實現代碼了,感興趣的可以自己實現一下。
下個博客中我們將會一起學習如何在pygame中加載位圖,以及pygame中一些常用的數學函數。並且還會綜合前幾次學到的知識制作一個小游戲。游戲效果圖如下: