Pacman mit Tkinter

Stellt hier eure Projekte vor.
Internetseiten, Skripte, und alles andere bzgl. Python.
Benutzeravatar
jonas
User
Beiträge: 156
Registriert: Dienstag 9. September 2008, 21:03

Hi

Zum Level laden würde doch sowas hier reichen:

Code: Alles auswählen

#!/usr/bin/python 
# -*- coding: utf-8 -*- 
 
import os 
 
LEVELDIR = '/home/jonas/scripts/levels' 
 
class NoLevelDataFoundError(Exception): 
    pass 

#ehemals NoFileError
 
def get_level_data(fobj): 
    level = [x.strip() for x in fobj.readlines()] 
    return level 
    
def load_levels(lvldir): 
    levels = list() 
    for root, dirs, files in os.walk(lvldir): 
        if files: 
            for file_ in files: 
                with open(root + os.sep + file_) as fobj: 
                    levels.append(get_level_data(fobj)) 
        else: 
            raise NoLevelDataFoundError
    return levels 
 
print load_levels(LEVELDIR)
Die Leveldateien könnten dann einfach so aussehen:

Code: Alles auswählen

#################
#...............#           
#...p.......p...#            
#...............#            
#...............#            
#......#g#......#            
#.... #ggg#.....#             
#.....#####.....#             
#...............#             
#...............#             
#...............#
#################
Lg, Jonas :wink:
EDIT: Exceptionname geändert (s.Code)
Zuletzt geändert von jonas am Dienstag 25. Mai 2010, 09:58, insgesamt 1-mal geändert.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

kaytec hat geschrieben:Hallo Hyperion !

Das ist die Fehlermeldung:

Code: Alles auswählen

Exception in Tkinter callback
Traceback (most recent call last):
  File "/usr/lib/python2.6/lib-tk/Tkinter.py", line 1413, in __call__
    return self.func(*args)
TypeError: set_player_position() takes exactly 3 arguments (4 given)
Ich meine das hier:

Code: Alles auswählen

    def set_player_position(self, x, y, event):
        self.x, self.y = x, y
Den Aufruf davon kapiere ich nicht wirklich:

Code: Alles auswählen

    def move_player(self, button, x, y):
        self.root.bind(button, partial(
            self.pac_man.set_player_position, x, y))
Wozu das ganze? event wird doch gar nicht benötigt in der PacMan-Klasse - zumindest wird das Objekt durch die set_player_position nicht genutzt... oder sehe ich das falsch?

Falls doch würde ich auch mal behaupten, dass die Trennung von Logik und GUI dann schlecht implementiert wäre.

@jonas: Ob man diese Exception wirklich braucht, sei mal dahingestellt. Aber sollte sie dann nicht eher Bezug zu den Leveldaten aufzeigen? Also eher "NoLevelDataFound" o.ä.

Generell würde ich statt des custom-Formates auf json o.ä. zurückgreifen. Da hat man es dann leichter, andere Werte in eine Datei reinzubringen und ggf. mehr als einen Level in einer Datei mühelos abzulegen.
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
Benutzeravatar
kaytec
User
Beiträge: 608
Registriert: Dienstag 13. Februar 2007, 21:57

Hallo Hyperion und jonas !

@ jonas Danke

@Hyperion
Die Fehlermeldung kommt, wenn ich den event in "set_player_position" nicht übergebe, obwohl dieser von der Gui nicht offensichtlich übergeben wird.

Code: Alles auswählen

def set_player_position(self, x, y):
        self.x, self.y = x, y
Ohne event kommt die Fehlermeldung:

Code: Alles auswählen

Exception in Tkinter callback
Traceback (most recent call last):
  File "/usr/lib/python2.6/lib-tk/Tkinter.py", line 1413, in __call__
    return self.func(*args)
TypeError: set_player_position() takes exactly 3 arguments (4 given)
>Exit code: 0
Die zusätzliche Funktion "move_player" ist unnötigt. Hatte bei Snake vor längerer Zeit das Problem, dass ich nicht direkt über eine Schleife beim Initialisieren der Gui die Tasten binden konnte. Wurde in einem älteren Thread (kann ihn leider nicht finden) auch so gelöst. Warum es jetzt geht ?

