2014-12-05 119 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