Space Invaders

Hier werden alle anderen GUI-Toolkits sowie Spezial-Toolkits wie Spiele-Engines behandelt.
Antworten
Newcomer
User
Beiträge: 131
Registriert: Sonntag 15. Mai 2011, 20:41

Hi, ich habe space Invaders mit pygame realsisiert (-;
es ist hier:
http://www.python-forum.de/pastebin.php?mode=view&s=230
Nur noch ne Frage:
1. Wie findet ihr den Code? (ist mein erstes spiel)
2. Wie kann man Bilder hochladen????
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Puh... zum Code kann man viel sagen.

@2.) Du musst das Bild auf einen Webspace laden und dann hier verlinken. imageshack und Konsorten bieten sich da an.

@Code: Ich habe ihn nur mal überflogen, daher sind folgende Dinge nicht vollständig:

- feste Pfade im Code - damit wird Dein Spiel de facto unspielbar bei anderen Usern und die Wartung erschwert sich.

- krude Namen. Was ist ``Patrone_e`` im Gegensatz zu ``Patrone``?

- die Event-Abfrage in einem Spieler-Objekt halte ich für eher unelegant. Es ist ja logisch, dass ein Spiel auf Tasten reagieren muss - aber dahinter steckt ja eher der Spieler im Sinne von ``Benutzer`` und nicht des Objekts, welches einen Avatar repräsentiert. Aber darüber mag man streiten können. In Sinne der Unabhängigkeit von GUI und Logik wäre meine Ansicht aber vertretbar.

- Wenn du den Zähler in einer Schleife nicht brauchst, dann bietet sich ``_`` als Name an:

Code: Alles auswählen

# bei dir:
    for i in range(gegner):
        e_g.add(Enemy((pygame.display.get_surface().get_width()/2,50),pat_g))
# lesbarer
    for _ in range(gegner):
        pass
Bei Python2 solltest Du auch eher ``xrange`` verwenden.

- Du solltest Die ``main``-Funktion folgendermaßen aufrufen.

Code: Alles auswählen

if __name__ == "__main__":
    main()
- vermeide *-Importe!

- viele Magic Numbers. Wieso setzt Du Attribute auf fixe Werte? Default-Werte sind ja ok, aber wieso kan man die bei der Erstellung eines Objekts nicht gleich festlegen?

Code: Alles auswählen

class Player(...):
    def __init__(self, image, leben=100):
        self.image = image
        self.leben = leben
Ähnliches kann man bei den Zufallszahlen (in ``Enemy``) beobachten.

- Du mischt Deutsch und Englisch bei Deinen Namen. Du solltest das konsolidieren.

- Am Schluss das wichtigste: Es fehlt jegliche Dokumentation! Ohne die ist der ganze Code quasi wertlos, da Du selber in wenigen Wochen den Überblick verlieren wirst. Python bietet Dir doch sogar mit den Doc-Strings ein eingebautes Sprachmittel. Nutze das!
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
deets

Auch von mir ein paar Anmerkungen:

- die Vererbung fuer Patrone & Patrone_e ist voellig ueberfluessig. Die verschiedenen Bilder und Bewegungsrichtungen besser als Parameter geloest
- die verschiedenen update-Methoden mit unterschiedlichen Signaturen sind ungluecklich. Man bemueht sich ueblicherweise in einer Game-Engine darum, alle Objekte gleich zu behandeln. Natuerlich muss der Spieler auf Mausevents reagieren - aber es koennte ja auch ein besonders fieser Gegner immer alle Bewegungen mit machen.
- der Player macht zu viel! Sowas wie eine game-over-logik gehoert nach draussen, ausserhalb des game-loops. Wenn zB der Spieler eine bestimmte exception wirft, oder einfach seinen Zustand aendert, dann geht der game-loop hin & macht, was auch immer game-over bedeutet. Nicht der Spieler selbst!
- ueblicherweise abstrahiert man key & sonstige Input-events, und erzeugt spiel-spezifische events wie zB move_left, move_right usw. Damit wird dann auch dein main-loop viel einheitlicher.
deets

