Seite 1 von 1
Canvas-Bug (?)
Verfasst: Sonntag 17. Juni 2012, 09:47
von raiminator
Moin,
Ich hatte angefangen ein kleiner Fußballspiel zu programmieren, wo man mit Pfeiltasten bzw. WASD seine Spieler bewegen kann. mit einem Spieler funktioniert das auch soweit, aber wennn ich ihn nach links, linksoben oder linksunten bewege zieht er (warum auch immer) graue Linien hinter sich.
Hier der Code:
Code: Alles auswählen
import Tkinter as tk
from player import *
pressLeft,pressRight,pressUp,pressDown = False,False,False,False
posX,posY = 100,100
running = False
ball = False
main = tk.Tk()
# Bilder
img_pitchBG = tk.PhotoImage(file='img/pitch.gif')
# GUI
main.state('zoomed')
pitch = tk.Canvas(main, width=1000, height=600)
pitch.create_image(500, 300, image=img_pitchBG)
pitch.place(x=100, y=50, width=1000, height=600)
player1 = Player(pitch, '#ff0000', True, 100, 100)
def up(e):
global pressUp
pressUp = True
def down(e):
global pressDown
pressDown = True
def left(e):
global pressLeft
pressLeft = True
def right(e):
global pressRight
pressRight = True
def r_up(e):
global pressUp
pressUp = False
def r_down(e):
global pressDown
pressDown = False
def r_left(e):
global pressLeft
pressLeft = False
def r_right(e):
global pressRight
pressRight = False
def update():
global posX,posY
if pressLeft:
posX -= 1
if pressRight:
posX += 1
if pressUp:
posY -= 1
if pressDown:
posY += 1
p.setCoords(posX, posY)
main.after(1, update)
def start():
global running,ball
ball = not(ball)
player1.setBall(ball)
if running:
return
running = True
update()
main.bind('<KeyPress-w>', up)
main.bind('<KeyPress-s>', down)
main.bind('<KeyPress-a>', left)
main.bind('<KeyPress-d>', right)
main.bind('<KeyRelease-w>', r_up)
main.bind('<KeyRelease-s>', r_down)
main.bind('<KeyRelease-a>', r_left)
main.bind('<KeyRelease-d>', r_right)
button_start = tk.Button(main, text='Starten', command=start)
button_start.pack()
main.mainloop()
und die Datei player.py:
Code: Alles auswählen
class Player:
def __init__(self, pitch, color, team, x, y):
self.pitch = pitch
r = 8
self.id_circle = self.pitch.create_oval(x-r, y-r, x+r, y+r, fill=color, outline='#000000', width=1)
self.x = x
self.y = y
def setCoords(self, x, y):
self.pitch.coords(self.id_circle, x-r, y-r, x+r, y+r)
self.x = x
self.y = y
def setBall(self, ball):
if ball:
self.pitch.itemconfig(self.id_circle, outline='#eeeeee', width=4)
r = 12
self.pitch.coords(self.id_circle, self.x-r, self.y-r, self.x+r, self.y+r)
else:
self.pitch.itemconfig(self.id_circle, outline='#000000', width=1)
r = 8
self.pitch.coords(self.id_circle, self.x-r, self.y-r, self.x+r, self.y+r)
Der Spieler wird auf dem Feld als roter Kreis mit schwarzem Rahmen angezeigt.
Die Methode setBall ist dazu da das Aussehen des Players zu ändern, wenn er den Ball bekommt [setBall(True)]. dann sollte er einen grauen rand bekommen und größer werden. Bei setBall(False) wird er wieder kleiner und bekommt den schewarzen Rahmen zurück. Das Klappt auch soweit.
Wenn er aber gerade den grauen Rahmen hat und ich ihn nach links bewege zieht er diesen grauen Strich hinter sich.
Woher kommt das und wie kann ich das wieder beheben?
Danke, Grüße raiminator
Re: Canvas-Bug (?)
Verfasst: Sonntag 17. Juni 2012, 10:31
von BlackJack
@raiminator: Was auch immer das Problem ist, bei den Sternchen-Importen, den vielen ``global``\s, und Namen wie `p` oder `i` hast Du Grössere.

