@Benni1000: Hast Du das Spiel mal eine zweite Runde gespielt? Dann sollte Dir ein Fehler auffallen.
Formatierung und Namensgebung hält sich nicht an
PEP 8 -- Style Guide for Python Code.
Code auf Modulebene sollte sich auf die Definition von Konstanten im weitesten Sinne beschränken. Also Werte, Funktionen, Klassen, und so weiter. Anderer Code sollte in einer Hauptfunktion verschwinden die nur ausgeführt wird, wenn ``if __name__ == '__main__':`` gilt. Dann kann man das Modul auch importieren ohne dass gleich das Spiel los läuft. Zum Beispiel um einzelne Funktionen und Klassen testen oder wiederverwenden zu können.
Abkürzungen die nicht allgemein bekannt sind als Namen sind eine schlechte Idee.
Diese Unmengen von `pygame.image.load()` sind unglaublich ineffizient. Jedes mal werden Bilddateien geladen um sie zu zeichnen statt sie nur einmal zu laden und dann aus dem Speicher auf die Anzeige zu „blitten”. Teilweise werden Bilder geladen um ihre Abmessungen zu ermitteln nur im das *selbe* Bild gleich *noch einmal* zu laden um es zu „blitten”. Und das für jeden Frame — das ist Wahnsinn.
``if`` ist keine Funktion, also sollte man es auch nicht so schreiben das es wie eine aussieht. Klammern um die Bedingung sind unnötig und nach einem Schlüsselwort steht gewöhnlich ein Leerzeichen.
Für Wahrheitswerte hat Python die literalen Werte `True` und `False`, dafür sollte man nicht die Zahlen 1 und 0 missbrauchen.
Es gibt einiges an „magischen” Zahlen in dem Programm. Die sollte man durch Konstanten beziehungsweise Rechnungen ersetzen, wenn sich der Wert aus den Konstanten ableiten lässt.
Kommentare sollen dem Leser einen Mehrwert vermitteln, den er alleine durch den Quelltext nicht hat. ``#Flip`` oder ``#Delay`` direkt vor dem Aufruf einer gleichnamigen Funktion bringt keinen Mehrwert.
Klassen sollten wenn sie nicht von einer spezifischeren Basisklasse abgeleitet werden, explizit von `object` erben, damit es „new style”-Klassen werden.
Bei den Klassen könnte man einiges an Quelltext durch sinvolle Vererbung sparen. Eine generischere Klasse für animierte, bewegliche Grafikobjekte würde auch Sinn machen. Und die Verwendung der `Sprite`-Klassen von `pygame`, die für bewegliche Grafikobjekte gedacht sind. Die `state`-Attribute als Zahlen könnte man sich auch an einigen Stellen sparen in dem man nicht die Indirektion über Zahlen und ``if``-Abfragen macht, sondern dort gleich mit den passenden Objekten arbeitet. In der Behandlung der `state`\s ist auch viel unnötige Quelltextwiederholung. So etwas ist ein natürlicher Feind von Programmierern — das vermeidet man wo es nur geht.
Die beiden `gen*()`-Funktionen sollten keine Liste übergeben bekommen, sondern eine Liste mit den generierten Objekten zurück geben. Beziehungsweise sollte man sich an der Stelle mal mit Sprite-Gruppen von `pygame` beschäftigen. Bei der Positionsberechnung dort sind schon wieder magische Zahlen im Spiel, die man besser von der tatsächlichen Grösse der Bilder ableiten sollte. Die Vergleiche auf `i` sind auch unpythonisch. Da würde man eher die Daten die zu jedem `i`-Wert gehören in eine Liste packen und dann mit der `enumerate()`-Funktion über die `i`\s und die Werte iterieren.
`displayMenu()` und `gameOver()` teilen sich gemeinsamen Code.
`startGame()` ist deutlich zu lang und zu komplex. Es ist auch wieder zu viel Code nahezu identisch in verschiedenen Zweigen den man heraus ziehen und nur einmal schreiben sollte.
Eine ``for``-Schleife um Elemente einer Liste zu zählen ist hoffentlich nicht ernst gemeint.
Es kann passieren, dass ein Ufo erzeugt wird, während bereits eines auf dem Bildschirm ist.
Objekte aus Listen zu entfernen über die man gerade iteriert ist keine gute Idee. Das funktioniert nicht immer so wie man das gerne hätte.
Die Indirektion von `moving` und `direction` von Zeichenketten zu Bewegungsdaten ist unnötig umständlich.