programmier fehler tkinter "pong"

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.
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

Andere Benennungen gemacht (search replace). Eine Funktion außen rum, damit sich keiner beschwert und übersichtlicher umsortiert, nämlich Konstanten, Variablen, Widgets, Bindings und Spiel Ablauf und alles sieht doch gut aus:

Code: Alles auswählen

import tkinter as tk

class Var: pass

def main():

    # constants ====================

    FIELD_WIDTH = 800
    FIELD_HEIGHT = 400
    BALL_SIZE = 20
    RACKET_SPEEED = 20
    RACKET_HEIGHT = 60
    RACKET_WIDTH = 20

    # variables =====================

    score = Var()
    racket_ypos = Var()
    ball = Var()

    score.left = score.right = 0

    racket_ypos.left = racket_ypos.right = (FIELD_HEIGHT - RACKET_HEIGHT)/2

    ball.x , ball.y = RACKET_WIDTH , (FIELD_HEIGHT - BALL_SIZE)/2
    ball.dx = ball.dy = 15
    ball.playing = 0

    # widgets =======================

    win = tk.Tk();
    win.title("Pong")

    playing_field = tk.Canvas(win, bg='black',height=FIELD_HEIGHT, width=FIELD_WIDTH)
    playing_field.pack()
    ping_pong_ball = playing_field.create_oval(ball.x, ball.y, ball.x+BALL_SIZE, ball.y+BALL_SIZE, width=2, fill='white')
    line = playing_field.create_line(FIELD_WIDTH/2, 0, FIELD_WIDTH/2, FIELD_HEIGHT, width=4, fill="white", dash=(4, 8 ))
    left_racket  = playing_field.create_line(RACKET_WIDTH, racket_ypos.left, RACKET_WIDTH, racket_ypos.left+RACKET_HEIGHT, width=10, fill="white")
    right_racket  = playing_field.create_line(FIELD_WIDTH-RACKET_WIDTH, racket_ypos.right, FIELD_WIDTH-RACKET_WIDTH, racket_ypos.right+RACKET_HEIGHT, width=10, fill="white")
    # Create the score text
    counter=playing_field.create_text(FIELD_WIDTH/2, 20, text='0:0', font=('courier', 20), fill="white")

    # bindings ======================


    def lup(event):
        if racket_ypos.left > RACKET_SPEEED:
            racket_ypos.left=racket_ypos.left-RACKET_SPEEED

    def ldown(event):
        if racket_ypos.left < (FIELD_HEIGHT-RACKET_HEIGHT-RACKET_SPEEED):
            racket_ypos.left=racket_ypos.left+RACKET_SPEEED

    def rmove(event):
        ypos = event.y
        if ypos > 0 and ypos < (FIELD_HEIGHT-RACKET_HEIGHT):  # if in range
            racket_ypos.right = ypos

    def startit(event):
        ball.playing = 1

    # Use the following keys to move the racket
    win.bind('q', lup)
    win.bind('a', ldown)
    win.bind('<B1-Motion>', rmove)
    win.bind('<space>', startit) # start game by hitting space


    # game sequence ===============================================

    def move():

        if wenn_die_runde_nicht_zu_ende_ist():
            bewegt_sich_der_ball_ueber_das_spielfeld()

        if wenn_der_ball_am_oberen_rand_anstoesst():
            dann_soll_der_ball_sich_wieder_nach_unten_bewegen()

        elif wenn_der_ball_am_unteren_rand_anstoesst():
            dann_soll_der_ball_sich_wieder_nach_oben_bewegen()

        if wenn_der_ball_auf_den_linken_schlaeger_knallt():
            dann_soll_er_vom_linken_schlaeger_zurueckprallen()

        elif wenn_der_ball_auf_den_rechten_schlaeger_knallt():
            dann_soll_er_vom_rechten_schlaeger_zurueckprallen()

        if wenn_der_ball_ins_rechte_aus_geht():
            dann_erhoehe_die_trefferzahl_fuer_den_linken_spieler()
            positioniere_den_ball_auf_der_startposition_fuer_den_rechten_spieler()
            und_die_runde_ist_zu_ende()    

        elif wenn_der_ball_ins_linke_aus_geht():
            dann_erhoehe_die_trefferzahl_fuer_den_rechten_spieler()
            positioniere_den_ball_auf_der_startposition_fuer_den_linken_spieler()
            und_die_runde_ist_zu_ende()    
                
        schlaeger_ball_und_treffer_darstellen()
        
        win.after(50, move)


    def wenn_die_runde_nicht_zu_ende_ist():
        return ball.playing

    def bewegt_sich_der_ball_ueber_das_spielfeld():
        ball.x, ball.y = ball.x +ball.dx, (ball.y+ball.dy)
        
    def positioniere_den_ball_auf_der_startposition_fuer_den_linken_spieler():
        ball.x,ball.y,ball.dx = RACKET_WIDTH+10, racket_ypos.left+(RACKET_HEIGHT-BALL_SIZE)/2, abs(ball.dx)

    def positioniere_den_ball_auf_der_startposition_fuer_den_rechten_spieler():
        ball.x,ball.y,ball.dx = FIELD_WIDTH-RACKET_WIDTH-10, racket_ypos.right+(RACKET_HEIGHT-BALL_SIZE)/2,-abs(ball.dx)

    def wenn_der_ball_am_oberen_rand_anstoesst():
        return ball.y > (FIELD_HEIGHT-BALL_SIZE)

    def dann_soll_der_ball_sich_wieder_nach_unten_bewegen():
        ball.y, ball.dy = FIELD_HEIGHT-BALL_SIZE, -ball.dy

    def wenn_der_ball_am_unteren_rand_anstoesst():
        return ball.y < 0

    def dann_soll_der_ball_sich_wieder_nach_oben_bewegen():
        ball.y, ball.dy= 0, -ball.dy

    def wenn_der_ball_ins_rechte_aus_geht():
        return ball.x > (FIELD_WIDTH-BALL_SIZE)

    def wenn_der_ball_ins_linke_aus_geht():
        return ball.x < 0

    def dann_erhoehe_die_trefferzahl_fuer_den_linken_spieler():
        score.left=score.left+1     # increment score for left player

    def dann_erhoehe_die_trefferzahl_fuer_den_rechten_spieler():
        score.right=score.right+1   # increment score for right player

    def wenn_der_ball_auf_den_linken_schlaeger_knallt():
        return ball.x <= RACKET_WIDTH and ball.y>racket_ypos.left and ball.y < (racket_ypos.left+RACKET_HEIGHT)

    def dann_soll_er_vom_linken_schlaeger_zurueckprallen():
        ball.x, ball.dx = RACKET_WIDTH+5, -ball.dx

    def und_die_runde_ist_zu_ende():
        ball.playing = 0  # stop the game

    def wenn_der_ball_auf_den_rechten_schlaeger_knallt():
        return ball.x >= (FIELD_WIDTH-RACKET_WIDTH-BALL_SIZE) and ball.y >= racket_ypos.right and ball.y <= (racket_ypos.right+RACKET_HEIGHT)

    def dann_soll_er_vom_rechten_schlaeger_zurueckprallen():
        ball.x, ball.dx = (FIELD_WIDTH-RACKET_WIDTH-BALL_SIZE-5), -ball.dx

    def schlaeger_ball_und_treffer_darstellen():
        playing_field.coords(ping_pong_ball, ball.x, ball.y, ball.x+BALL_SIZE, ball.y+BALL_SIZE)
        # draw current score
        playing_field.itemconfigure(counter, text=str(score.left) + ":" + str(score.right))
        # Change the positon of the two rackets
        playing_field.coords(right_racket, FIELD_WIDTH-RACKET_WIDTH, racket_ypos.right, FIELD_WIDTH-RACKET_WIDTH, racket_ypos.right+RACKET_HEIGHT)
        playing_field.coords(left_racket, RACKET_WIDTH, racket_ypos.left, RACKET_WIDTH, racket_ypos.left+RACKET_HEIGHT)

    # == start game ======================

    move()  # draw next sequence
    win.mainloop()

