这是我的check_for_pause()函数:
#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
然而,每当我试图暂停时,这会让我的程序无响应!基本上,我希望变量“暂停”为True或False。按下空格键时,它应该更改为当前不存在的空格键。因为我在另一个永无止境的循环中使用check_for_pause(),所以我需要使它在函数空间栏被释放时才停止执行,否则如果用户持有空格键的时间超过一秒,它将会继续在True和False之间切换。
当我运行此程序时,为什么我的程序无响应的任何想法?我知道这与等待空格键被释放的位有关,因为当我删除那段代码然后我的程序运行正常(但显然暂停功能不起作用)。
答案 0 :(得分: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我已经提供了您应该使用事件队列的理由。
答案 1 :(得分: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'
在上面的代码中,每次按空格键时我都会暂停切换。如果您只想在按住空格键时暂停,请执行以下操作:
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%准确的事件。