Waren noch Fehler in der Logik --> http://paste.pocoo.org/show/217826/

Gruß Frank
Benutzeravatar
jonas
User
Beiträge: 156
Registriert: Dienstag 9. September 2008, 21:03

Hi Hyperion!

Ja, der Exceptionname von dir ist besser. Ich werds ändern ;-)

Lg, Jonas :wink:
BlackJack

@Hyperion: `event` wird nicht verwendet aber von `Tkinter` wird es übergeben, also muss dafür auch ein formales Argument vorhanden sein.

Da wo Du sagst, den Aufruf verstehst Du nicht, wird es ja auch gar nicht aufgerufen sondern ein "callable" aus der Methode erstellt, bei der die Argumente `x` und `y` mittels `partial()` vorbelegt werden, und ein "callable" herauskommt, was nur noch ein Argument, nämlich das Event entgegennimmt. Und das ist nun einmal die Signatur die `Tkinter` für ein Callback bei `bind()` erwartet.
Benutzeravatar
kaytec
User
Beiträge: 608
Registriert: Dienstag 13. Februar 2007, 21:57

Hallo Hyperion !

Das mit dem event hat mich beschäftigt und ich habe mal versucht es aufzuzeigen.

Hier mal ein Versuch mit "lambda", einer zusätzlichen Funktion und ohne event.
http://paste.pocoo.org/show/217945/

Hier mal ein Versuch mit "lambda" ohne eine zusätzlichen Funktion und ohne event.
http://paste.pocoo.org/show/217948/

Hier mal ein Versuch mit partial und mit event.
http://paste.pocoo.org/show/217949/

Hier mal ein Versuch mit partial und ohne event.
http://paste.pocoo.org/show/217951/

Gruß Frank
Benutzeravatar
wuf
User
Beiträge: 1529
Registriert: Sonntag 8. Juni 2003, 09:50

Hallo kaytec

Die Variante:
http://paste.pocoo.org/show/217951/

Wirft bei mir folgende Exception:
  • Exception in Tkinter callback
    Traceback (most recent call last):
    File "/usr/lib/python2.5/lib-tk/Tkinter.py", line 1403, in __call__
    return self.func(*args)
    TypeError: set_walker_position() takes exactly 3 arguments (4 given)
    Exception in Tkinter callback
    Traceback (most recent call last):
    File "/usr/lib/python2.5/lib-tk/Tkinter.py", line 1403, in __call__
    return self.func(*args)
    TypeError: set_walker_position() takes exactly 3 arguments (4 given)
Die Exception kann unterbunden werden indem du die Methode:

Code: Alles auswählen

def set_walker_position(self, x, y):
auf

Code: Alles auswählen

def set_walker_position(self, x, y, *args):
erweiterst.

Gruß wuf :wink:
Take it easy Mates!
BlackJack

@wuf: Oder statt ``*args`` eben nur ein zusätzliches Argument `event`. Denn genau das wird da ja übergeben. Womit wir wieder am Ausgangspunkt wären.
Benutzeravatar
kaytec
User
Beiträge: 608
Registriert: Dienstag 13. Februar 2007, 21:57

Hallo wuf !

Ich wollte nur zeigen welche Möglichkeiten es gibt und welche Probleme auftauchen. Mit "lambda" geht es ohne ein "event" zu übergeben, doch nur mit dem "Umweg" über eine zusätzliche Funktion. Bei fehlendem "Umweg" bewegt sich der "walker" nicht.

Bei "partial" geht es ohne den "Umweg" aber halt nur mit dem "event".

Könnte man fast ins Tk-Forum verschieben.

Gruß Frank
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Ok, also ich habe jetzt verstanden, dass man dieses event als Parameter vorsehen muss. Nur frage ich mich noch, ob das ein sinnvoller Weg ist? Denn so muss ich doch das eigentlich GUI unabhängige Modell mit der GUI verquicken bzw. es an die GUI anpassen.