main()
Ich meine, das macht man eben so. Zum Schluß benennt man besser und kopiert übersichtlicher um. Aber es dass man es wegwirft, weil es noch nicht übersichtlich geordnet ist, ist Krampf. Also, so ein Programm ist kein Pfusch es fehlten nur noch abschließende Verschönerungsarbeiten.

Allerdings RACKET_WIDTH habe ich nicht richtig benannt. Es handelt sich hierbei um den Abstand vom Spielrand. Die Breite ist 10.
Sirius3
User
Beiträge: 18265
Registriert: Sonntag 21. Oktober 2012, 17:20

@Alfons Mittelmeyer: man kann eine Var-Klasse deklarieren und einfach irgendwelche Attribute nachträglich dranhängen, macht man aber nicht. So hast Du also Deine globalen Variablen in mehrere Gruppen einsortiert, macht die Sache etwas übersichtlicher, man sollte aber erst gar nicht mit globalen Variablen anfangen. Die Sortierung ist aber auch falsch. Es gibt keinen Score mit left und right, sondern einen left_player und einen right_player, die jeweils einen Score und eine Position haben und auch noch ein Canvas-Objekt, das bei Dir noch extra ist. Und da sowohl left_player als auch right_player die selben Attribute haben, ist das die Gelegenheit, daraus EINE Player-Klasse zu machen. Das ist aber für den TE wahrscheinlich noch ein Schritt zu viel, so dass ich schon als erste Antwort geschrieben habe, erst einmal mit Funktionen anzufangen (richtigen und nicht die »def«-Kommentare, die das Programm so schön unstrukturiert machen, wie Du sie hast)
stefanxfg
User
Beiträge: 85
Registriert: Sonntag 2. April 2017, 14:11

