简体   繁体   English

为什么我的暂停系统不起作用? (Pygame)

[英]Why is my pause system not working? (Pygame)

Here's my check_for_pause() function: 这是我的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

however this keeps making my program become unresponsive whenever I try to pause it! 但是,这会使我的程序在每次尝试暂停时都变得无响应! Basically, I want the variable "paused" to be either True or False. 基本上,我希望变量“ paused”为True或False。 When the space bar is pressed, it should change to whichever one it isn't currently. 按下空格键时,它应该更改为当前未选择的任何一个。 Because I'm using check_for_pause() in another never-ending loop, I need to make it so that the function only stops executing when the space bar is released, otherwise if the user holds the space bar for more than a split second it will keep switching between True and False. 因为我在另一个永无休止的循环中使用了check_for_pause(),所以我需要这样做,以便函数仅在释放空格键时才停止执行,否则,如果用户按住空格键超过一秒钟,它将保持在正确与错误之间切换。

Any ideas why my program becomes unresponsive when I run this? 有什么想法为什么我在运行该程序时我的程序无响应? I know it's to do with the bit that waits until the space bar's been released because when I remove that bit of the code then my program runs fine (but obviously the pause feature then doesn't work). 我知道这与等待释放空格键的位有关,因为当我删除那部分代码时,我的程序可以正常运行(但是显然,暂停功能不起作用)。

You have a main loop that probably looks something like this... 您的主循环可能看起来像这样...

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

When you check for pause, and the space key is pressed down, paused gets set to True. 当您检查暂停时,并按下空格键时,暂停将设置为True。 Then, you have this loop... 然后,你有这个循环...

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

The problem with this loop is that you assume that pygame.key.get_pressed() will continue to return up-to-date information. 此循环的问题是,您假设pygame.key.get_pressed()将继续返回最新信息。 However, looking at the pygame source code , it appears that it uses SDL_GetKeyState, which says as part of its documentation.. 但是,查看pygame源代码 ,似乎它使用了SDL_GetKeyState,这是其文档的一部分。

Note: Use SDL_PumpEvents to update the state array.

In other words, repeatedly calling pygame.key.get_pressed() will NOT give you the updated key state if you are not additionally calling something like pygame.event.pump() , which actually updates pygame with the new key states. 换句话说,如果您不另外调用pygame.event.pump()类的东西,而反复调用pygame.key.get_pressed()不会给您更新的键状态,实际上会使用新的键状态来更新pygame。 So, you could quickly fix this by introducing that pump function into the loop, as currently it is just running forever. 因此,您可以通过将该泵功能引入循环中来快速解决此问题,因为当前它一直在运行。

That being said: DON'T DO THIS. 话虽这么说:不要这样做。 If you do it this way, your game will not be able to do ANYTHING when paused: this includes showing a "paused" screen, continuing to play the music in the background, etc. What you want to do instead is keep track of if the game is paused, and if so, change how the game is updating. 如果以这种方式进行操作,则游戏在暂停时将无法执行任何操作:这包括显示“已暂停”屏幕,继续在后台播放音乐等。您要做的就是跟踪是否游戏暂停,如果暂停,请更改游戏的更新方式。

In the part of your game where you update things, some items should only happen if the game is paused. 在游戏中更新内容的部分中,某些项目仅应在游戏暂停后才发生。 Something like... 就像是...

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()

In this case, the main loop will still happen, the game will continue to be drawn, and the input will continue to be handled. 在这种情况下,主循环仍然会发生,游戏将继续进行绘制,并且输入将继续得到处理。 However, the enemies and players will not be moving, therefore the game can be said to be "paused". 但是,敌人和玩家不会移动,因此可以说游戏已“暂停”。

Finally, there is also the fact that you're relying on get_key_pressed(), which you probably don't want to do. 最后,还有一个事实就是您依赖于get_key_pressed(),而您可能不想这样做。 See this other similar answer I've given for reasons why you should be instead using the event queue. 请参阅我给出的其他类似答案,以了解为什么应改为使用事件队列的原因。

You should never stop running your game loop in a game even if it paused. 即使暂停,也永远都不要停止运行游戏循环。 Also pauses are generally handled through events. 暂停通常也通过事件来处理。 For example look at this code: 例如看下面的代码:

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'

In the above code, I toggle paused every time I press spacebar. 在上面的代码中,每当我按下空格键时,我会切换为暂停。 If you want to pause only while holding spacebar do this: 如果只想在按住空格键时暂停,请执行以下操作:

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'

As a general note, you should always be handling events from your event queue or Pygame will just cry and whine and do nothing (be unresponsive). 作为一般说明,您应该始终在处理事件队列中的事件,否则Pygame只会哭泣和抱怨,什么也不做(无响应)。 Thus, never stop spinning on your game loop even if you have paused the game. 因此,即使您暂停了游戏,也请不要停止游戏循环。

EDIT: Alternatively, as abarnert pointed out in the comments you can do a trick with equality comparisons to assure that you never get conflicts between KEYDOWN and KEYUP events: 编辑:或者,正如abarnert在评论中指出的那样,您可以通过相等比较来做一个技巧,以确保您不会在KEYDOWN和KEYUP事件之间发生冲突:

paused = event.type == KEYDOWN

This way you won't have "syncing problems" where the code accidentally sets paused to True whenever you actually release the spacebar. 这样,您就不会遇到“同步问题”,只要您真正释放空格键,代码就不会意外将paused设置为True。 This can happen if 2 KEYDOWN events happen in a row or if 2 KEYUP events happen in a row (instead of a smooth alternating sequence like KEYDOWN, KEYUP, KEYDOWN, KEYUP, etc.). 如果连续发生2个KEYDOWN事件或连续发生2个KEYUP事件(而不是像KEYDOWN,KEYUP,KEYDOWN,KEYUP等这样的平滑交替序列),则会发生这种情况。 It's best to not assume that all event queues feed events that are 100 percent accurate. 最好不要假设所有事件队列都提供100%准确的事件。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM