2013-09-23 76 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

相关问题