Ich kann es nicht verstehen, warum man hier persönlich wird. Das Forum soll doch als Spielwiese für Diskussionen offen sein. Natürlich sollen und können verschiedenste Herangehensweisen diskutiert werden. Dabei können Vor- und Nachteile erörtert werden. Es gibt doch den Spruch: " Es führen viele Wege nach Rom.
Ihr könnt und dürft doch nicht über richtig und falsch urteilen, sondern darauf hinweisen, dass man mit der oder der Methodik durchaus unvorhergesehene Systemverhalten erzeugt. (z.B. globale Variablen definieren, obwohl es schön ist g=9,81 m/s^2 als global zu haben)

Aus meiner Sicht hatte Alfons nicht "Pfuscharbeit" betrieben oder den Code sonderlich umgearbeitet, sondern nur das bis dahin bestehende Programm zum laufen gebracht und das Systemverhalten wie erwartet, richtig gestellt. Kann es nicht sein, dass manch anderer den ursprünglichen Code nicht richtig verstanden haben und das dann als Pfusch bezeichnet hat?

Ich möchte mich an dieser Stelle an die Forumseigner wenden, da ich mit dem Ausschluß von Alfns nicht einverstanden bin. Ich möchte nicht streiten und böses Blut schüren, sondern möchte das hier konstruktiv gearbeitet wird. Aber die Anschludigungen und Beleidungen, man sollte erst einmal die Grundlagen lernen und den Code wegschmeißen, zeigen eher, dass einige so abgestumpft sind, immer dasselbe zu den neuen Programmierern zu erzählen.

Ich bin selbst auch jemand, der erst neu in der Python-Programmierung ist. Mir hat Alfons mit dem GUI-Designer und zahlreichen anderen Vorschlägen zur Seiten gestanden. ich denke, ich habe ihn mit 100000 Fragen genervt, da ich seine Codevorschläge nicht verstanden hatte. Durch ihn habe ich durchaus vieles dazu gelernt, da ich an meinem Projekt gelernt habe und nicht an Codeschnipseln.

Ich hoffe, dass sich der rauhe Ton in dem Forum ändert und konstruktiv gearbeitet wird. Ansonsten muss es eben umgetauft werden in "PYTHON-EXPERT-Forum.de".
Ich hoffe, dass hier auch mal der Besitzer des Forums etwas dazu sagen könnte und nicht nur die Moderatoren.

Im Übrigen appeliere ich an die Moderatoren auch mal an ihre Anfänge zu denken und Alfons wieder zuzulassen. Er zeigt euch , dass andere Wege, andere Gesichtspunkte, andere Hernagehensweisen möglich sind. Bitte verwerft nicth alles. Es geht auch anders, Wie gesagt, viele Wege führen ans Ziel.
Benutzeravatar
kbr
User
Beiträge: 1507
Registriert: Mittwoch 15. Oktober 2008, 09:27

Gegen

Code: Alles auswählen

GRAVITY_CONSTANT = 9.81  # m/s^2
auf globaler Ebene ist gar nichts einzuwenden. Problematisch wird es, sobald es sich um veränderbare Inhalte handelt. Dann wird ein Programm potentiell fragil, da die Gefahr von Seiteneffekten zunimmt. Code dieser Art ist schwerer zu debuggen und wird, wenn er mit der Zeit an Umfang zunimmt, im Extremfall sogar unwartbar.

Erstaunlicherweise musste dieses hier immer wieder durchdiskutiert werden, solange, bis einige wohl dünnhäutig wurden, da auch der Anspruch bestand, gerade Anfänger keine Lösungen zu zeigen, die erfahrungsgemäß problematisch sind.

Was im Forum hinter den Kulissen geschehen ist, vermag ich nicht zu sagen. Ich bin jedoch in einem anderen Forum (ein B2B Forum, das mit Programmieren überhaupt nichts zu tun hat) Moderator und wir hatten einmal das Problem sehr rüder Inhalte, wobei ich auch per PM angegangen wurde. Wir konnten mit der Situation dann umgehen, in Folge aber haben einige Moderatoren ihre Tätigkeit niedergelegt. Machen waren vielleicht auch nicht darauf vorbereitet, dass Kommunikationsstil und Moderationsmöglichkeiten in einem Forum nicht mit denen in einer persönlichen Gesprächsrunde deckungsgleich sind.

Ich finde es gehört zur Netiquette sich in einem Forum so zu verhalten, dass ein Moderator erst gar nicht in Verlegenheit gebracht wird, moderieren zu müssen.
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

stefanxfg hat geschrieben:Ich kann es nicht verstehen, warum man hier persönlich wird. Das Forum soll doch als Spielwiese für Diskussionen offen sein. Natürlich sollen und können verschiedenste Herangehensweisen diskutiert werden. Dabei können Vor- und Nachteile erörtert werden. Es gibt doch den Spruch: " Es führen viele Wege nach Rom.
Ihr könnt und dürft doch nicht über richtig und falsch urteilen, sondern darauf hinweisen, dass man mit der oder der Methodik durchaus unvorhergesehene Systemverhalten erzeugt. (z.B. globale Variablen definieren, obwohl es schön ist g=9,81 m/s^2 als global zu haben)

....

Im Übrigen appeliere ich an die Moderatoren auch mal an ihre Anfänge zu denken und Alfons wieder zuzulassen. Er zeigt euch , dass andere Wege, andere Gesichtspunkte, andere Hernagehensweisen möglich sind. Bitte verwerft nicth alles. Es geht auch anders, Wie gesagt, viele Wege führen ans Ziel.
Mir ist nicht klar wovon du da redest. Niemand hat Alfons irgendwo rausgeworfen. Das mag mancher sich wuenschen, aber es ist ein grosser Schritt, und er ist schlicht nicht gegangen worden.
stefanxfg
User
Beiträge: 85
Registriert: Sonntag 2. April 2017, 14:11

Hallo __deets__,

ich bin mit Alfons noch im Kontakt. Mir hat er mitgeteil, dass er sein Login gesperrt ist. Daher habe ich mich hier zu Wort gemeldet. Aber nicht um ihn zu verteidigen, sondern um zu sagen, dass ich mir die Art und Weise der Diskussionen nicht gefällt. Jedenfalls kann es nicht sein, dass man als Neuling für offentsichtliche Fehler an den Pranger gestellt wird.
Ich möchte und werde darüber nicht weiter diskutieren. Ich lese jedenfalls solche Kommentare mit großem Bedauern.
Benutzeravatar
snafu
User
Beiträge: 6862
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Hier besteht eben ein gewisser Anspruch, dass man tendenziell eher hochwertigen Code vermitteln möchte. Anfänger sollen von erfahrenen Programmierern lernen können. Alfons untergräbt dieses Prinzip völlig, weil die meisten seiner Vorschläge an sich funktionieren mögen, aber stilistisch unterirdisch sind. Und nachdem wohl niemand mehr so wirklich auf seine Monologe im TKinter-Forum eingegangen ist, fing er an sich in fremde Threads einzumischen. Mal als Beispiel: Normalerweise sollten Doppelposts die Ausnahme bleiben. Alfons hingegen knallt regelmäßig Fünfachposts raus. Und Alfons verstößt auch anderweitig IMHO völlig bewusst gegen hier geltende Verhaltensregeln. Sofern er tatsächlich gesperrt wurde, finde ich das ehrlich gesagt in diesem Fall nachvollziehbar. Zensur muss manchmal sein, wenn Freundlichkeit und Offenheit schamlos ausgenutzt wird. Aus meiner Sicht ist Alfons ein klassischer Troll, der zur Zeit äußerst erfolgreich vorgeht, da er es schafft, das Klima hier zunehmend zu vergiften.
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Wenn
stefanxfg hat geschrieben:Hallo __deets__,

