2

画面に表示されるすべての円を(カーソルをそれらの上に移動して)取得する必要があるPygameを使用して、単純なゲームを作成しています(毎秒さらに表示されます)。コードはかなり長いので、サンプルコードを作成しました。このコードは正常に動作し、Pygame ウィンドウはまったく応答しなくなります。

import pygame, random, sys

pygame.init()

window=pygame.display.set_mode((480,360))

end_program=False
while not end_program:
    for event in pygame.event.get():
        if event.type==pygame.QUIT  or  pygame.key.get_pressed()[pygame.K_ESCAPE]: #If the user either click the "x", or pressed the "esc" key
            end_program=True

    pass

pygame.quit()
sys.exit()

ただし、私のゲームでは、ユーザーにもう一度プレイする選択肢を与えるために、すべてend_programを別のループでラップする必要があります。示されている例では、これはbreak_from_second_loop次のとおりです。

import pygame, random, sys

pygame.init()

window=pygame.display.set_mode((480,360))

end_program=False
while not end_program:
    for event in pygame.event.get():
        if event.type==pygame.QUIT  or  pygame.key.get_pressed()[pygame.K_ESCAPE]: #If the user either click the "x", or pressed the "esc" key
            end_program=True

    break_from_second_loop=False

    while not break_from_second_loop:
        pass

pygame.quit()
sys.exit()

これを実行すると、ウィンドウが応答しなくなります。(コードをまったく変更せずに) 別のループでコードをラップするのと同じくらい簡単なことがなぜこれを行うのか誰でも知っていますか?

4

2 に答える 2

3

問題は、イベント ループを実行していない場合、ゲームが応答できないか、まったく何もできないことです。もう 1 つのループでは、イベント ループを実行していません。

これは、イベント ループ ベースのプログラミングの一般的な問題です。時間がかかることはできませんし、複数のイベントにまたがる必要があることもできません。

そのため、ループをいくつかのステップに分割し、イベント ループのたびに 1 つのステップ (またはいくつかのステップ) だけを実行する必要があります。

この特定のケースでは、実際には非常に単純です。これwhileを anに変更しif(メイン ループの外側に移動しhas_got_all_circles=Falseます)、ロジックはイベント ループを介して毎回正確に 1 回実行されます。

または、これを に変更して 内移動するとif、イベント ループの反復ごとに 1 回ではなく、イベントごとに 1 回だけ実行されるようになります。for

3 番目の方法は、すべてを関数に分解し、イベント ループがアイドル状態のとき、またはフレームごとに 1 回、20 ミリ秒ごとに 1 回など、アイドル関数またはタイマー関数として設定することです。

あなたの場合、3 つのうちどれが適切かを知るのは難しいですが、基本的な考え方はすべて同じなので、2 つ目のものだけを示します。

end_program=False
break_from_second_loop=False
while not end_program:
    for event in pygame.event.get():
        if event.type==pygame.QUIT  or  pygame.key.get_pressed()[pygame.K_ESCAPE]: #If the user either click the "x", or pressed the "esc" key
            end_program=True
        if not break_from_second_loop:
            pass

このブログ投稿では、一般的な問題をより詳細に説明していますが、そのほとんどは、この特定の問題にはあまり当てはまりません。

于 2013-10-17T19:56:54.287 に答える
1

あなたが抱えている問題は、ゲーム ロジックを実行する while ループ内にイベント ループ コードをネストしていないことです。必要なものの一般的な構造は次のとおりです。

while not end_program:
    while not end_game:
        handle_events()
        do_one_frame_of_game_logic()
    offer_another_game()

offer_another_game独自のイベント処理コードを使用して、独自のループで実行する必要がある可能性もあります。

実際、使用したいロジックをステート マシン システムにカプセル化することもできます。PlayingGameGameOver、およびのような状態がありDoYouWantToPlayAgain、それぞれがしばらく実行されてから、別の状態に引き渡されます。メインループは次のようになります。

state = StartState()
while state:
    state.handle_events()
    state.update()
    state.draw()
    state = state.next_state() # most of the time, the state will return itself
于 2013-10-18T08:45:37.000 に答える