@kwon: Das ist auch an der neuen Stelle falsch eingerückt, weil jetzt pro Ereignis ein `update()` stattfindet — also auch wenn es gar kein Mausereignis ist. Und noch schlimmer: die Anzeige wird pro Ereignis neu gezeichnet, was auf der einen Seite das `clock`-Objekt ”aushebelt” und auf der anderen Seite die GUI nicht aktualisiert wenn keine Ereignisse kommen. Was zu Darstellungsproblemen/Fehlern führen kann wenn man beispielsweise ein anderes Fenster vor/über das Pygame-Fenster bewegt, weil dabei eventuell zerstörte Teile der Anzeige eventuell nicht neu gezeichnet/repariert werden.
Weitere Anmerkungen zum Quelltext:
Auf Modulebene sollte nur Code stehen der Konstanten, Funktionen, und Klassen definiert. Das Hauptprogramm steht üblicherweise in einer Funktion die `main()` heisst.
Konstanten werden per Konvention KOMPLETT_GROSS geschrieben.
Das `pygame.quit()` könnte man mit ``try``/``finally`` ein bisschen besser garantieren.
`background` wird definiert, aber nirgends verwendet.
Ich vermute mal ganz stark, dass `Paddel` eigentlich `Paddle` heissen soll.
Die Attribute `width` und `height` sind in `Paddle` redundant, weil diese Informationen bereits in `rect` stecken.
Im `Paddle` auf das Display-Surface zuzugreifen ist nicht gut. Das Paddle sollte nicht selbst ermitteln wo es dargestellt wird, denn so verbaut man sich Möglichkeiten. Beispielsweise eine Begrenzung um das Spielfeld oder andere Anzeigen wie Punktestand, ein Logo, und so weiter. Also braucht mindestens die `__init__()`- und vielleicht auch die `update()`-Methode mindestens ein `Rect`-Objekt als Argument in welchen Grenzen es sich bewegen kann/darf.
Man muss bei `Rect`-Objekten auch weniger eigene Rechnungen mit der Höhe und der Breite anstellen und bekommt damit auch leichter lesbaren Code. Um beispielsweise die Unterseite eines `Rect` an der Unterseite eines anderen auszurichten, muss man nicht selbst die `y`-Position anhand der Höhe ausrechenen, sondern kann direkt schreiben was man will: ``paddle_rect.bottom = playfield_rect.bottom``. Und man muss auch keine Höhe oder Breite durch 2 teilen, weil es `center`, `centerx`, `centery`, `mitbottom`, `midleft`, `midright`, und `midtop` als Attribute auf `Rect`-Objekten gibt. Und um die Position eines `Rect`-Objektes komplett in ein anderes zu verschieben, sollte es ausserhalb liegen, gibt es die `clamp()`-Methode.
Auch das `Paddle`-Objekte die Mausposition selbst abfragen ist unsauber. Die sollte beim `update()` übergeben werden, und auch nur wenn ein Mausereignis verarbeitet wird. Eventuell sogar auch erst nachdem alle Ereignisse abgearbeitet werden, damit man sich `update()`-Aufrufe spart, die sowieso nicht gezeichnet werden.
Zwischenstand:
Code: Alles auswählen
#!/usr/bin/env python3
import pygame
BLUE = (0, 0, 255)
WHITE = (255, 255, 255)
class Paddle(pygame.sprite.Sprite):
def __init__(self, playfield_rect):
pygame.sprite.Sprite.__init__(self)
self.playfield_rect = playfield_rect
self.image = pygame.Surface((80, 15))
self.image.fill(BLUE)
self.rect = self.image.get_rect()
self.rect.bottom = self.playfield_rect.bottom
def update(self, position):
x, _ = position
self.rect.centerx = x
self.rect = self.rect.clamp(self.playfield_rect)
def main():
pygame.init()
try:
screen = pygame.display.set_mode((800, 600))
pygame.mouse.set_visible(1)
all_sprites = pygame.sprite.Group()
paddle = Paddle(screen.get_rect())
all_sprites.add(paddle)
clock = pygame.time.Clock()
while True:
clock.tick(30)
screen.fill(WHITE)
for event in pygame.event.get():
if event.type == pygame.QUIT:
return
elif event.type == pygame.MOUSEMOTION:
paddle.update(event.pos)
all_sprites.draw(screen)
pygame.display.flip()
finally:
pygame.quit()
if __name__ == "__main__":
main()