Re: Canvas-Bug (?)
Verfasst: Sonntag 17. Juni 2012, 15:01
von raiminator
@BlackJack: ich hoffe mal mit dem Code oben hast du jetzt keine
Probleme mehr

Re: Canvas-Bug (?)
Verfasst: Sonntag 17. Juni 2012, 15:15
von Hyperion
raiminator hat geschrieben:@BlackJack: ich hoffe mal mit dem Code oben hast du jetzt keine
Probleme mehr

Äh... was hat sich denn da essenziell geändert? Ich sehe immer noch einen *-Import und lauter `globals`...
Zudem wäre es ja trivial aus dem Player-Modul das einzig vorhandene Objekt explizit zu importieren
Des Weiteren solltest Du Dich mehr an PEP8 halten; Funktionen werden klein und mit Unterstrichen benannt, nicht "mixedCase". Außerdem würde ich statt Gettern und Settern eher mit Properties arbeiten; das ist pythonischer
Zudem hast Du viel zu viel Copy&Paste-Code in Deinem Programm. Ein einfaches Beispiel ist dieses hier:
Code: Alles auswählen
main.bind('<KeyPress-w>', up)
main.bind('<KeyPress-s>', down)
main.bind('<KeyPress-a>', left)
main.bind('<KeyPress-d>', right)
main.bind('<KeyRelease-w>', r_up)
main.bind('<KeyRelease-s>', r_down)
main.bind('<KeyRelease-a>', r_left)
main.bind('<KeyRelease-d>', r_right)
Wieso drückst Du das nicht mittels einer geeigneten Datenstruktur und einer Schleife aus?
Code: Alles auswählen
bindings = (
('<KeyPress-w>', up),
('<KeyPress-s>', down),
# usw.
)
for name, func in bindings:
main.bind(name, func)
Das gezeigt ist aber an sich eher unnötig komplex. Wenn Du doch bei einem Tastendruck eine Funktion aufrufen kannst, wieso muss es denn immer eine separate sein, die dann dazu noch den Wert einer globalen Variablen ändert? Viele einfacher und imho offensichtlicher wäre es doch, immer die gleiche Funktion aufzurufen und dieser per Parameter mitzuteilen, *welche* Taste gedrückt wurde!
Re: Canvas-Bug (?)
Verfasst: Sonntag 17. Juni 2012, 17:42
von raiminator
Toll. ich verstehe ja dass diese Community Probleme mit Leuten hat, die noch an andere Programmiersprachen gewöhnt sind, aber meine eigentliche Frage war ja, ob jemand weiß woher dieser Bug (?) beim Canvas kommt.
Re: Canvas-Bug (?)
Verfasst: Sonntag 17. Juni 2012, 18:28
von EyDu
Hallo.
raiminator hat geschrieben:Toll. ich verstehe ja dass diese Community Probleme mit Leuten hat, die noch an andere Programmiersprachen gewöhnt sind, aber meine eigentliche Frage war ja, ob jemand weiß woher dieser Bug (?) beim Canvas kommt.
Damit hat hier sicher keiner Probleme, da die meisten hier mehrere andere Programmiersprachen beherrschen. Ganz unabhängig davon sie die Anmerkungen jedoch sprachunabhängig. Auch in anderen Sprachen müllt man sich nicht den Namensraum zu, verwendet globale Variablen und kopiert Code.
Sieh es doch aus einem anderen Blickwinkel: du möchtest Hilfe zu einen Problem und solltest daher die Frage für die Helfenden so einfach wie möglich stellen. Nur wenige haben so viel Zeit und Lust sich durch schlechten Code zu arbeiten. Neben vielen Verbesserungen an deinem Programm erhöht guter Code also auch noch die Chancen auf eine Antwort.
Sebastian
Re: Canvas-Bug (?)
Verfasst: Sonntag 17. Juni 2012, 18:34
von deets
Dazu gesellt sich auch noch, dass der gezeigte Code nicht laeuft - mal heisst es player1, mal p, und das benutzte Bild sollte man vielleicht auch zur Verfuegung stellen - schliesslich macht es einen Unterschied, ob man da was zuerst in den Hintergrund malt oder nicht.
Re: Canvas-Bug (?)
Verfasst: Montag 18. Juni 2012, 14:08
von wuf
Hi raiminator
Wie schon deets erwähnte enthält dein erstes Skript einige Bremsen. Habe es soweit angepasst damit es für mich startfähig ist.
Main:
Code: Alles auswählen
import Tkinter as tk
from player import *
pressLeft,pressRight,pressUp,pressDown = False,False,False,False
posX,posY = 100,100
running = False
ball = False
main = tk.Tk()
# Bilder
img_pitchBG = tk.PhotoImage() #file='img/pitch.gif')
# GUI
#main.state('zoomed')
pitch = tk.Canvas(main, width=1000, height=600, bg='steelblue')
pitch.pack()
pitch.create_image(500, 300, image=img_pitchBG)
player1 = Player(pitch, '#ff0000', True, 100, 100)
def up(e):
global pressUp
pressUp = True
def down(e):
global pressDown
pressDown = True
def left(e):
global pressLeft
pressLeft = True
def right(e):
global pressRight
pressRight = True
def r_up(e):
global pressUp
pressUp = False
def r_down(e):
global pressDown
pressDown = False
def r_left(e):
global pressLeft
pressLeft = False
def r_right(e):
global pressRight
pressRight = False
def update():
global posX,posY
if pressLeft:
posX -= 1
if pressRight:
posX += 1
if pressUp:
posY -= 1
if pressDown:
posY += 1
player1.setCoords(posX, posY)
main.after(1, update)
def start():
global running,ball
ball = not(ball)
player1.setBall(ball)
if running:
return
running = True
update()
main.bind('<KeyPress-w>', up)
main.bind('<KeyPress-s>', down)
main.bind('<KeyPress-a>', left)
main.bind('<KeyPress-d>', right)
main.bind('<KeyRelease-w>', r_up)
main.bind('<KeyRelease-s>', r_down)
main.bind('<KeyRelease-a>', r_left)
main.bind('<KeyRelease-d>', r_right)
button_start = tk.Button(main, text='Starten', command=start)
button_start.pack()
main.mainloop()
Klasse Player:
Code: Alles auswählen
class Player:
def __init__(self, pitch, color, team, x, y):
self.pitch = pitch
self.r = 8
self.id_circle = self.pitch.create_oval(x-self.r, y-self.r, x+self.r,
y+self.r, fill=color, outline='#000000', width=1)
self.x = x
self.y = y
def setCoords(self, x, y):
self.pitch.coords(self.id_circle, x-self.r, y-self.r, x+self.r,
y+self.r)
self.x = x
self.y = y
def setBall(self, ball):
if ball:
self.pitch.itemconfig(self.id_circle, outline='#eeeeee', width=4)
r = 12
self.pitch.coords(self.id_circle, self.x-r, self.y-r, self.x+r, self.y+r)
else:
self.pitch.itemconfig(self.id_circle, outline='#000000', width=1)
r = 8
self.pitch.coords(self.id_circle, self.x-r, self.y-r, self.x+r, self.y+r)
Habe noch eine Frage betreffs Bedienung über die Tastatur. So wie ich sehe bewegst du den Spieler mit den Tasten 'a', 'w', 's', 'd'. Wie gedenkst du einen der 11 bzw. insgesamt 22 Spieler über die Tastatur zu selektieren?
Gruß wuf

