0

ここに私の 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にする必要があります。スペースバーを押すと、現在のものではないものに変わるはずです。もう 1 つの終わりのないループで check_for_pause() を使用しているため、スペース バーが離されたときにのみ関数の実行が停止するようにする必要があります。 True と False を交互に繰り返します。

これを実行するとプログラムが応答しなくなる理由はありますか? コードのそのビットを削除すると、プログラムが正常に実行されるため、スペースバーが解放されるまで待機するビットに関係していることはわかっています(ただし、明らかに一時停止機能は機能しません)。

4

2 に答える 2

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 のソース コードを見ると、ドキュメントの一部として 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() に依存しているという事実もあります。代わりにイベントキューを使用する必要がある理由については、私が提供した他の同様の回答を参照してください。

于 2013-09-23T20:39:04.717 に答える
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% 正確なイベントをフィードすると仮定しないことをお勧めします。

于 2013-09-23T20:44:27.283 に答える