Man muss doch auch so einen Tastendruck abfangen und dann die entsprechende (ohne unnützen event-Parameter) Methode der Spiellogik aufrufen können!?!
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
Benutzeravatar
kaytec
User
Beiträge: 608
Registriert: Dienstag 13. Februar 2007, 21:57

Hallo Hyperion !

In dem ersten Versuch ist es ohne eine Übergabe des "event", doch "lambda" soll man durch "partial" ersetzen - ist mit so gesagt worden.

Gruß Frank
problembär

HerrHagen hat geschrieben:Weils so gut passt - man schaue sich das mal an (21.05.2010):
http://www.google.de/
Sogar mit Ton.
Ja, und:

http://yuccatree.de/2010/05/google-teures-pacman/

:shock:
Benutzeravatar
kaytec
User
Beiträge: 608
Registriert: Dienstag 13. Februar 2007, 21:57

Hallo !

An der Logik gebastelt --> http://paste.pocoo.org/show/220334/

Gruß Frank
marl0n
User
Beiträge: 1
Registriert: Mittwoch 9. Juni 2010, 18:22

Das Spiel ist dir echt sehr gut gelungen!
Simpel, aber es macht Spaß. Es ist auch nicht zu leicht ;)
Du solltest aber noch ein Blinken beim Übergang vom grauen zum farbigen der Gegner hinzufügen. Das kommt sonst sehr plötzlich und schon hat man ein leben verloren. Die Gegner sollten also vielleicht 3-5 mal blinken, bis sie wieder nicht-berührbar sind.
Top spiel!

marlon

Eine möglichkeit, eigene Maps zu öffnen, wäre auch cool. Man legt eine Datei an mit dem namen "mapname.map" und da steht die Map so drin, wie das Programm sie verarbeitet. Im Menü könnte dann ein Punkt "M: Map laden" sein ;)
arminn
User
Beiträge: 1
Registriert: Sonntag 22. August 2010, 21:23

Das Goolge loge habe ich jetzt erst gesehen ist super
nomnom
User
Beiträge: 487
Registriert: Mittwoch 19. Mai 2010, 16:25

kaytec hat geschrieben:Hallo !

An der Logik gebastelt --> http://paste.pocoo.org/show/220334/

Gruß Frank
Ist ein Pacman ohne Wände logisch? :P

EDIT: Achso, das ist nur das erste Level :oops:

Schade das es keine Kommentare im Quellcode gibt. :( Scheint aber trotzdem einigermaßen verständlich zu sein.
Xynon1
User
Beiträge: 1267
Registriert: Mittwoch 15. September 2010, 14:22

Ja, sehr gelungen, auch wenn man beim Quellcode noch einiges etwas Übersichtlicher gestalten könnte.

Nur eines versteh ich nicht - wieso verweist ihr auf eine externe Seite für das "Google Doodle" ?
kann man doch auch ganz bequem auf google anschauen: http://www.google.com/pacman
Traue keinem Computer, den du nicht aus dem Fenster werfen kannst.
Xynon auf GitHub
Benutzeravatar
kaytec
User
Beiträge: 608
Registriert: Dienstag 13. Februar 2007, 21:57

Hallo !

Das letzte mal habe ich Pacman auf dem Atari 2600 (Anfang der 80er) gespielt, doch konnte ich mich nicht mehr so genau an die Levels erinnern. Ein Level ohne Wände ist eines mehr ohne viel Denken :roll:.

Würde ja gerne Kommentare einfügen, doch woher soll ich wissen, was ich da vor 6 Monaten zusammengeschustert habe :K.

Gruß Frank
Xynon1
User
Beiträge: 1267
Registriert: Mittwoch 15. September 2010, 14:22

In dem man die Komentare gleich setzt :wink:
Traue keinem Computer, den du nicht aus dem Fenster werfen kannst.
Xynon auf GitHub
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

kaytec hat geschrieben: Würde ja gerne Kommentare einfügen, doch woher soll ich wissen, was ich da vor 6 Monaten zusammengeschustert habe :K.
Dazu verweise ich auf die ersten beiden Antworten, sowie die erste auf Seite 2 :twisted:
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
Antworten