Programm nimmt nach einigen sekunden keine Klicks mehr an

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Hangman

Hallo,
ich muss für die Schule ein Spiel in Python mit Pygame schreiben. Das Programm an sich läuft auch ganz gut, allerdings habe ich das Problem, dass nach einigen Sekunden zwar scheinbar noch registriert wird, dass die Maus bewegt wird, das Programm auf Maus-Klicks allerdings niocht mehr reagiert :(

Am Ende des Quellcodes wird die Funktion main() aufgerufen. Über diese wird dann eine andere Funktion runde() aufgerufen, die dann wiederum mehrmals die Funktion turn() aufruft. anschliessend wird wiederum die Funktion runde() aufgerufen. meine event abfrage steht nun in der Funktion turn() die für den Benutzer scheinbar ständig aktiv ist, da die Funktion runde() nur aufgerufen wird, um sofort wieder die Funktion turn() aufzurufen.
Hier der Code für turn():

Code: Alles auswählen

def turn(spieleramzug,aktuellerunde): #wird jedes mal ausgefuehrt, wenn ein Spieler am Zug ist
    zeigeinfosspiel(spieleramzug,aktuellerunde)
    nochdran=1 #Variable, die fuer die Begrenzung der event-schleife erforderlich ist
    while nochdran==1: #so lange dauert ein Zug
        if pygame.event.get([MOUSEBUTTONDOWN]): #eventabfrage
            for i in planeten.keys(): #bei einem Klick auf einen Planeten soll etwas passieren
                if planeten[i]["besitzer"] == spieleramzug:
                    planetkoordy = planeten[i]["koordy"]
                    planetkoordx = planeten[i]["koordx"]
                    if (pygame.mouse.get_pos()[0] > planetkoordx and pygame.mouse.get_pos()[0] < planetkoordx+29 and pygame.mouse.get_pos()[1] > planetkoordy and pygame.mouse.get_pos()[1] < planetkoordy+29) :
                        nochdran=0 #runde wird beendet
                        zeigeinfosplanet(planeten[i],"ja")
        for i in planeten.keys(): #bei einem Klick auf einen Planeten soll etwas passieren
            if planeten[i]["besitzer"] == spieleramzug:
                planetkoordy = planeten[i]["koordy"]
                planetkoordx = planeten[i]["koordx"]
                if (pygame.mouse.get_pos()[0] > planetkoordx and pygame.mouse.get_pos()[0] < planetkoordx+29 and pygame.mouse.get_pos()[1] > planetkoordy and pygame.mouse.get_pos()[1] < planetkoordy+29) :
                    zeigeinfosplanet(planeten[i])
    return()
ich vermute, der Fehler liegt darin, dass die while schleife nicht ständig aktiv ist. andererseits wäre das unlogisch, da sie ja, sobald sie nicht mehr aktiv ist, wieder aufgreufen wird :(
vielen dank für die hilfe im vorraus :)
HarryH
User
Beiträge: 266
Registriert: Freitag 23. Mai 2003, 09:08
Wohnort: Deutschland

Hi Hangman,

Teste mal, ob die while-Schleife auch wirklich unterbrochen wird (print-Befehl in die tiefste if-Abfrage einfügen). Vielleicht läuft sie sich tot und blockiert deswegen das gesamte Programm?
Gruß, Harry
Hangman

nur die Klicks werden nicht mehr angenommen. die position der maus wird weiter erkannt und auf diese Art kann ich auch weiterhin funktionen ausführen. nur eben die klicks werden nicht mehr erkannt :(
HarryH
User
Beiträge: 266
Registriert: Freitag 23. Mai 2003, 09:08
Wohnort: Deutschland

Hi Hangman,

Schick doch mal die anderen dazugehörigen Funktionen die mit der Funktion turn in Verbindung stehen.
Gruß, Harry
Gast

Code: Alles auswählen

if __name__ == '__main__': main(9000,100,["jkhsdfuihsk","Hangman"])
da wir die funktion main mit parametern aufgerufen....

Code: Alles auswählen

def main(anzahlplaneten,anzrunden,mitspieler):
    spielererstellen(mitspieler) #erstellt ein Dictionary mit je einem Dictionary pro Spieler
    planetenerstellen(anzahlplaneten) #erstellt ein Dictionary mit je einem Dictionary pro Planeten
    startplanetenzuweisen() #weist jedem Spieler einen Planeten zu
    pygame.display.update() 
    runde(mitspieler,1,anzrunden) #das Spiel selber beginnt mit der ersten Runde
das ist jetzt halt die funktion main.. in dieser werden erst diverse funktionen aufgerufen, die bestimmte einstellungen vornehmen etc. das wichtige ist die funktion runde:

Code: Alles auswählen

def runde(mitspieler,aktuellerunde,anzrunden): #rekursive funktion. bei jedem aufruf eine runde weiter
    if anzrunden >= aktuellerunde:
        for i in mitspieler: #alle spieler kommen nach einander dran
            turn(i,aktuellerunde)
        aktuellerunde += 1 #aktuelle runde wird um 1 erhoeht
        runde(mitspieler,aktuellerunde,anzrunden)
in dieser wird dann mehrfach turn aufgerufen:

Code: Alles auswählen

def turn(spieleramzug,aktuellerunde): #wird jedes mal ausgefuehrt, wenn ein Spieler am Zug ist
    zeigeinfosspiel(spieleramzug,aktuellerunde)
    nochdran=1 #Variable, die fuer die Begrenzung der event-schleife erforderlich ist
    while nochdran==1: #so lange dauert ein Zug
        if pygame.event.get([MOUSEBUTTONDOWN]): #eventabfrage
            for i in planeten.keys(): #bei einem Klick auf einen Planeten soll etwas passieren
                if planeten[i]["besitzer"] == spieleramzug:
                    planetkoordy = planeten[i]["koordy"]
                    planetkoordx = planeten[i]["koordx"]
                    if (pygame.mouse.get_pos()[0] > planetkoordx and pygame.mouse.get_pos()[0] < planetkoordx+29 and pygame.mouse.get_pos()[1] > planetkoordy and pygame.mouse.get_pos()[1] < planetkoordy+29) :
                        nochdran=0 #runde wird beendet
                        zeigeinfosplanet(planeten[i],"ja")
        for i in planeten.keys(): #bei einem Klick auf einen Planeten soll etwas passieren
            if planeten[i]["besitzer"] == spieleramzug:
                planetkoordy = planeten[i]["koordy"]
                planetkoordx = planeten[i]["koordx"]
                if (pygame.mouse.get_pos()[0] > planetkoordx and pygame.mouse.get_pos()[0] < planetkoordx+29 and pygame.mouse.get_pos()[1] > planetkoordy and pygame.mouse.get_pos()[1] < planetkoordy+29) :
                    zeigeinfosplanet(planeten[i])
    return()
eigentlich sollte also immer, wenn turn() beendet ist turn sozusagen sofort wieder aufgerufen werden. scheinbar wird nur die annahme von Klicksbeendet :(
BlackJack

Hilft Dir nicht bei Deinem Problem: Aber `runde()` ist völlig unnötiger weise rekursiv. Das würde ich ändern.

Und man braucht am Ende einer Funktion kein ``return``. Die Klammern danach wären auch überflüssig.
Hangman
User
Beiträge: 11
Registriert: Donnerstag 12. Mai 2005, 15:06
Kontaktdaten:

BlackJack hat geschrieben:Hilft Dir nicht bei Deinem Problem: Aber `runde()` ist völlig unnötiger weise rekursiv. Das würde ich ändern.
Wieso ist das unnötig? diese Funktion muss nachher wieder aufgerufen werden....
BlackJack hat geschrieben:Und man braucht am Ende einer Funktion kein ``return``. Die Klammern danach wären auch überflüssig.
in diesem fall brauchte ich es schon...frag mich nicht, warum....ohne das ging es nicht :(

edit: zum ersten: so wird geregelt dass nach der ersten runde die 2. kommt etc.
HarryH
User
Beiträge: 266
Registriert: Freitag 23. Mai 2003, 09:08
Wohnort: Deutschland

Hi Hangman,

Probier mal die Funktion 'turn' folgendermaßen aufzurufen:

Code: Alles auswählen

import thread
thread.start_new_thread(turn, (i, aktuellerunde,))
Meiner Meinung nach blockiert nämlich die ständig laufende while-Schleife
den Hauptthread, so daß keine Benutzeraktion zugelassen werden kann.
Durch das Aufrufen der Funktion 'turn', in einem externen Thread wird die
verhindert.

Zusätzlich würde ich am Ende der while-Schleife noch folgendes einbauen:

Code: Alles auswählen

import time
time.sleep(0.1)
Dadurch läuft die Schleife nicht ständig auf "Volltouren" sondern wird
jedesmal am Ende für eine 1\10 Sekunde angehalten, was für die
Benutzeraktionen noch relevant ist, aber die Systemleistung minimiert.

Und Übrigens:
Wie beendest du dein Programm? Ich habe keine Abbruchbedingung gefunden.

Edit (Leonidas): Code in Python-Tags gesetzt.
Gruß, Harry
Hangman
User
Beiträge: 11
Registriert: Donnerstag 12. Mai 2005, 15:06
Kontaktdaten:

danke für die hilfe :) nun läuft das programm an sich zwar durch, allerdibngs bekommt man keine möglichkeit zur Aktion, da alles sofort hinter einander abläuft. die mainfunktion läuft weiter, wodurch turn() sofort wieder aufgerufen wird. das programm läuft also durch, bis es am ende angekommen ist.

Das ende wird durch die if bedingung

Code: Alles auswählen

    if anzrunden >= aktuellerunde:
und durch das erhöhen von aktuellerunde erreicht.

edit: ich hab ent wirklich ahnung von threads...... gibts da irgendwo ne gute anleitung, wo man was dazu lernen kann?
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Hangman hat geschrieben:edit: ich hab ent wirklich ahnung von threads...... gibts da irgendwo ne gute anleitung, wo man was dazu lernen kann?
Da wäre die Doku zum thread und zum threading-Modul, sowie das Thread-Kapitel im Python Cookbook. Aber deutsche Doku zu dem Thema habe ich gerade nicht gefunden. Jedoch ist thread.start_new_thread() recht einfach zu verstehen :)
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Hangman
User
Beiträge: 11
Registriert: Donnerstag 12. Mai 2005, 15:06
Kontaktdaten:

vom Prinzip her habe ich das glaube ich schon verstanden.. das problem ist nur, dass das hier etwas amcht, was gar nicht sein soll....
ich will ja nicht, dass das hauptprogramm weiter läuft, während das andere noch nicht fertig ausgeführt ist....

aber mich interessiert halt, was threads sind :) deswegen thx für die tutorials :)
BlackJack

