python plots Das Hinzufügen einer zusätzlichen Schleife führt zu keiner Antwort




python plot title (2)

Ich mache ein einfaches Spiel mit Pygame, wo Sie (durch Bewegen des Mauszeigers über sie) alle Kreise bekommen müssen, die auf dem Bildschirm erscheinen (mehr erscheint jede Sekunde). Der Code ist ziemlich lang, also habe ich einen Beispielcode gemacht. Dieser Code funktioniert gut, das Pygame-Fenster reagiert überhaupt nicht mehr:

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

In meinem Spiel muss ich jedoch, um dem Benutzer die Wahl zu geben, erneut spielen zu können, alles in end_program in eine andere Schleife end_program . Im folgenden Beispiel ist dies 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()

Wenn das jetzt ausgeführt wird, reagiert das Fenster nicht mehr! Wer weiß, warum etwas so einfach wie das Umwickeln des Codes in einer anderen Schleife (ohne den Code überhaupt zu ändern) dies tut?


Das Problem ist, dass das Spiel nicht reagieren oder überhaupt etwas tun kann, wenn Sie die Ereignisschleife nicht ausführen. In der anderen Schleife wird die Ereignisschleife nicht ausgeführt.

Dies ist ein generelles Problem bei der ereignisschleifenbasierten Programmierung. Sie können nichts tun, was lange dauert, und Sie können nichts tun, das über mehrere Ereignisse hinweg ausgeführt werden muss.

Sie müssen also Ihre Schleife in einzelne Schritte aufteilen und jeweils nur einen Schritt (oder einige davon) durch die Ereignisschleife durchführen.

In diesem speziellen Fall ist es eigentlich ziemlich einfach: has_got_all_circles=False das has_got_all_circles=False in ein if (und verschiebe die has_got_all_circles=False außerhalb der Hauptschleife), und deine Logik läuft jetzt jedes Mal genau einmal durch die Ereignisschleife.

Alternativ können Sie es in ein if ändern und es auch innerhalb von for , sodass es jetzt genau einmal pro Ereignis statt einmal pro Ereignisschleifeniteration ausgeführt wird.

Eine dritte Alternative besteht darin, das Ganze in eine Funktion zu zerlegen und es als eine Leerlauf- oder Zeitgeberfunktion einzustellen, die immer dann ausgeführt wird, wenn die Ereignisschleife im Leerlauf ist, oder einmal pro Frame oder einmal alle 20 ms oder was auch immer.

Es ist schwer zu wissen, welche der drei in Ihrem Fall geeignet ist, aber die Grundidee ist in allen von ihnen die gleiche, also werde ich nur die zweite zeigen:

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

In diesem Blogbeitrag wird das allgemeine Problem genauer erläutert - obwohl das meiste für dieses spezielle Problem nicht wirklich geeignet ist.


Das Problem, das Sie haben, besteht darin, dass Sie Ihren Ereignis-Loop-Code nicht innerhalb der while-Schleife verschachteln, die Ihre Spiellogik ausführt. Hier ist die allgemeine Struktur dessen, was Sie wollen:

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

Es ist möglich, dass offer_another_game auch in einer eigenen Schleife mit eigenem Ereignisbehandlungscode ausgeführt werden muss.

Vielleicht möchten Sie die Logik, die Sie verwenden möchten, in ein Zustandsmaschinensystem kapseln. Sie würden Zustände wie PlayingGame , GameOver und DoYouWantToPlayAgain , die jeweils für eine Weile laufen und dann in einen anderen Staat DoYouWantToPlayAgain . Ihre Hauptschleife wäre dann etwas wie:

state = StartState()
while state:
    state.handle_events()
    state.update()
    state.draw()
    state = state.next_state() # most of the time, the state will return itself




pygame