Re: Canvas-Bug (?)
Verfasst: Dienstag 19. Juni 2012, 15:53
von raiminator
Hatte ich mir so vorgestellt dass man es zu zweit spielt und jeder außer ASDW bzw. Pfeiltasten eine Taste zum Spieler wechseln hat, eine zum Schießen und zum Passen (vllt. q, e, Leertaste und linke Maustaste, rechte Maustaste, Enter)
Naja, das Programm bis jetzt war ja nur der Anfang.
Zu den Globals:
ich habe gerade mal versucht, das Programm so zu ändern dass es keine Globals mehr gibt. ball und running sind mehr oder weniger unnötig für das weitere Programm, die wären sowieso noch weggekommen.
Aber ohne pressUp, pressDown... und posX, posY komme ich einfach nicht aus.. muss man wirklich alle Globals vermeiden oder hat jemand einen Vorschlag wie man das umschreiben könnte?
Re: Canvas-Bug (?)
Verfasst: Dienstag 19. Juni 2012, 16:15
von Hyperion
raiminator hat geschrieben:
ich habe gerade mal versucht, das Programm so zu ändern dass es keine Globals mehr gibt. ball und running sind mehr oder weniger unnötig für das weitere Programm, die wären sowieso noch weggekommen.
Man entwirft Programme eigentlich so, dass man erst gar keine `globals` benötigt
raiminator hat geschrieben:
Aber ohne pressUp, pressDown... und posX, posY komme ich einfach nicht aus.. muss man wirklich alle Globals vermeiden oder hat jemand einen Vorschlag wie man das umschreiben könnte?
Ja, indem Du diese einfach an die Funktion übergibst, bei der sie gebraucht werden; wenn sie einen Zustand besitzen, kann man diese in eine Klasse oder auch eine simple Datenstruktur wie ein Dict packen und dieses entsprechend in einer Funktion auslesen. Es gibt da viele Möglichkeiten; mir war es jetzt zu mühsam, mir Deinen speziellen Code anzugucken und zu überlegen, wie man das da am besten macht.
Re: Canvas-Bug (?)
Verfasst: Dienstag 19. Juni 2012, 18:18
von raiminator
Hyperion hat geschrieben:
Man entwirft Programme eigentlich so, dass man erst gar keine `globals` benötigt
'Man' vielleicht, wenn du damit erfahrenere Python-Programmier meinst

