import pygame from random import randint OBJ_OVER = "GameOver" OBJ_BALL = "Ball" OBJ_PADDLE = "Paddle" OBJ_SCORE = "Score" ############################################################################### class GameObject(): """ Oberklasse für alle Objekte im Spiel Jedes Objekt sollte sich selbst aktualisieren und darstellen können """ def update(self, game_objects): pass def draw(self, window): pass ############################################################################### class Window(GameObject): """ Das eigentliche Fenster für das Spiel Stellt den schwarzen Hintergrund dar und wird daher als erstes gezeichnet Steuert auch die Spielgeschwindigkeit """ def __init__(self): self.width = 640 self.height = 480 self.title = "Pong" pygame.init() pygame.display.set_caption(self.title) self.size = (self.width, self.height) self.screen = pygame.display.set_mode(self.size) self.clock = pygame.time.Clock() def update(self, game_objects): self.clock.tick(50) def draw(self, window=None): black = (0, 0, 0) self.screen.fill(black) ############################################################################### class GameOverLabel(GameObject): """ Boolsches "Objekt", das festhält, ob das Spiel verloren wurde Stellt in diesem Fall die Game Over Schrift bereit """ def __init__(self, window): font = pygame.font.Font(None, 36) self.image = font.render('Game Over', 1, (255, 255, 255)) self.rect = self.image.get_rect(centerx=window.width // 2, centery=window.height // 2) self.is_over = False def draw(self, window): if self.is_over: window.screen.blit(self.image, self.rect) ############################################################################### class BouncingBall(GameObject): """ Das wandernde Ohm-Zeichen Abprallen wird im Rahmen der Aktualisierung berechnet Darstellung nur, wenn nicht gerade "Game Over angezeigt wird" """ def __init__(self, window): self.size = [window.width, window.height] self.object_image = pygame.image.load('ohm.png') self.object_size = (50, 50) self.object_position = [window.width / 2 - self.object_size[0] / 2, window.height /2 - self.object_size[1]] # self.object_speed = [randint(1,7), randint(1,7)] self.object_speed = [5,5] self.rect = pygame.Rect(self.object_position[0], self.object_position[1], self.object_size[0], self.object_size[1]) def update(self, game_objects): if game_objects[OBJ_OVER].is_over: return for dim in [0, 1]: # Bewegung des Objekts self.object_position[dim] += self.object_speed[dim] # Bouncing? if self.object_position[dim] < 0: self.object_speed[dim] *= -1 end = self.object_position[dim] + self.object_size[dim] if end > self.size[dim]: self.object_speed[dim] *= -1 if self.object_position[1] + self.object_size[1] > self.size[1]: game_objects[OBJ_OVER].is_over = True ## rect aktualisieren, damit die Kollision stimmt ## self.rect.x = self.object_position[0] self.rect.y = self.object_position[1] ## Bouncing bei Schlägertreff ## paddle = game_objects[OBJ_PADDLE] if self.rect.colliderect(paddle.rect): self.object_speed[1] *= -1 def draw(self, window): window.screen.blit(self.object_image, self.object_position) ############################################################################### class Paddle(GameObject): """ Der Schläger Darstellung nur, wenn nicht gerade "Game Over angezeigt wird" """ def __init__(self, window): self.width = 100 self.height = 10 x = window.width // 2 - self.width // 2 y = window.height - 2 * self.height self.rect = pygame.Rect(x, y, self.width, self.height) self.color = (255, 0, 0) # rot self.speed = 10 self.dx = 0 self.dy = 0 def update(self, game_objects): self.rect.x += self.dx self.rect.y += self.dy def draw(self, window): pygame.draw.rect(window.screen, self.color, self.rect) ############################################################################### class Score(GameObject): def __init__(self, window): self.window = window self.score = 0 def increment(self, game_objects): self.score += 100 def draw(self, window): pass def main(): """ Main-Funktion mit Game-Loop Hostet die beiden zentralen Variablen "window" und "game_objects" """ window = Window() game_objects = dict() init(window, game_objects) running = True while running: running = user_input(window, game_objects) update(window, game_objects) draw(window, game_objects) def init(window : Window, game_objects): """ Anlegen aller Objekte des Spiels """ game_objects[OBJ_OVER] = GameOverLabel(window) game_objects[OBJ_BALL] = BouncingBall(window) game_objects[OBJ_PADDLE] = Paddle(window) def user_input(window, game_objects): """ Abarbeiten aller Events :return: False, falls das Spiel beendet wird, sonst True """ def process_event(): """ Verarbeitung eines Events """ if event.type == pygame.QUIT: return False if event.type == pygame.KEYDOWN: if event.key == pygame.K_ESCAPE: return False if event.key == pygame.K_SPACE and game_objects[OBJ_OVER].is_over: init(window, game_objects) if event.key == pygame.K_LEFT: game_objects[OBJ_PADDLE].dx -= game_objects[OBJ_PADDLE].speed if event.key == pygame.K_RIGHT: game_objects[OBJ_PADDLE].dx += game_objects[OBJ_PADDLE].speed if event.type == pygame.KEYUP: if event.key == pygame.K_LEFT: game_objects[OBJ_PADDLE].dx += game_objects[OBJ_PADDLE].speed if event.key == pygame.K_RIGHT: game_objects[OBJ_PADDLE].dx -= game_objects[OBJ_PADDLE].speed return True result = True for event in pygame.event.get(): result = result and process_event() return result def update(window, game_objects): """ Aktualisierung aller Objekt """ window.update(game_objects) for o in game_objects.values(): o.update(game_objects) def draw(window, game_objects): """ Zeichnen aller Objekte """ window.draw() for o in game_objects.values(): o.draw(window) pygame.display.flip() if __name__ == "__main__": main()