Hangman hat geschrieben:
BlackJack hat geschrieben:Hilft Dir nicht bei Deinem Problem: Aber `runde()` ist völlig unnötiger weise rekursiv. Das würde ich ändern.
Wieso ist das unnötig? diese Funktion muss nachher wieder aufgerufen werden....

edit: zum ersten: so wird geregelt dass nach der ersten runde die 2. kommt etc.
Das ist unnötig weil man das viel einfacher und sauberer in einer Schleife ausdrücken kann:

Code: Alles auswählen

def runde(mitspieler, anzrunden):
    for aktuellerunde in xrange(1, anzrunden + 1):
        for i in mitspieler:
            turn(i, aktuellerunde)
Hangman
User
Beiträge: 11
Registriert: Donnerstag 12. Mai 2005, 15:06
Kontaktdaten:

stimmt auch...
wo is der unterschied zwischen range und xrange?
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Hangman hat geschrieben:wo is der unterschied zwischen range und xrange?
Bei range bekommst du eine Liste, bei xrange einen Iterator. Iteratoren belasten den Speicher meist wesentlich weniger, da sie erst erstellt werden, wenn man sie benötigt.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Hangman
User
Beiträge: 11
Registriert: Donnerstag 12. Mai 2005, 15:06
Kontaktdaten:

aso gut thx :)
Hangman
User
Beiträge: 11
Registriert: Donnerstag 12. Mai 2005, 15:06
Kontaktdaten:

nu versteh ich das gar nicht mehr :(
ich hab das ganze nu komplett geändert. Jetzt hab ich nur noch ne while schleife, die bei einem Mausklick die funktion mausklick aufruft und als parameter die koordinaten der maus übergibt :( der gleiche fehler wie viorher bleibt :(

die while schleife:

Code: Alles auswählen

while 1:
	if pygame.event.get([MOUSEBUTTONDOWN]):
		mausklick(pygame.mouse.get_pos()[0], pygame.mouse.get_pos()[1])
und die funktion mauskilck:

Code: Alles auswählen

def mausklick(mausx, mausy):
	for i in planeten.keys(): #bei einem Klick auf einen Planeten soll etwas passieren
		if planeten[i]["besitzer"] == aktuell["spieler"]:
			planetkoordy = planeten[i]["koordy"]
			planetkoordx = planeten[i]["koordx"]
			if (pygame.mouse.get_pos()[0] > planetkoordx and pygame.mouse.get_pos()[0] < 	planetkoordx+29 and pygame.mouse.get_pos()[1] > planetkoordy and pygame.mouse.get_pos()[1] < planetkoordy+29) :
				if aktuell["aktion"]=="startausw":
                        		aktuell["neueaktion"]={"startplani":i}
					aktuell["aktion"]="zielausw"
		if planeten[i]["besitzer"] != aktuell["spieler"]:
			planetkoordy = planeten[i]["koordy"]
			planetkoordx = planeten[i]["koordx"]
			if (pygame.mouse.get_pos()[0] > planetkoordx and pygame.mouse.get_pos()[0] < 	planetkoordx+29 and pygame.mouse.get_pos()[1] > planetkoordy and pygame.mouse.get_pos()[1] < planetkoordy+29) :
				if aktuell["aktion"]=="zielausw":
					aktuell["neueaktion"]["zielplani"]=i
					aktuell["aktion"]="ende"
				elif aktuell["aktion"]=="ende":
					beendeturn()
wäre nett, wenn mir jemand helfen kann ;)
Hangman
User
Beiträge: 11
Registriert: Donnerstag 12. Mai 2005, 15:06
Kontaktdaten:

gut hab den fehler selber gefunden :)
die abfrage funktioniert so nicht... muss ein for event in pygame.get.event(): hin....

viele dank für eure hilfe :)
Antworten