2014-12-05 125 views
1

我正在用Python設計一款遊戲,並想知道如何製作一個可以在我的遊戲中運行的高效計時器。Python遊戲計時器(線程?)

注意:我正在使用Pygame。

我現在有一個定時器,像這樣:

import time 

seconds = 60 

def start_timer(): 
    global seconds 
    while seconds > 0: 
     print seconds 
     seconds -= 1 
     time.sleep(1) 

然而,在我的主要遊戲功能運行時,我的遊戲掛起因爲timer.sleep的。

def main(self): 
    Timer.start_timer() 

我很確定我的問題與不使用線程有關,雖然我不是100%確定。有人能幫我解釋一下合適的解決方案嗎?

+0

這是一個使用像PyGame的圖形遊戲?如果是這樣,那麼可能比線程有更好的答案。但線程仍然可以工作。 – abarnert 2014-12-05 21:58:15

+0

是的,這是一款使用PyGame的遊戲! – test 2014-12-05 22:00:12

回答

0

如果您使用的是PyGame,它有自己的time functionality您應該使用。

如果您使用的是事件循環或混合設計,讓您在pygame.event.get()或環相似,稱之爲「事件處理程序」對不同的事件,如鼠標點擊或鍵下,你可以使用set_timer創建活動每秒都會發生。例如:

TIMER1_EVENT = pygame.USEREVENT + 1 

def start_timer1(): 
    global seconds 
    seconds = 60 
    pygame.time.set_timer(TIMER1_EVENT, 1000) 

def on_timer1(): 
    global seconds 
    print seconds 
    seconds -= 1 
    if seconds < 0: 
     pygame.time.set_timer(TIMER1_EVENT, 0) 

# elsewhere, inside your main event loop 
elif event.type == TIMER1_EVENT: 
    on_timer1() 

在文檔中爲每個函數鏈接了非常簡單的示例程序;如果你看看set_timer的例子,你會看到使用起來非常簡單。

如果你使用的是純粹的幀循環,你可能已經調用Clock.tick或類似的,你將不得不使用它的返回值來計算自上次以來的毫秒數,並決定是否你已經通過了另一個整數秒,當你通過0。

+0

這裏是我的主循環的一個pastebin:http://pastebin.com/E3LYfYqf我相信它是一個幀循環,因爲我有'clock.tick'。你能用我的代碼給我一個例子嗎?我對皮格梅相當陌生。謝謝! – test 2014-12-05 22:16:53

+0

@test:你仍然有一個圍繞'pygame.event.get()'的循環,這意味着你仍然可以使用'pygame.time.set_timer()'。如果您根本沒有事件循環,則只需要手動計數代碼。在你的代碼中,你所需要做的就是在第61行後面添加這個'elif'。並且,無論你想啓動定時器的任何條件,當然都要給'start_timer1()'添加一個調用。 – abarnert 2014-12-05 22:19:10

+0

嗯,當我添加'elif:on_timer1()'時,定時器永遠不會啓動,當我刪除'elif'時,它似乎隨機運行,而不是每秒一次。我贊同不理解這一點。正如我所說我是Pygame的新手。 – test 2014-12-05 22:26:15

0

如果您使用的是PyGame或其他圖形庫,並且圍繞事件循環或幀速率循環構建了遊戲,則需要使用該庫附帶的函數。如果你有一個事件循環,你可以讓它安排一個事件在60秒內觸發。如果你有一個幀率循環,你可能會做同樣的事情,或需要檢查一次/幀的剩餘時間。

但是,如果你是而不是這樣做,那麼是的,線程是答案。

對於簡單的定時器,最簡單的解決方案是Timer類。但是,這不會自動執行重複計時器,因此您必須手動添加該計時器。例如,你可以開始一個1秒鐘的定時器,並且已經期滿後它開始另1秒計時器:

def start_timer(): 
    global seconds 
    if seconds > 0: 
     print seconds 
     seconds -= 1 
     threading.Timer(1, start_timer).start() 

seconds = 60 
threading.Timer(1, start_timer).start() 

然而,它通常是一個更容易使用,它知道如何來爲他們做重複計時器您。您可以自己創建一個(請注意,threading文檔包含指向source的鏈接,並且不難找出如何添加邏輯,使其每interval秒(而不是僅一次)觸發count次)。或者你可以找到go search PyPI,並找到幾十個已經爲你實施的人。

另外請記住,一旦你使用線程,你必須處理線程問題。如果您使用GUI庫,他們通常不會讓您從後臺線程調用GUI方法。如果您訪問的是兩個線程之間共享的變量,則通常需要使用Lock或其他同步對象來保護它。等等。

+0

但是,我正在使用幀速率循環;你的代碼似乎有點工作。我將如何做一個與我的上面一樣的計時器?我想每1秒鐘遞減一次,這似乎開始了兩次,而我只想要一次。謝謝 – test 2014-12-05 22:08:31

+0

@test:這隻啓動一個計時器 - 但是這個計時器在一秒後到期,所以你啓動一秒鐘後到期的_second_計時器,所以你開始一個第三個計時器,依此類推,直到第60個計時器到期,你不要擊中'如果'並且不要開始第61次。這就是爲什麼內置的Timer使用笨拙,爲什麼我建議使用另一種替代方法。 – abarnert 2014-12-05 22:16:11