2013-09-23 74 views
0

這裏是我的check_for_pause()函數:爲什麼我的暫停系統不工作? (pygame的)

#Check if the user is trying to pause the game 
def check_for_pause(): 
    keys=pygame.key.get_pressed() #Get status of all keys 
    if keys[K_SPACE]: #The space bar is held down 
     global paused #Make global so it can be edited 
     if paused==True: #It was paused, so unpause it 
      paused=False 
     elif paused==False: #It was playing, so pause it 
      paused=True 

     #Don't let the main loop continue until the space bar has been released again, otherwise the variable will flicker between True and False where the loop runs so fast! 
     space_bar_pressed=keys[K_SPACE] 
     while space_bar_pressed: #Repeat this loop until space_bar_pressed is False 
      keys=pygame.key.get_pressed() 
      if not keys[K_SPACE]: #Space bar has been released so set space_bar_pressed to False 
       space_bar_pressed=False 

然而,這一直讓我的程序無響應每當我試圖暫停!基本上,我希望變量「paused」爲True或False。當按下空格鍵時,它應該更改爲當前不在的那個。因爲我在另一個永無止境的循環中使用了check_for_pause(),所以我需要這樣做,以便函數只在空格鍵釋放時才停止執行,否則如果用戶將空格鍵保留一秒以上,它將會繼續在True和False之間切換。

任何想法爲什麼我的程序在運行時無響應?我知道這是關於等待空格鍵被釋放的位,因爲當我刪除那段代碼時,我的程序運行正常(但顯然暫停功能不起作用)。

+1

是否有你不使用事件隊列的原因?當按下某個鍵時,該鍵的一個* single *事件將被髮送到隊列,這與釋放時相同。使用隊列將確保您的暫停切換僅觸發一次。 –

+0

「但是,當我試圖暫停時,這會使我的程序無法響應!」那當然是的。你正在運行一個循環,直到你釋放空格鍵纔會返回,所以程序不可能響應其他任何事情,因爲它仍然在循環中運行代碼。 – abarnert

+0

(這正是_why_你應該爲幾乎任何GUI應用程序使用事件循環設計。) – abarnert

回答

6

你有一個主循環,可能看起來是這樣的......

while True: 
    check_for_pause() 
    # Update the game 
    # Draw the game 

當您檢查暫停和空格鍵被按下時,暫停被設置爲True。然後,你有這樣的循環......

space_bar_pressed=keys[K_SPACE] 
while space_bar_pressed: #Repeat this loop until space_bar_pressed is False 
    keys=pygame.key.get_pressed() 
    if not keys[K_SPACE]: #Space bar has been released so set space_bar_pressed to False 
     space_bar_pressed=False 

這個循環的問題是,您認爲pygame.key.get_pressed()將繼續返回了最新信息。然而,看着pygame source code,看來,它採用SDL_GetKeyState,它說其文檔的一部分。

Note: Use SDL_PumpEvents to update the state array. 

換句話說,一邊喊pygame.key.get_pressed()將不會給你更新的密鑰如果你不是另外調用類似pygame.event.pump()的狀態,它實際上用新的鍵狀態更新pygame。因此,您可以通過將該泵功能引入循環來快速修復此問題,因爲它目前只是永遠運行。

這就是說:不要這樣做。如果你這樣做,你的遊戲在暫停時將無法做任何事情:這包括顯示一個「暫停」屏幕,繼續在後臺播放音樂,等等。你想要做的是跟蹤如果遊戲暫停,如果是,請更改遊戲更新的方式。

在您更新遊戲的部分遊戲中,有些項目只有在遊戲暫停時纔會發生。喜歡的東西...

paused = False 
while True: 
    # This function should just return True or False, not have a loop inside of it. 
    paused = check_for_paused() 

    if not paused: 
     # This function moves your enemies, do physics, etc. 
     update_game() 

    draw_game() 

在這種情況下,主循環依然會發生,遊戲將繼續繪製,輸入將繼續處理。然而,敵人和玩家不會移動,因此遊戲可以說是「暫停」了。

最後,還有一個事實是,您依賴的是get_key_pressed(),您可能不想這樣做。請參閱this other similar answer我給出了您應該改爲使用事件隊列的原因。

+0

很好的解釋。但實際上,他應該編寫一個循環遍歷'pygame.event.get()'的主循環,而不是儘可能快地循環並輪詢事件(如[教程](http://www.pygame。組織/文檔/嘖嘖/嗵/ games2.html))。 – abarnert

+0

非常有幫助的答案。非常感謝! – RedRocker227

3

即使遊戲暫停,也不應該停止在遊戲中運行遊戲循環。通常還通過事件處理暫停。例如看看這段代碼:

import pygame, sys 
from pygame.locals import * 
pygame.init() 
pygame.display.set_mode((400,400)) 

paused = False # global 

while True: 
    for event in pygame.event.get(): 
     if event.type == QUIT: 
      pygame.quit() 
      sys.exit() 
     elif event.type == KEYDOWN: 
      if event.key == K_SPACE: 
       paused = not paused 

    if paused: 
     continue # skip this iteration if paused 

    # add your game code here 
    print 'game code running' 

在上面的代碼,I切換暫停每次我按下空格鍵的時間。如果您想暫停僅在持有空格鍵這樣做:

while True: 
    for event in pygame.event.get(): 
     if event.type == QUIT: 
      pygame.quit() 
      sys.exit() 
     elif event.type in (KEYDOWN, KEYUP): # checks membership in tuple 
      if event.key == K_SPACE: 
       paused = not paused 

    if paused: 
     continue # skip this iteration if paused 

    # add your game code here 
    print 'game code running' 

作爲一般的筆記,你應該總是來處理從事件隊列或pygame的事件只會哭和抱怨,什麼也不做(是反應遲鈍)。因此,即使您暫停遊戲,也不要停止旋轉游戲循環。

編輯:或者,如abarnert在評論中指出,你可以做相等比較一招,保證不會讓你KEYDOWN和KEYUP事件之間的衝突:

paused = event.type == KEYDOWN 

這樣你就不必「同步問題」,代碼在您實際釋放空格鍵時意外將paused設置爲True。如果在一行中發生2個KEYDOWN事件或者在一行中發生2個KEYUP事件(而不是像KEYDOWN,KEYUP,KEYDOWN,KEYUP等平滑交替序列),就會發生這種情況。最好不要假設所有事件隊列都會提供100%準確的事件。

+0

我認爲編寫'paused = event.type == KEYDOWN'或類似的代碼更清晰,而不是在第二個版本中進行切換。另外,它避免了你可能以某種方式出現「不同步」並最終暫停的可能性,除非空格鍵被幫助關閉,而不是被關閉。但除此之外,這是一個很好的答案。 – abarnert

+0

@abarnert添加了關於您提到的同步問題的說明。 :) – Shashank

相關問題