An die FUnktion übrgeben hatte ich ja versucht, aber wie soll ich eine Funktion schreiben, die sich selbst updatet, und gleichzeitig auf Knopfdruck reagiert bzw. Parameter übergeben bekommt? Das ist ja mein Problem..
Re: Canvas-Bug (?)
Verfasst: Dienstag 19. Juni 2012, 20:55
von wuf
Hi raiminator
Danke für deine Antwort. Ich finde deine Idee interessant und mutig ein Fussball-Spiel in Python & Tkinter zu programmieren. Das Projekt könnte ein grösseres Ausmass annehmen. Sollte das Projekt auch nicht fertig werden kannst du dabei sicher viel Erfahrung sammeln. Learning by doing ist auch ein Weg sich Stoff anzueignen. Bin zwar ein völliger Laie was Fussball anbelangt aber es gibt hierzu ja viele Informationen auf dem Internet wo man sich schlau machen kann. Da mich die Spiel-Programmierung auch ein wenig interessiert habe ich einmal versucht deine Idee auf MVC-Basis als Prototyp zu realisieren. Vielleicht wird dir der Anblick meines Skriptes ein wenig Kopfweh verursachen. Speziell der Teil unter 'move_key_bindings'. Das MVC setzt sich ja aus drei Hauptklassen zusammen. Das sind die Model-View-Controller Klassen. Da dein Projekt ja etwas Großes werden könnte wäre es sinnvoll auf der MVC-Basis aufzubauen um den Überblick nicht zu verlieren. Das Projekt könnte noch besser strukturiert werden indem es auf mehrere Dateien aufgeteilt würde z.B. football_model.py, football_view.py, football_control.py, football_config.py, football_images.py usw. Diese Dateien könnten untereinander wo sie nötig sind importiert werden. Das Skript muss natürlich noch wesentlich erweitert werden um alle Spieler zu integrieren! Hier wäre mein Prototyp verfügbar:
MVC-Football Prototype
Das Skript ist ein erster Wurf und kann sicher noch wesentlich verbessert werden! Noch viel Spass beim Programmieren.
Gruß wuf