ich bin mit Alfons noch im Kontakt. Mir hat er mitgeteil, dass er sein Login gesperrt ist. Daher habe ich mich hier zu Wort gemeldet. Aber nicht um ihn zu verteidigen, sondern um zu sagen, dass ich mir die Art und Weise der Diskussionen nicht gefällt. Jedenfalls kann es nicht sein, dass man als Neuling für offentsichtliche Fehler an den Pranger gestellt wird.
Ich möchte und werde darüber nicht weiter diskutieren. Ich lese jedenfalls solche Kommentare mit großem Bedauern.
Dafuer, das du ihn nicht verteidigen moechtest, springst du recht nachdruecklich in die Bresche fuer ihn.

Das er dir persoenlich geholfen hat ist schoen fuer dich. Das er aber gleichzeitig nun ein leuchtendes Beispiel fuer eine gelungene Diskussionskultur ist entbehrt nicht einer gewissen Ironie. Alfons ist alles andere als ein unbschriebenes Blatt wenn es um die Herabsetzung der Ansaetze anderer geht. Insofern muss er es auch aushalten, wenn es ihm mal entgegenschallt, wie er es in den Wald hineinrief.

Ob die Disukssionskultur im allgemeinen hier der Verbesserung bedarf, steht auf einem anderen Blatt. Das mag sein. Auf der anderen Seite zeugt deine Haltung nicht von viel Verstaendnis fuer die Position derjenigen hier, die ebenfalls unter viel Aufwand Antworten auf die Fragen vieler Leute hier geben.

Zum einen ist hier halt der Anspruch, nicht "irgendwie" etwas zum laufen zu bringen. Genausowenig wie dir ein Installateur-Meister anerkennend auf die Schulter klopft, wenn du die Gastherme mit Klebeband und Spucke an der Wand befestigt hast, und dir dringend anraet, das vernuenftig zu machen, so versuchen auch wir hier, die Anfaenger auf den richtigen Weg zu setzen. Und ja, dazu gehoert auch die Ansagen, das etwas mal einfach Mist ist.

Zum anderen gibt es hier einen deutlichen Aufwaertstrend (ich mache dafuer den Raspberry PI "verantwortlich") von Leuten, die statt anfangen einfach abgreifen wollen. Wir sollen hier eine Art Programmierbasar darstellen, bei dem einen unverzueglich und natuerlich kostenlos geholfen wird. Ein Wunsch, das richtige Programmieren zu erlernen, ist nicht wirklich zu erkennen.

Das Tag fuer Tag immer wieder zu erleben, und damit umzugehen ohne den Glauben daran zur verlieren, das hier jemand Hilfe zur Selbsthilfe moechte, ist halt auch nicht so ganz einfach. Das rechtfertigt keine Unverschaemtheit, aber eine gewisse Zurueckhaltung nicht gleich alles frei Haus zu liefern und zu verlangen, dass die Leute ernsthaftes Interesse zeigen, durchaus.
Benutzeravatar
Damaskus
Administrator
Beiträge: 1000
Registriert: Sonntag 6. März 2005, 20:08
Wohnort: Schwabenländle

stefanxfg hat geschrieben:Hallo __deets__,

ich bin mit Alfons noch im Kontakt. Mir hat er mitgeteil, dass er sein Login gesperrt ist.

Der User Alfons Mittelmeyer wurde von mir für unbestimmte Zeit gesperrt.
Antworten