Hyperion hat geschrieben: - Am Schluss das wichtigste: Es fehlt jegliche Dokumentation! Ohne die ist der ganze Code quasi wertlos, da Du selber in wenigen Wochen den Überblick verlieren wirst. Python bietet Dir doch sogar mit den Doc-Strings ein eingebautes Sprachmittel. Nutze das!
Da widerspreche ich. Kommentare sind IMHO voellig ueberbewertet, besonders was doc-strings angeht. Ich dokumentiere trickreiche Code-Stellen, die etwas auf besonders hinterrueckse Art machen (natuerlich nur, weil es sich nicht anders machen laesst), und zwar inline. Und wenn es denn etwas mehr sein soll, dann ala Sphinx wirkliche Dokumentation, welche Konzepte und Zusammenhaenge verdeutlicht.

Denn Kommentare ala "diese Methode macht X und Y" rotten ueblicherweise mit einer extrem niedrigen Halbwertszeit. Und sind dann *noch* verwirrender.

Ausnahmen sind IMHO Bibliotheken, die klare und auf laengere Sicht stabile Schnittstellen bieten sollen. Aber auch da sind Beispiele & konzeptionelle Dokumentation im Zweifel mehr wert finde ich.
lunar

@deets: In Python bietet nur Dokumentation eine vollständige Beschreibung einer Schnittstelle, inklusive Typen und Ausnahmen, denn diese Informationen kann man im Gegensatz zu beispielsweise Java nicht aus der Signatur ablesen. Insofern kann eine Bibliothek eigentlich nicht auf vollständige und ausführliche Docstrings aller öffentlichen Objekte verzichten, Beispiele und konzeptionelle Dokumentation können und müssen diese sicherlich ergänzen, aber bestimmt nicht ersetzen. Ansonsten sehe ich persönlich es als Qualitätsmerkmal, wenn auch interne Schnittstellen sauber dokumentiert sind. Das Argument, Docstrings könnten rotten, lasse ich nicht gelten. Schließlich tun sie das nicht von selbst, sondern nur, wenn der Entwickler etwas ändert, ohne den Docstring zu aktualisieren. Insofern sagen verrottete Docstrings ziemlich viel aus über die Qualität eines Projekts und die Entwickler, welche die Docstrings haben verrotten lassen :)

Zudem zwingt das Schreiben von Docstrings dazu, mal wirklich über Schnittstellen und Typen nachzudenken, und kann dem OP insofern durchaus helfen, mehr Struktur in sein Programm zu bekommen.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

@deets: Ich habe nicht gesagt, dass man alles über DocStrings lösen muss ;-)

Bei kleinen Methoden mag es ja sogar so sein, dass man auf einen DocString verzichten kann - auch wenn ich es nicht für falsch halte, auch dort die Aufgabe und Signatur klar zu machen (wie lunar ja auch anmerkte). Aber bei einer Klasse habe ich ja nur den Namen - weiß man damit wirklich, zu was diese gut ist? Da eine Klasse ja auch nichts "tut" wird es imho noch schwieriger sich vorzustellen, was man damit so anstellen kann bzw. wozu sie gedacht ist.

Und für ein Spiel in diesem Umfang braucht es imho keine separate Doku mittels Sphinx ;-) Aber man sollte einem Anfänger doch noch vermitteln dürfen, dass Dokumentation wichtig ist :P
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
Newcomer
User
Beiträge: 131
Registriert: Sonntag 15. Mai 2011, 20:41

Danke für die Verbesserungsvorschläge :D. Werd versuchen sie gleich umzusetzen
deets

@lunar

Ueber Schnittstellen und Typen denke ich durch testgetriebene Entwicklung nach - prosa schreiben finde ich dazu ungeeignet.

Natuerlich ist eine proper dokumentierte Funktionalitaet besser als dieselbe ohne. Aber in der Realitaet findet sich eben sehr oft stattdessen eine falsch dokumentierte Funktionalitaet.

Nur ist gute Dokumentation schreiben auch nicht trivial. Wieviel Kontext setzt du denn vorraus? Muss man schon das Projekt kennen, sind Begriffe eingefuehrt, wenn nicht, muessen die irgendwo als Glossar bekannte gemacht werden? wer pflegt dieses Glossar? Und nur weil jemand programmieren kann, kann er noch lange nicht gut dokumentieren.

Fuer meine persoenliche Erfahrung kann ich einfach sagen: Dokumentation kann einen Einstieg in eine Codebasis bestenfalls erleichtern. Aber am Ende zaehlt eh der Code, und ich habe mir lieber selbst einen Ueberblick verschafft, statt mich auf falsche Angaben zu verlassen. Da hilft auch alle schoene Theorie nicht.
Antworten