Re: Canvas-Bug (?)
Verfasst: Mittwoch 20. Juni 2012, 14:14
von raiminator
Schönes Skript, aber viele Sachen verstehe
ich noch nicht so ganz
Braucht man da wirklich soo viele Klassen? bzw. wozu MVC oder wo ist der Sinn davon?
----------
Ich habe jetzt einfach mal von vorne angefangen, und versuche mal alles mit Klassen zu realisieren.
Re: Canvas-Bug (?)
Verfasst: Mittwoch 20. Juni 2012, 15:57
von wuf
Hier vorab etwas über MVC:
MVC-Theorie
Gruß wuf

Re: Canvas-Bug (?)
Verfasst: Donnerstag 21. Juni 2012, 13:10
von raiminator
@wuf:
Ok... ich denke mal dass das eher was für erfahrenere Programmierer ist, deshalb lasse ich erstmal die Finger davon

ich bin jetzt fast so weit wie du, ich poste den Code dann bald nochmal

Gruß raiminator
Re: Canvas-Bug (?)
Verfasst: Donnerstag 21. Juni 2012, 13:45
von wuf
Hi raiminator
raiminator hat geschrieben:Ok... ich denke mal dass das eher was für erfahrenere Programmierer ist, deshalb lasse ich erstmal die Finger davon

OK raiminator verstehe ich voll. Jeder sollte sein Projekt so lösen wie es seine momentanen Kenntnisse ermöglichen.
Betreffs MVC:
Der oder mein Hauptgrund hierfür ist sollte ich den grafischen Teil jetzt auf Tkinter basieren einmal durch ein anderes GUI-Toolkit wie Pygame, wxPython oder PyQt ersetzen muss ich nur die Klassen erneuern die das GUI-Handling erledigen. Die Model-, Control-Klasse und Konfiguration kann fast 1:1 ungeändert übernommen werden.
raiminator hat geschrieben:ich bin jetzt fast so weit wie du, ich poste den Code dann bald nochmal

Super! Viel Spass.
Gruß wuf

Re: Canvas-Bug (?)
Verfasst: Donnerstag 21. Juni 2012, 16:00
von raiminator
Gut, dann habe ich das verstanden. Da ich aber bis jetzt nur Tkinter "
beherrsche" reicht mir das halt erstmal so aus

Re: Canvas-Bug (?)
Verfasst: Freitag 22. Juni 2012, 15:04
von raiminator
Re: Canvas-Bug (?)
Verfasst: Samstag 23. Juni 2012, 08:18
von wuf
Hi raiminator
Wie ich sehe ist dein Fussballspiel schon mächtig gewachsen. Wo sind die Globals geblieben? Du hast es geschafft sie zu eliminieren. Super! Habe eine Frage. Ist die Spieleraufstellung wie du sie gewählt hast eine Standardaufstellung für Fussballspiele? Interessiert mich da ich selber etwas in diese Richtung programmiere. Ich nehme an, dass du deinen Spielern auf dem Felde noch einen sichtbaren Tag anheftest (Nr., Buchstabe oder Name) damit du weisst wo sich welcher Spieler befindet? Wie ist die Bedienung?
Gruß wuf

Re: Canvas-Bug (?)
Verfasst: Samstag 23. Juni 2012, 11:38
von raiminator
ich als
Werder-Fan nehme wohl immer [4, 1, 2, 1, 2], am häufigsten wird aber
[4, 2, 3, 1] oder [4, 2, 2, 2] verwendet

muss man dann halt oben in der Konfiguration ändern.
Das mit dem Tag... werde ich noch machen, jetzt aber erstmal Spieler wechseln- und passen-Funktion
